### Getting Started/Aster Api Wallet # Aster DEX API Wallet Setup Guide This guide explains how to create and configure an API Wallet for secure trading on Aster DEX. ## Why Use API Wallet? - ✅ **Binance-compatible API**: Easy migration from Binance - ✅ **Separate Trading Wallet**: Enhanced security - ✅ **Revocable Access**: Can be disabled anytime - ✅ **Lower Fees**: Competitive trading fees ## Prerequisites - A Web3 wallet (MetaMask, WalletConnect, etc.) - Funds on supported EVM chain (Ethereum, BSC, Polygon, etc.) ## Step 1: Register on Aster DEX 1. Visit [Aster DEX](https://www.asterdex.com/en/referral/fdfc0e) (use referral link for fee discount) 2. Connect your Web3 wallet 3. Complete any required verification ## Step 2: Create API Wallet 1. Go to [Aster API Wallet](https://www.asterdex.com/en/api-wallet) 2. Connect your main wallet 3. Click **Create API Wallet** 4. Approve the transaction in your wallet ## Step 3: Save API Wallet Credentials After creation, save these **immediately**: | Field | Description | |-------|-------------| | **User Address** | Your main wallet address | | **Signer Address** | API wallet address | | **Private Key** | API wallet private key | ⚠️ **Important**: The private key is only shown once! Save it securely. ## Step 4: Configure in NOFX Add your API wallet through the NOFX web interface: 1. Open NOFX dashboard (http://localhost:3000) 2. Go to **Exchange Configuration** 3. Enable **Aster DEX** 4. Enter: - **User**: Your main wallet address (with `0x`) - **Signer**: API wallet address (with `0x`) - **Private Key**: API wallet private key (remove `0x` prefix) 5. Save configuration ## Configuration Example ``` User: 0xYOUR_MAIN_WALLET_ADDRESS Signer: 0xYOUR_API_WALLET_SIGNER_ADDRESS Private Key: your_api_wallet_private_key_without_0x ``` ## Fund Your Account 1. Deposit supported assets to Aster DEX 2. Transfer to your trading account 3. API wallet will trade using these funds ## Managing Your API Wallet ### Revoke Access 1. Go to [Aster API Wallet](https://www.asterdex.com/en/api-wallet) 2. Find your API wallet 3. Click **Revoke** or **Delete** ### Create New API Wallet You can create multiple API wallets: - Delete old wallet first (recommended) - Or create additional wallet for different purposes ## Security Best Practices - Never share your API wallet private key - Store credentials in a secure password manager - Revoke access when not in use - Use separate wallets for different applications - Monitor API wallet activity regularly ## Troubleshooting | Issue | Solution | |-------|----------| | Authentication failed | Verify User, Signer, and Private Key are correct | | Invalid signature | Ensure private key doesn't have `0x` prefix | | Insufficient balance | Deposit funds to Aster DEX | | API wallet not found | Create new API wallet at asterdex.com | ## Supported Chains Aster DEX supports multiple EVM chains: - Ethereum Mainnet - BNB Smart Chain (BSC) - Polygon - And more... Select your preferred chain when depositing funds. --- ### Getting Started/Binance Api # Binance API Setup Guide This guide explains how to create and configure Binance API keys for use with NOFX. ## Create API Key 1. Log in to your [Binance account](https://www.binance.com) 2. Go to **Account** → **API Management** 3. Click **Create API** 4. Select **System Generated** API key type 5. Complete 2FA verification 6. Name your API key (e.g., "NOFX Trading") ## Configure API Permissions Enable the following permissions: - ✅ **Enable Reading** - Required - ✅ **Enable Futures** - Required for trading - ❌ **Enable Withdrawals** - Keep disabled for security ## IP Whitelist (Recommended) For enhanced security: 1. Click **Edit restrictions** 2. Select **Restrict access to trusted IPs only** 3. Add your server's IP address 4. Save changes ## Save Your Keys After creation, you'll see: - **API Key**: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` - **Secret Key**: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` ⚠️ **Important**: Save the Secret Key immediately - it's only shown once! ## Configure in NOFX Add your API credentials through the NOFX web interface: 1. Open NOFX dashboard (http://localhost:3000) 2. Go to **Exchange Configuration** 3. Enable **Binance** 4. Enter your API Key and Secret Key 5. Save configuration ## Troubleshooting | Error | Solution | |-------|----------| | `Invalid API-key` | Check if API key is correct | | `Signature verification failed` | Check if Secret key is correct | | `IP not whitelisted` | Add your IP to whitelist or disable IP restriction | | `Futures not enabled` | Enable Futures permission in API settings | ## Security Best Practices - Never share your API keys - Use IP whitelisting - Don't enable withdrawal permissions - Create separate API keys for different applications - Regularly rotate your API keys --- ### Getting Started/Bybit Api # Bybit API Setup Guide This guide explains how to create and configure Bybit API keys for use with NOFX. ## Create API Key 1. Log in to your [Bybit account](https://partner.bybit.com/b/83856) 2. Go to **Account & Security** → **API Management** 3. Click **Create New Key** 4. Select **System-generated API Keys** 5. Complete 2FA verification 6. Name your API key (e.g., "NOFX Trading") ## Configure API Permissions Enable the following permissions: - ✅ **Read-Write** - Required for trading - ✅ **Contract** - Required for futures/perpetual trading - ❌ **Withdrawals** - Keep disabled for security ## IP Whitelist (Recommended) For enhanced security: 1. Click **Edit** on your API key 2. Add your server's IP address to the whitelist 3. Save changes ## Save Your Keys After creation, you'll see: - **API Key**: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` - **API Secret**: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` ⚠️ **Important**: Save the API Secret immediately - it's only shown once! ## Configure in NOFX Add your API credentials through the NOFX web interface: 1. Open NOFX dashboard (http://localhost:3000) 2. Go to **Exchange Configuration** 3. Enable **Bybit** 4. Enter your API Key and API Secret 5. Save configuration ## Troubleshooting | Error | Solution | |-------|----------| | `Invalid API key` | Check if API key is correct | | `Signature error` | Check if API Secret is correct | | `IP not allowed` | Add your IP to whitelist | | `Permission denied` | Enable Contract trading permission | ## Security Best Practices - Never share your API keys - Use IP whitelisting - Don't enable withdrawal permissions - Create separate API keys for different applications - Regularly rotate your API keys --- ### Getting Started/Custom Api.En # Custom AI API Usage Guide ## Features NOFX now supports using any OpenAI-compatible API format, including: - OpenAI official API (gpt-4o, gpt-4-turbo, etc.) - OpenRouter (access to multiple models) - Locally deployed models (Ollama, LM Studio, etc.) - Other OpenAI-compatible API services ## Configuration Method ~~Add trader using custom API in `config.json` (deprecated):~~ *Note: Custom APIs and traders are now configured through the Web interface. config.json only retains basic settings.* ```json { "traders": [ { "id": "trader_custom", "name": "My Custom AI Trader", "ai_model": "custom", "exchange": "binance", "binance_api_key": "your_binance_api_key", "binance_secret_key": "your_binance_secret_key", "custom_api_url": "https://api.openai.com/v1", "custom_api_key": "sk-your-openai-api-key", "custom_model_name": "gpt-4o", "initial_balance": 1000, "scan_interval_minutes": 3 } ] } ``` ## Configuration Fields | Field | Type | Required | Description | |-------|------|----------|-------------| | `ai_model` | string | ✅ | Set to `"custom"` to enable custom API | | `custom_api_url` | string | ✅ | API Base URL (without `/chat/completions`). Special usage: If ending with `#`, use full URL (no auto path append) | | `custom_api_key` | string | ✅ | API key | | `custom_model_name` | string | ✅ | Model name (e.g. `gpt-4o`, `claude-3-5-sonnet`, etc.) | ## Usage Examples ### 1. OpenAI Official API ```json { "ai_model": "custom", "custom_api_url": "https://api.openai.com/v1", "custom_api_key": "sk-proj-xxxxx", "custom_model_name": "gpt-4o" } ``` ### 2. OpenRouter ```json { "ai_model": "custom", "custom_api_url": "https://openrouter.ai/api/v1", "custom_api_key": "sk-or-xxxxx", "custom_model_name": "anthropic/claude-3.5-sonnet" } ``` ### 3. Local Ollama ```json { "ai_model": "custom", "custom_api_url": "http://localhost:11434/v1", "custom_api_key": "ollama", "custom_model_name": "llama3.1:70b" } ``` ### 4. Azure OpenAI ```json { "ai_model": "custom", "custom_api_url": "https://your-resource.openai.azure.com/openai/deployments/your-deployment", "custom_api_key": "your-azure-api-key", "custom_model_name": "gpt-4" } ``` ### 5. Using Full Custom Path (append #) For certain special API endpoints that already include the full path (including `/chat/completions` or other custom paths), you can append `#` at the end of the URL to force using the full URL: ```json { "ai_model": "custom", "custom_api_url": "https://api.example.com/v2/ai/chat/completions#", "custom_api_key": "your-api-key", "custom_model_name": "custom-model" } ``` **Note**: The `#` will be automatically removed, and the actual request will be sent to `https://api.example.com/v2/ai/chat/completions` ## Compatibility Requirements Custom APIs must: 1. Support OpenAI Chat Completions format 2. Accept `POST` requests to `/chat/completions` endpoint (or append `#` at URL end for custom path) 3. Support `Authorization: Bearer {api_key}` authentication 4. Return standard OpenAI response format ## Important Notes 1. **URL Format**: `custom_api_url` should be the Base URL, system will auto-append `/chat/completions` - ✅ Correct: `https://api.openai.com/v1` - ❌ Wrong: `https://api.openai.com/v1/chat/completions` - 🔧 **Special usage**: If you need to use a full custom path (without auto-appending `/chat/completions`), append `#` at the URL end - Example: `https://api.example.com/custom/path/chat/completions#` - System will automatically remove `#` and use the full URL directly 2. **Model Name**: Ensure `custom_model_name` exactly matches the model name supported by your API provider 3. **API Key**: Some locally deployed models may not require a real API key, you can fill in any string 4. **Timeout Settings**: Default timeout is 120 seconds, may need adjustment if model response is slow ## Multi-AI Comparison Trading You can configure multiple traders with different AIs for comparison: ```json { "traders": [ { "id": "deepseek_trader", "ai_model": "deepseek", "deepseek_key": "sk-xxxxx", ... }, { "id": "gpt4_trader", "ai_model": "custom", "custom_api_url": "https://api.openai.com/v1", "custom_api_key": "sk-xxxxx", "custom_model_name": "gpt-4o", ... }, { "id": "claude_trader", "ai_model": "custom", "custom_api_url": "https://openrouter.ai/api/v1", "custom_api_key": "sk-or-xxxxx", "custom_model_name": "anthropic/claude-3.5-sonnet", ... } ] } ``` ## Troubleshooting ### Issue: Configuration Validation Failed **Error Message**: `使用自定义API时必须配置custom_api_url` (custom_api_url must be configured when using custom API) **Solution**: After setting `ai_model: "custom"`, ensure you also configure: - `custom_api_url` - `custom_api_key` - `custom_model_name` ### Issue: API Call Failed **Possible Causes**: 1. URL format error - Normal usage: Should not include `/chat/completions` (system will auto-append) - Special usage: If full path is needed, remember to append `#` at URL end 2. Invalid API key 3. Incorrect model name 4. Network connection issues **Debug Method**: Check error messages in logs, usually includes HTTP status code and error details ## Backward Compatibility Existing `deepseek` and `qwen` configurations are unaffected and can continue to be used: ```json { "ai_model": "deepseek", "deepseek_key": "sk-xxxxx" } ``` Or ```json { "ai_model": "qwen", "qwen_key": "sk-xxxxx" } ``` --- ### Getting Started/Custom Api # 自定义 AI API 使用指南 ## 功能说明 现在 NOFX 支持使用任何 OpenAI 格式兼容的 API,包括: - OpenAI 官方 API (gpt-4o, gpt-4-turbo 等) - OpenRouter (可访问多种模型) - 本地部署的模型 (Ollama, LM Studio 等) - 其他兼容 OpenAI 格式的 API 服务 ## 配置方式 在 `config.json` 中添加使用自定义 API 的 trader(~~已弃用~~): *注意:现在通过Web界面配置自定义API和交易员,config.json仅保留基础设置* ```json { "traders": [ { "id": "trader_custom", "name": "My Custom AI Trader", "ai_model": "custom", "exchange": "binance", "binance_api_key": "your_binance_api_key", "binance_secret_key": "your_binance_secret_key", "custom_api_url": "https://api.openai.com/v1", "custom_api_key": "sk-your-openai-api-key", "custom_model_name": "gpt-4o", "initial_balance": 1000, "scan_interval_minutes": 3 } ] } ``` ## 配置字段说明 | 字段 | 类型 | 必需 | 说明 | |-----|------|------|------| | `ai_model` | string | ✅ | 设置为 `"custom"` 启用自定义 API | | `custom_api_url` | string | ✅ | API 的 Base URL (不含 `/chat/completions`)。特殊用法:如果以 `#` 结尾,则使用完整 URL(不自动添加路径) | | `custom_api_key` | string | ✅ | API 密钥 | | `custom_model_name` | string | ✅ | 模型名称 (如 `gpt-4o`, `claude-3-5-sonnet` 等) | ## 使用示例 ### 1. OpenAI 官方 API ```json { "ai_model": "custom", "custom_api_url": "https://api.openai.com/v1", "custom_api_key": "sk-proj-xxxxx", "custom_model_name": "gpt-4o" } ``` ### 2. OpenRouter ```json { "ai_model": "custom", "custom_api_url": "https://openrouter.ai/api/v1", "custom_api_key": "sk-or-xxxxx", "custom_model_name": "anthropic/claude-3.5-sonnet" } ``` ### 3. 本地 Ollama ```json { "ai_model": "custom", "custom_api_url": "http://localhost:11434/v1", "custom_api_key": "ollama", "custom_model_name": "llama3.1:70b" } ``` ### 4. Azure OpenAI ```json { "ai_model": "custom", "custom_api_url": "https://your-resource.openai.azure.com/openai/deployments/your-deployment", "custom_api_key": "your-azure-api-key", "custom_model_name": "gpt-4" } ``` ### 5. 使用完整自定义路径(末尾添加 #) 对于某些特殊的 API 端点,如果已经包含完整路径(包括 `/chat/completions` 或其他自定义路径),可以在 URL 末尾添加 `#` 来强制使用完整 URL: ```json { "ai_model": "custom", "custom_api_url": "https://api.example.com/v2/ai/chat/completions#", "custom_api_key": "your-api-key", "custom_model_name": "custom-model" } ``` **注意**:`#` 会被自动去除,实际请求会发送到 `https://api.example.com/v2/ai/chat/completions` ## 兼容性要求 自定义 API 必须: 1. 支持 OpenAI Chat Completions 格式 2. 接受 `POST` 请求到 `/chat/completions` 端点(或在 URL 末尾添加 `#` 以使用自定义路径) 3. 支持 `Authorization: Bearer {api_key}` 认证 4. 返回标准的 OpenAI 响应格式 ## 注意事项 1. **URL 格式**:`custom_api_url` 应该是 Base URL,系统会自动添加 `/chat/completions` - ✅ 正确:`https://api.openai.com/v1` - ❌ 错误:`https://api.openai.com/v1/chat/completions` - 🔧 **特殊用法**:如果需要使用完整的自定义路径(不自动添加 `/chat/completions`),可以在 URL 末尾添加 `#` - 例如:`https://api.example.com/custom/path/chat/completions#` - 系统会自动去掉 `#` 并直接使用该完整 URL 2. **模型名称**:确保 `custom_model_name` 与 API 提供商支持的模型名称完全一致 3. **API 密钥**:某些本地部署的模型可能不需要真实的 API 密钥,可以填写任意字符串 4. **超时设置**:默认超时时间为 120 秒,如果模型响应较慢可能需要调整 ## 多 AI 对比交易 你可以同时配置多个不同 AI 的 trader 进行对比: ```json { "traders": [ { "id": "deepseek_trader", "ai_model": "deepseek", "deepseek_key": "sk-xxxxx", ... }, { "id": "gpt4_trader", "ai_model": "custom", "custom_api_url": "https://api.openai.com/v1", "custom_api_key": "sk-xxxxx", "custom_model_name": "gpt-4o", ... }, { "id": "claude_trader", "ai_model": "custom", "custom_api_url": "https://openrouter.ai/api/v1", "custom_api_key": "sk-or-xxxxx", "custom_model_name": "anthropic/claude-3.5-sonnet", ... } ] } ``` ## 故障排除 ### 问题:配置验证失败 **错误信息**:`使用自定义API时必须配置custom_api_url` **解决方案**:确保设置了 `ai_model: "custom"` 后,同时配置了: - `custom_api_url` - `custom_api_key` - `custom_model_name` ### 问题:API 调用失败 **可能原因**: 1. URL 格式错误 - 普通用法:不应包含 `/chat/completions`(系统会自动添加) - 特殊用法:如果需要完整路径,记得在 URL 末尾添加 `#` 2. API 密钥无效 3. 模型名称错误 4. 网络连接问题 **调试方法**:查看日志中的错误信息,通常会包含 HTTP 状态码和错误详情 ## 向后兼容性 现有的 `deepseek` 和 `qwen` 配置完全不受影响,可以继续使用: ```json { "ai_model": "deepseek", "deepseek_key": "sk-xxxxx" } ``` 或 ```json { "ai_model": "qwen", "qwen_key": "sk-xxxxx" } ``` --- ### Getting Started/Hyperliquid Agent Wallet # Hyperliquid Agent Wallet Setup Guide This guide explains how to create and configure an Agent Wallet for secure trading on Hyperliquid. ## Why Use Agent Wallet? - ✅ **More Secure**: Never expose your main wallet private key - ✅ **Limited Access**: Agent only has trading permissions - ✅ **Revocable**: Can be disabled anytime from Hyperliquid interface - ✅ **Separate Funds**: Keep main holdings safe ## Prerequisites - A wallet with funds on Hyperliquid - Access to [Hyperliquid](https://app.hyperliquid.xyz/join/AITRADING) ## Step 1: Connect Your Main Wallet 1. Visit [Hyperliquid](https://app.hyperliquid.xyz/join/AITRADING) 2. Click **Connect Wallet** (top right) 3. Choose MetaMask, WalletConnect, or other Web3 wallet 4. Approve the connection ## Step 2: Create Agent Wallet 1. Click on your wallet address (top right) 2. Go to **Settings** → **API & Agents** 3. Or visit directly: [https://app.hyperliquid.xyz/agents](https://app.hyperliquid.xyz/agents) 4. Click **Create Agent** or **Add Agent** 5. System generates a new agent wallet automatically ## Step 3: Save Agent Credentials After creation, save these immediately: - **Agent Wallet Address**: `0x...` (starts with 0x) - **Agent Private Key**: Shown only once! ⚠️ **Important**: The private key is only displayed once. Save it securely! ## Step 4: Configure in NOFX Add your agent wallet through the NOFX web interface: 1. Open NOFX dashboard (http://localhost:3000) 2. Go to **Exchange Configuration** 3. Enable **Hyperliquid** 4. Enter: - **Wallet Address**: Your main wallet address (with `0x`) - **Private Key**: Agent private key (remove `0x` prefix) 5. Save configuration ## Agent Wallet Details | Field | Description | Example | |-------|-------------|---------| | Main Wallet | Your connected wallet (holds funds) | `0xABC123...` | | Agent Wallet | Sub-wallet for trading | `0xDEF456...` | | Private Key | Only needed for NOFX | `abc123...` (no 0x) | ## Managing Your Agent ### Revoke Agent Access 1. Go to [Hyperliquid Agents](https://app.hyperliquid.xyz/agents) 2. Find your agent in the list 3. Click **Revoke** or **Delete** ### Create Multiple Agents You can create multiple agents for different purposes: - One for NOFX - One for other trading bots - One for manual API access ## Security Best Practices - Use agent wallet instead of main wallet private key - Store agent private key securely - Revoke unused agents - Monitor agent activity regularly - Keep main wallet funds separate from trading funds ## Troubleshooting | Issue | Solution | |-------|----------| | Agent not working | Check if agent is still active in Hyperliquid settings | | Invalid signature | Ensure private key doesn't have `0x` prefix | | Insufficient funds | Transfer funds to your Hyperliquid account | | Connection error | Check network (mainnet vs testnet) setting | --- ### Getting Started/Lighter Agent Wallet # Lighter Agent Wallet Setup Guide This guide explains how to create and configure an Agent Wallet for secure trading on Lighter. ## Why Use Agent Wallet? - ✅ **More Secure**: Never expose your main wallet private key - ✅ **Limited Access**: Agent only has trading permissions - ✅ **Revocable**: Can be disabled anytime - ✅ **Separate Funds**: Keep main holdings safe ## Prerequisites - A Web3 wallet (MetaMask, WalletConnect, etc.) - Access to [Lighter](https://lighter.xyz) ## Step 1: Connect Your Main Wallet 1. Visit [Lighter](https://lighter.xyz) 2. Click **Connect Wallet** 3. Choose MetaMask, WalletConnect, or other Web3 wallet 4. Approve the connection ## Step 2: Create Agent Wallet 1. Navigate to **Settings** or **API** section 2. Look for **Agent Wallet** or **Trading Wallet** option 3. Click **Create Agent** or **Generate New Wallet** 4. Approve the transaction if required ## Step 3: Save Agent Credentials After creation, save these immediately: | Field | Description | |-------|-------------| | **Main Wallet Address** | Your connected wallet address | | **Agent Wallet Address** | Generated agent wallet address | | **Agent Private Key** | Private key for the agent wallet | ⚠️ **Important**: The private key is only shown once! Save it securely. ## Step 4: Configure in NOFX Add your agent wallet through the NOFX web interface: 1. Open NOFX dashboard (http://localhost:3000) 2. Go to **Exchange Configuration** 3. Enable **Lighter** 4. Enter: - **Wallet Address**: Your main wallet address (with `0x`) - **Private Key**: Agent private key (remove `0x` prefix) 5. Save configuration ## Managing Your Agent ### Revoke Agent Access 1. Go to Lighter Settings 2. Find your agent in the list 3. Click **Revoke** or **Delete** ### Fund Your Account 1. Deposit supported assets to Lighter 2. Agent wallet will trade using deposited funds ## Security Best Practices - Use agent wallet instead of main wallet private key - Store agent private key securely - Revoke unused agents - Monitor agent activity regularly - Keep main wallet funds separate from trading funds ## Troubleshooting | Issue | Solution | |-------|----------| | Agent not working | Check if agent is still active | | Invalid signature | Ensure private key doesn't have `0x` prefix | | Insufficient funds | Deposit funds to your Lighter account | | Connection error | Check network settings | --- ### Getting Started/Okx Api # OKX API Setup Guide This guide explains how to create and configure OKX API keys for use with NOFX. ## Create API Key 1. Log in to your [OKX account](https://www.okx.com/join/1865360) 2. Go to **Account** → **API** 3. Click **Create API Key** 4. Select **Trade** as the purpose 5. Complete 2FA verification 6. Name your API key (e.g., "NOFX Trading") ## Configure API Permissions Enable the following permissions: - ✅ **Read** - Required - ✅ **Trade** - Required for trading - ❌ **Withdraw** - Keep disabled for security ## Passphrase OKX requires a passphrase in addition to API Key and Secret: 1. Create a strong passphrase during API creation 2. Save it securely - you'll need it for configuration ## IP Whitelist (Recommended) For enhanced security: 1. Click **Edit** on your API key 2. Enable **IP Whitelist** 3. Add your server's IP address 4. Save changes ## Save Your Keys After creation, you'll have: - **API Key**: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` - **Secret Key**: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` - **Passphrase**: Your created passphrase ⚠️ **Important**: Save the Secret Key immediately - it's only shown once! ## Configure in NOFX Add your API credentials through the NOFX web interface: 1. Open NOFX dashboard (http://localhost:3000) 2. Go to **Exchange Configuration** 3. Enable **OKX** 4. Enter: - **API Key** - **Secret Key** - **Passphrase** 5. Save configuration ## Troubleshooting | Error | Solution | |-------|----------| | `Invalid API key` | Check if API key is correct | | `Invalid signature` | Check if Secret key and Passphrase are correct | | `IP not whitelisted` | Add your IP to whitelist or disable IP restriction | | `Permission denied` | Enable Trade permission in API settings | ## Security Best Practices - Never share your API keys or passphrase - Use IP whitelisting - Don't enable withdrawal permissions - Create separate API keys for different applications - Regularly rotate your API keys --- ### Getting Started/README # 🚀 Getting Started with NOFX **Language:** [English](README.md) | [中文](README.zh-CN.md) This section contains all the documentation you need to get NOFX up and running. ## 📋 Deployment Options Choose the method that best fits your needs: ### 🐳 Docker Deployment (Recommended) **Best for:** Beginners, quick setup, production deployments - **English:** [docker-deploy.en.md](docker-deploy.en.md) - **中文:** [docker-deploy.zh-CN.md](docker-deploy.zh-CN.md) **Pros:** - ✅ One-command setup - ✅ All dependencies included - ✅ Easy to update and manage - ✅ Isolated environment **Quick Start:** ```bash cp config.json.example config.json ./scripts/start.sh start --build ``` --- ## 🤖 AI Configuration ### Custom AI Providers - **English:** [custom-api.en.md](custom-api.en.md) - **中文:** [custom-api.md](custom-api.md) Use custom AI models or third-party OpenAI-compatible APIs: - Custom DeepSeek endpoints - Self-hosted models - Other LLM providers --- ## 🔑 Prerequisites Before starting, ensure you have: ### For Docker Method: - ✅ Docker 20.10+ - ✅ Docker Compose V2 ### For Manual Method: - ✅ Go 1.21+ - ✅ Node.js 18+ - ✅ TA-Lib library --- ## 📚 Next Steps After deployment: 1. **Configure AI Models** → Web interface at http://localhost:3000 2. **Set Up Exchange** → Add Binance/Hyperliquid credentials 3. **Create Traders** → Combine AI models with exchanges 4. **Start Trading** → Monitor performance in dashboard ### 🔐 Optional: Enable Admin Mode (Single-User) For single-tenant/self-hosted usage, you can enable strict admin-only access: 1) In `config.json` set the 2 fields below: ```jsonc { "admin_mode": true, ... "jwt_secret": "YOUR_JWT_SCR" } ``` 2) Set environment variables (Docker compose already wired): - `NOFX_ADMIN_PASSWORD` — admin password (plaintext; hashed on startup) 3) Login at `/login` using the admin password. All non-essential endpoints are blocked to unauthenticated users while admin mode is enabled. --- ## ⚠️ Important Notes **Before Trading:** - ⚠️ Test on testnet first - ⚠️ Start with small amounts - ⚠️ Understand the risks - ⚠️ Read [Security Policy](../../SECURITY.md) **API Keys:** - 🔑 Never commit API keys to git - 🔑 Use environment variables - 🔑 Restrict IP access - 🔑 Enable 2FA on exchanges --- ## 🆘 Troubleshooting **Common Issues:** 1. **Docker build fails** → Check Docker version, update to 20.10+ 2. **TA-Lib not found** → `brew install ta-lib` (macOS) or `apt-get install libta-lib0-dev` (Ubuntu) 3. **Port 8080 in use** → Change `API_PORT` in .env file 4. **Frontend won't connect** → Check backend is running on port 8080 **Need more help?** - 📖 [FAQ](../guides/faq.zh-CN.md) - 💬 [Telegram Community](https://t.me/nofx_dev_community) - 🐛 [GitHub Issues](https://github.com/NoFxAiOS/nofx/issues) --- [← Back to Documentation Home](../README.md) --- ### Getting Started/README.Zh CN # 🚀 NOFX 快速开始 本节包含让 NOFX 运行起来所需的所有文档。 ## 📋 部署选项 选择最适合您的方式: ### 🐳 Docker 部署(推荐) **适合:** 初学者、快速部署、生产环境 - **中文文档:** [docker-deploy.zh-CN.md](docker-deploy.zh-CN.md) - **English:** [docker-deploy.en.md](docker-deploy.en.md) **优势:** - ✅ 一键启动 - ✅ 包含所有依赖 - ✅ 易于更新和管理 - ✅ 隔离环境 **快速开始:** ```bash cp config.json.example config.json ./scripts/start.sh start --build ``` --- ## 🤖 AI 配置 ### 自定义 AI 提供商 - **中文文档:** [custom-api.md](custom-api.md) - **English:** [custom-api.en.md](custom-api.en.md) 使用自定义 AI 模型或第三方 OpenAI 兼容 API: - 自定义 DeepSeek 端点 - 本地部署的模型 - 其他 LLM 提供商 --- ## 🔑 环境要求 开始之前,请确保已安装: ### Docker 方式: - ✅ Docker 20.10+ - ✅ Docker Compose V2 ### 手动部署方式: - ✅ Go 1.21+ - ✅ Node.js 18+ - ✅ TA-Lib 库 --- ## 📚 下一步 部署完成后: 1. **配置 AI 模型** → 访问 Web 界面 http://localhost:3000 2. **设置交易所** → 添加 Binance/Hyperliquid 凭证 3. **创建交易员** → 将 AI 模型与交易所结合 4. **开始交易** → 在仪表板中监控表现 --- ## ⚠️ 重要提示 **交易前:** - ⚠️ 先在测试网测试 - ⚠️ 从小金额开始 - ⚠️ 了解风险 - ⚠️ 阅读[安全策略](../../SECURITY.md) **API 密钥:** - 🔑 永远不要提交 API 密钥到 git - 🔑 使用环境变量 - 🔑 限制 IP 访问 - 🔑 在交易所启用 2FA --- ## 🆘 故障排除 **常见问题:** 1. **Docker 构建失败** → 检查 Docker 版本,更新到 20.10+ 2. **找不到 TA-Lib** → `brew install ta-lib` (macOS) 或 `apt-get install libta-lib0-dev` (Ubuntu) 3. **端口 8080 被占用** → 在 .env 文件中更改 `API_PORT` 4. **前端无法连接** → 检查后端是否在端口 8080 上运行 **需要更多帮助?** - 📖 [常见问题](../guides/faq.zh-CN.md) - 💬 [Telegram 社区](https://t.me/nofx_dev_community) - 🐛 [GitHub Issues](https://github.com/NoFxAiOS/nofx/issues) --- [← 返回文档首页](../README.md) --- ### Community/Bounty Aster # 🚀 [BOUNTY] Integrate Aster Exchange Support ## 💰 Bounty Reward **To be discussed** - Open to proposals from contributors ## 📋 Overview We're looking for contributors to add Aster exchange support to NOFX AI Trading System. Currently supports Binance Futures, seeking to expand to Aster perpetual contracts. ## 🎯 Task Requirements ### Core Features to Implement #### 1. **Aster API Integration** - [ ] Account management (balance, positions, margin) - [ ] Market data fetching (K-lines, order book, trades) - [ ] Order execution (market/limit orders) - [ ] Position management (open, close, modify) - [ ] Websocket real-time data stream (if available) #### 2. **Adapter Layer** - [ ] Create `trader/aster_perpetual.go` adapter - [ ] Implement unified interface compatible with existing `BinanceFuturesClient` - [ ] Handle Aster-specific features (if any) #### 3. **Configuration Support** ```json { "traders": [ { "id": "aster_trader", "name": "Aster AI Trader", "exchange": "aster", // NEW "aster_api_key": "xxx", "aster_secret_key": "xxx", "ai_model": "deepseek", "initial_balance": 1000.0 } ] } ``` #### 4. **Risk Control Adaptation** - [ ] Adapt position limits for Aster specs - [ ] Handle leverage rules (may differ from Binance) - [ ] Implement liquidation price calculation - [ ] Funding rate integration (if applicable) #### 5. **Testing & Documentation** - [ ] Unit tests for API wrapper - [ ] Integration tests with testnet (if available) - [ ] Update README with Aster setup guide - [ ] Add Aster-specific troubleshooting docs ## 📚 Technical References **Aster Resources:** - Official Website: [Add Aster exchange URL] - API Documentation: [Add Aster API docs URL] - SDK/Libraries: [Add if available] **NOFX Architecture:** - See `trader/binance_futures.go` as reference implementation - Main trading logic: `trader/auto_trader.go` - Configuration: `config.json` structure ## 🔧 Implementation Guidelines ### File Structure ``` trader/ ├── binance_futures.go (existing reference) ├── aster_perpetual.go (NEW - to implement) └── exchange_interface.go (NEW - unified interface) config/ └── config.go (UPDATE - add Aster config) ``` ### Interface to Implement ```go type ExchangeClient interface { // Account GetAccount() (*AccountInfo, error) GetPositions() ([]*Position, error) // Market Data GetKlines(symbol, interval string, limit int) ([]*Kline, error) GetTicker(symbol string) (*Ticker, error) // Trading CreateOrder(params *OrderParams) (*Order, error) ClosePosition(symbol, side string) error // Risk Management SetLeverage(symbol string, leverage int) error GetLiquidationPrice(position *Position) (float64, error) } ``` ## ✅ Acceptance Criteria **Minimum Requirements:** - [ ] Can connect to Aster testnet/mainnet - [ ] Fetch real-time account balance and positions - [ ] Execute market orders successfully - [ ] Close positions correctly - [ ] Calculate accurate P/L - [ ] No breaking changes to existing Binance integration **Bonus Points:** - [ ] Websocket streaming for real-time data - [ ] Support for limit orders and stop-loss/take-profit - [ ] Multi-exchange competition mode (Binance vs Aster) - [ ] Performance comparison dashboard ## 📝 How to Contribute 1. **Comment on this issue** to express interest 2. **Fork the repository** and create a feature branch 3. **Implement the integration** following guidelines above 4. **Test thoroughly** on testnet before mainnet 5. **Submit a Pull Request** with: - Code changes - Tests - Documentation updates - Demo video/screenshots ## 🤝 Support & Questions - Ask questions in this issue's comments - Join our Telegram: [NOFX Developer Community](https://t.me/nofx_dev_community) - Reference existing code: `trader/binance_futures.go` ## ⚠️ Important Notes - **Test on testnet first** - Do NOT test with real funds initially - **Maintain backward compatibility** - Existing Binance users should not be affected - **Code quality** - Follow existing code style and patterns - **Security** - Handle API keys securely, no hardcoded credentials ## 🔍 Research Needed **Before starting, please investigate:** - [ ] Does Aster provide a public API? (REST/Websocket) - [ ] Is there an official SDK or code examples? - [ ] Does Aster support testnet for development? - [ ] What are the API rate limits? - [ ] What symbols/markets are available? - [ ] Are there any unique features or limitations? **Share your findings in the comments!** --- **Ready to contribute?** Comment below or start working and submit a PR! **Questions?** Feel free to ask in the comments or on Telegram. --- ### Community/Bounty Guide # 📝 如何在 GitHub 发布集成任务 (Bounty) ## 🎯 发布步骤 ### 方法 1: 直接创建 GitHub Issue(推荐) 1. **访问项目 Issues 页面** ``` https://github.com/NoFxAiOS/nofx/issues ``` 2. **点击 "New Issue" 按钮** 3. **选择 "Feature Request" 模板**(如果可用) 4. **填写 Issue 内容** #### Hyperliquid 集成 Issue: ```markdown 标题:[BOUNTY] Integrate Hyperliquid Exchange Support 🚀 内容:复制 INTEGRATION_BOUNTY_HYPERLIQUID.md 的全部内容 ``` #### Aster 集成 Issue: ```markdown 标题:[BOUNTY] Integrate Aster Exchange Support 🚀 内容:复制 INTEGRATION_BOUNTY_ASTER.md 的全部内容 ``` 5. **添加标签 (Labels)** - `enhancement` - 新功能 - `bounty` - 悬赏任务 - `help wanted` - 寻求帮助 - `good first issue` - 适合新手(如果适用) 6. **点击 "Submit new issue"** --- ### 方法 2: 使用 GitHub CLI(适合命令行用户) ```bash # 安装 GitHub CLI (如果还没安装) brew install gh # macOS # 或访问 https://cli.github.com/ # 登录 gh auth login # 创建 Hyperliquid 集成 Issue gh issue create \ --title "[BOUNTY] Integrate Hyperliquid Exchange Support 🚀" \ --body-file INTEGRATION_BOUNTY_HYPERLIQUID.md \ --label "enhancement,bounty,help wanted" # 创建 Aster 集成 Issue gh issue create \ --title "[BOUNTY] Integrate Aster Exchange Support 🚀" \ --body-file INTEGRATION_BOUNTY_ASTER.md \ --label "enhancement,bounty,help wanted" ``` --- ## 💰 设置悬赏金额 ### 选项 1: 直接在 GitHub Issue 说明 在 Issue 开头写明: ```markdown ## 💰 Bounty Reward - **$500 USD** for complete Hyperliquid integration - **Bonus $200** for websocket real-time data support - **Bonus $100** for comprehensive tests and docs ``` ### 选项 2: 使用悬赏平台 **Gitcoin Bounties** - 网站:https://gitcoin.co/ - 支持加密货币支付 - 步骤: 1. 创建 Gitcoin 账户 2. 点击 "Post a Bounty" 3. 链接到你的 GitHub Issue 4. 设置奖金金额和条件 **Bountysource** - 网站:https://www.bountysource.com/ - 支持法币和加密货币 - 步骤: 1. 导入 GitHub Issue 2. 设置悬赏金额 3. 托管资金直到完成 **IssueHunt** - 网站:https://issuehunt.io/ - 专注于开源项目 - 步骤: 1. 连接 GitHub 仓库 2. 为特定 Issue 设置悬赏 3. 贡献者完成后自动支付 --- ## 📢 推广你的 Bounty ### 1. 社交媒体宣传 **Twitter/X:** ``` 🚀 $500 Bounty! 🚀 Looking for devs to integrate Hyperliquid exchange into NOFX AI Trading System ✅ Add perpetual contracts support ✅ Unified API interface ✅ Full testing & docs Issue: [GitHub链接] Details: [详情链接] #Bounty #OpenSource #Crypto #Trading ``` **Telegram:** - 在 NOFX 开发者社区发布:https://t.me/nofx_dev_community - 在相关的开发者群组分享 ### 2. 开发者社区 **Reddit:** - r/CryptoCurrency - r/algotrading - r/opensource - r/forhire **Discord:** - 相关的加密货币交易社区 - 开发者频道 ### 3. 开发者平台 **Dev.to / Hashnode:** 写一篇博客: - 介绍项目 - 说明集成需求 - 展示悬赏奖励 - 链接到 GitHub Issue --- ## 📋 Issue 管理最佳实践 ### 1. 及时回复 - 在24小时内回复所有问题 - 提供清晰的技术指导 - 鼓励潜在贡献者 ### 2. 更新进度 定期更新 Issue,说明: - 当前进展 - 已有贡献者 - 剩余工作 - 截止日期(如果有) ### 3. 设置里程碑 ```markdown ## 📅 Milestones **Phase 1 (Week 1-2):** API Wrapper - [ ] Basic API integration - [ ] Account & position fetching **Phase 2 (Week 3):** Trading Functions - [ ] Order execution - [ ] Position management **Phase 3 (Week 4):** Testing & Docs - [ ] Comprehensive tests - [ ] Documentation updates ``` ### 4. 评审 PR 当有人提交 Pull Request: - 快速进行代码审查 - 提供建设性反馈 - 测试功能是否正常 - 合并后及时支付赏金 --- ## ⚠️ 注意事项 ### 法律 & 合规 - ✅ 明确说明这是开源贡献,不是雇佣关系 - ✅ 确保贡献者同意 AGPL-3.0 License - ✅ 保留最终合并决定权 ### 资金管理 - ✅ 使用托管服务(Gitcoin、Bountysource) - ✅ 在 Issue 中明确支付条件 - ✅ 完成后及时支付 ### 质量控制 - ✅ 要求代码审查 - ✅ 必须有测试覆盖 - ✅ 必须有文档更新 - ✅ 不破坏现有功能 --- ## 📞 需要帮助? - **GitHub Issues**: https://github.com/NoFxAiOS/nofx/issues - **Telegram**: https://t.me/nofx_dev_community - **Twitter/X**: [@Web3Tinkle](https://x.com/Web3Tinkle) --- **祝你成功招募到优秀的开发者!** 🎉 --- ### Community/Bounty Hyperliquid # 🚀 [BOUNTY] Integrate Hyperliquid Exchange Support ## 💰 Bounty Reward **To be discussed** - Open to proposals from contributors ## 📋 Overview We're looking for contributors to add Hyperliquid exchange support to NOFX AI Trading System. Currently supports Binance Futures, seeking to expand to Hyperliquid perpetual contracts. ## 🎯 Task Requirements ### Core Features to Implement #### 1. **Hyperliquid API Integration** - [ ] Account management (balance, positions, margin) - [ ] Market data fetching (K-lines, order book, trades) - [ ] Order execution (market/limit orders) - [ ] Position management (open, close, modify) - [ ] Websocket real-time data stream #### 2. **Adapter Layer** - [ ] Create `trader/hyperliquid_perpetual.go` adapter - [ ] Implement unified interface compatible with existing `BinanceFuturesClient` - [ ] Handle Hyperliquid-specific features (if any) #### 3. **Configuration Support** ```json { "traders": [ { "id": "hyperliquid_trader", "name": "Hyperliquid AI Trader", "exchange": "hyperliquid", // NEW "hyperliquid_api_key": "xxx", "hyperliquid_secret_key": "xxx", "ai_model": "deepseek", "initial_balance": 1000.0 } ] } ``` #### 4. **Risk Control Adaptation** - [ ] Adapt position limits for Hyperliquid specs - [ ] Handle leverage rules (may differ from Binance) - [ ] Implement liquidation price calculation - [ ] Funding rate integration #### 5. **Testing & Documentation** - [ ] Unit tests for API wrapper - [ ] Integration tests with testnet - [ ] Update README with Hyperliquid setup guide - [ ] Add Hyperliquid-specific troubleshooting docs ## 📚 Technical References **Hyperliquid Resources:** - Official Docs: https://hyperliquid.gitbook.io/hyperliquid-docs - API Documentation: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api - SDK Examples: https://github.com/hyperliquid-dex **NOFX Architecture:** - See `trader/binance_futures.go` as reference implementation - Main trading logic: `trader/auto_trader.go` - Configuration: `config.json` structure ## 🔧 Implementation Guidelines ### File Structure ``` trader/ ├── binance_futures.go (existing reference) ├── hyperliquid_perpetual.go (NEW - to implement) └── exchange_interface.go (NEW - unified interface) config/ └── config.go (UPDATE - add Hyperliquid config) ``` ### Interface to Implement ```go type ExchangeClient interface { // Account GetAccount() (*AccountInfo, error) GetPositions() ([]*Position, error) // Market Data GetKlines(symbol, interval string, limit int) ([]*Kline, error) GetTicker(symbol string) (*Ticker, error) // Trading CreateOrder(params *OrderParams) (*Order, error) ClosePosition(symbol, side string) error // Risk Management SetLeverage(symbol string, leverage int) error GetLiquidationPrice(position *Position) (float64, error) } ``` ## ✅ Acceptance Criteria **Minimum Requirements:** - [ ] Can connect to Hyperliquid testnet/mainnet - [ ] Fetch real-time account balance and positions - [ ] Execute market orders successfully - [ ] Close positions correctly - [ ] Calculate accurate P/L - [ ] No breaking changes to existing Binance integration **Bonus Points:** - [ ] Websocket streaming for real-time data - [ ] Support for limit orders and stop-loss/take-profit - [ ] Multi-exchange competition mode (Binance vs Hyperliquid) - [ ] Performance comparison dashboard ## 📝 How to Contribute 1. **Comment on this issue** to express interest 2. **Fork the repository** and create a feature branch 3. **Implement the integration** following guidelines above 4. **Test thoroughly** on testnet before mainnet 5. **Submit a Pull Request** with: - Code changes - Tests - Documentation updates - Demo video/screenshots ## 🤝 Support & Questions - Ask questions in this issue's comments - Join our Telegram: [NOFX Developer Community](https://t.me/nofx_dev_community) - Reference existing code: `trader/binance_futures.go` ## ⚠️ Important Notes - **Test on testnet first** - Do NOT test with real funds initially - **Maintain backward compatibility** - Existing Binance users should not be affected - **Code quality** - Follow existing code style and patterns - **Security** - Handle API keys securely, no hardcoded credentials --- **Ready to contribute?** Comment below or start working and submit a PR! **Questions?** Feel free to ask in the comments or on Telegram. --- ### Community/HOW TO MIGRATE YOUR PR # 🔄 How to Migrate Your PR to the New Format **Language:** [English](HOW_TO_MIGRATE_YOUR_PR.md) | [中文](HOW_TO_MIGRATE_YOUR_PR.zh-CN.md) This guide helps you migrate your existing PR to meet the new PR management system requirements. --- ## 🎯 Why Migrate? While your existing PR **will still be reviewed and merged** under current standards, migrating it to the new format gives you: ✅ **Faster reviews** - Automated checks catch issues early ✅ **Better feedback** - Clear, actionable feedback from CI ✅ **Higher quality** - Consistent code standards ✅ **Learning** - Understand our new contribution workflow --- ## ⚡ Quick Check (Recommended) ### Step 1: Analyze Your PR ```bash # Run the PR health check (reads only, doesn't modify anything) ./scripts/pr-check.sh ``` This will analyze your PR and tell you: - ✅ What's good - ⚠️ What needs attention - 💡 How to fix issues - 📊 Overall health score ### Step 2: Fix Issues Based on the suggestions, fix the issues manually. Common fixes: ```bash # Rebase on latest dev git fetch upstream && git rebase upstream/dev # Format Go code go fmt ./... # Run tests go test ./... # Format frontend code cd web && npm run lint -- --fix ``` ### Step 3: Run Check Again ```bash # Verify all issues are fixed ./scripts/pr-check.sh ``` ### Step 4: Push Changes ```bash git push -f origin ``` ### What the Script Does 1. ✅ Syncs with latest `upstream/dev` 2. ✅ Rebases your changes 3. ✅ Formats Go code (`go fmt`) 4. ✅ Runs Go linting (`go vet`) 5. ✅ Runs tests 6. ✅ Formats frontend code (if applicable) 7. ✅ Pushes changes to your PR --- ## 🛠️ Manual Migration (Step by Step) If you prefer to do it manually: ### Step 1: Sync with Upstream ```bash # Add upstream if not already added git remote add upstream https://github.com/NoFxAiOS/nofx.git # Fetch latest changes git fetch upstream # Rebase your branch git checkout git rebase upstream/dev ``` ### Step 2: Backend Checks (Go) ```bash # Format Go code go fmt ./... # Run linting go vet ./... # Run tests go test ./... # If you made changes, commit them git add . git commit -m "chore: format and fix backend issues" ``` ### Step 3: Frontend Checks (if applicable) ```bash cd web # Install dependencies npm install # Fix linting issues npm run lint -- --fix # Check types npm run type-check # Test build npm run build cd .. # Commit any fixes git add . git commit -m "chore: fix frontend issues" ``` ### Step 4: Update PR Title (if needed) Ensure your PR title follows [Conventional Commits](https://www.conventionalcommits.org/): ``` (): Examples: feat(exchange): add OKX integration fix(trader): resolve position tracking bug docs(readme): update installation guide ``` **Types:** - `feat` - New feature - `fix` - Bug fix - `docs` - Documentation - `refactor` - Code refactoring - `perf` - Performance improvement - `test` - Test updates - `chore` - Build/config changes - `security` - Security improvements ### Step 5: Push Changes ```bash git push -f origin ``` --- ## 📋 Checklist After migrating, verify: - [ ] PR is rebased on latest `dev` - [ ] No merge conflicts - [ ] Backend tests pass locally - [ ] Frontend builds successfully - [ ] PR title follows Conventional Commits format - [ ] All commits are meaningful - [ ] Changes pushed to GitHub --- ## 🤖 What Happens After Migration? After you push your changes: 1. **Automated checks will run** (they won't block merging, just provide feedback) 2. **You'll get a comment** with check results and suggestions 3. **Maintainers will review** your PR with the new context 4. **Faster review** thanks to pre-checks --- ## ❓ Troubleshooting ### "Rebase conflicts" If you get conflicts during rebase: ```bash # Fix conflicts in your editor # Then: git add git rebase --continue # Or abort and ask for help: git rebase --abort ``` **Need help?** Just comment on your PR and we'll assist! ### "Tests failing" If tests fail: ```bash # Run tests to see the error go test ./... # Fix the issue # Then commit and push git add . git commit -m "fix: resolve test failures" git push -f origin ``` ### "Script not working" If the migration script doesn't work: 1. Check you have Go and Node.js installed 2. Try manual migration (steps above) 3. Ask for help in your PR comments --- ## 💡 Tips **Don't want to migrate?** - That's okay! Your PR will still be reviewed and merged - Migration is optional but recommended **First time using Git rebase?** - Check our [Git guide](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) - Ask questions in your PR - we're here to help! **Want to learn more?** - [Contributing Guidelines](../../CONTRIBUTING.md) - [Migration Announcement](MIGRATION_ANNOUNCEMENT.md) - [PR Review Guide](../maintainers/PR_REVIEW_GUIDE.md) --- ## 📞 Need Help? **Stuck on migration?** - Comment on your PR - Ask in [Telegram](https://t.me/nofx_dev_community) - Open a [Discussion](https://github.com/NoFxAiOS/nofx/discussions) **We're here to help you succeed!** 🚀 --- ## 🎉 After Migration Once migrated: 1. ✅ Wait for automated checks to run 2. ✅ Address any feedback in comments 3. ✅ Wait for maintainer review 4. ✅ Celebrate when merged! 🎉 **Thank you for contributing to NOFX!** --- ### Community/HOW TO MIGRATE YOUR PR.Zh CN # 🔄 如何将你的 PR 迁移到新格式 **语言:** [English](HOW_TO_MIGRATE_YOUR_PR.md) | [中文](HOW_TO_MIGRATE_YOUR_PR.zh-CN.md) 本指南帮助你将现有 PR 迁移以满足新的 PR 管理系统要求。 --- ## 🎯 为什么要迁移? 虽然你的现有 PR **仍将按照当前标准审核和合并**,但将其迁移到新格式可以获得: ✅ **更快的审核** - 自动化检查尽早捕获问题 ✅ **更好的反馈** - CI 提供清晰、可操作的反馈 ✅ **更高质量** - 一致的代码标准 ✅ **学习机会** - 了解我们新的贡献工作流程 --- ## ⚡ 快速检查(推荐) ### 步骤 1:分析你的 PR ```bash # 运行 PR 健康检查(只读,不修改任何内容) ./scripts/pr-check.sh ``` 这将分析你的 PR 并告诉你: - ✅ 什么是好的 - ⚠️ 什么需要注意 - 💡 如何修复问题 - 📊 整体健康评分 ### 步骤 2:修复问题 根据建议,手动修复问题。常见修复: ```bash # Rebase 到最新 dev git fetch upstream && git rebase upstream/dev # 格式化 Go 代码 go fmt ./... # 运行测试 go test ./... # 格式化前端代码 cd web && npm run lint -- --fix ``` ### 步骤 3:再次运行检查 ```bash # 验证所有问题都已修复 ./scripts/pr-check.sh ``` ### 步骤 4:推送更改 ```bash git push -f origin ``` ### 脚本做什么 1. ✅ 与最新的 `upstream/dev` 同步 2. ✅ Rebase 你的更改 3. ✅ 格式化 Go 代码(`go fmt`) 4. ✅ 运行 Go linting(`go vet`) 5. ✅ 运行测试 6. ✅ 格式化前端代码(如果适用) 7. ✅ 推送更改到你的 PR --- ## 🛠️ 手动迁移(逐步指南) 如果你更喜欢手动操作: ### 步骤 1:与 Upstream 同步 ```bash # 如果还没添加 upstream,添加它 git remote add upstream https://github.com/NoFxAiOS/nofx.git # 获取最新更改 git fetch upstream # Rebase 你的分支 git checkout git rebase upstream/dev ``` ### 步骤 2:后端检查(Go) ```bash # 格式化 Go 代码 go fmt ./... # 运行 linting go vet ./... # 运行测试 go test ./... # 如果有更改,提交它们 git add . git commit -m "chore: format and fix backend issues" ``` ### 步骤 3:前端检查(如果适用) ```bash cd web # 安装依赖 npm install # 修复 linting 问题 npm run lint -- --fix # 检查类型 npm run type-check # 测试构建 npm run build cd .. # 提交任何修复 git add . git commit -m "chore: fix frontend issues" ``` ### 步骤 4:更新 PR 标题(如果需要) 确保你的 PR 标题遵循 [Conventional Commits](https://www.conventionalcommits.org/): ``` (): 示例: feat(exchange): add OKX integration fix(trader): resolve position tracking bug docs(readme): update installation guide ``` **类型:** - `feat` - 新功能 - `fix` - Bug 修复 - `docs` - 文档 - `refactor` - 代码重构 - `perf` - 性能改进 - `test` - 测试更新 - `chore` - 构建/配置更改 - `security` - 安全改进 ### 步骤 5:推送更改 ```bash git push -f origin ``` --- ## 📋 检查清单 迁移后,验证: - [ ] PR 已基于最新 `dev` rebase - [ ] 没有合并冲突 - [ ] 后端测试在本地通过 - [ ] 前端构建成功 - [ ] PR 标题遵循 Conventional Commits 格式 - [ ] 所有 commit 都有意义 - [ ] 更改已推送到 GitHub --- ## 🤖 迁移后会发生什么? 推送更改后: 1. **自动化检查将运行**(不会阻止合并,只提供反馈) 2. **你将收到评论**,包含检查结果和建议 3. **维护者将审核** 你的 PR,有了新的上下文 4. **更快的审核** 得益于预检查 --- ## ❓ 故障排除 ### "Rebase 冲突" 如果在 rebase 期间遇到冲突: ```bash # 在编辑器中修复冲突 # 然后: git add git rebase --continue # 或中止并寻求帮助: git rebase --abort ``` **需要帮助?** 在你的 PR 中评论,我们会协助! ### "测试失败" 如果测试失败: ```bash # 运行测试查看错误 go test ./... # 修复问题 # 然后提交并推送 git add . git commit -m "fix: resolve test failures" git push -f origin ``` ### "脚本不工作" 如果迁移脚本不工作: 1. 检查你是否安装了 Go 和 Node.js 2. 尝试手动迁移(上面的步骤) 3. 在你的 PR 评论中寻求帮助 --- ## 💡 提示 **不想迁移?** - 没关系!你的 PR 仍将被审核和合并 - 迁移是可选的但推荐的 **第一次使用 Git rebase?** - 查看我们的 [Git 指南](https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%8F%98%E5%9F%BA) - 在你的 PR 中提问 - 我们在这里帮助! **想了解更多?** - [贡献指南](../../docs/i18n/zh-CN/CONTRIBUTING.md) - [迁移公告](MIGRATION_ANNOUNCEMENT.zh-CN.md) - [PR 审核指南](../maintainers/PR_REVIEW_GUIDE.zh-CN.md) --- ## 📞 需要帮助? **迁移遇到困难?** - 在你的 PR 中评论 - 在 [Telegram](https://t.me/nofx_dev_community) 提问 - 开启 [Discussion](https://github.com/NoFxAiOS/nofx/discussions) **我们在这里帮助你成功!** 🚀 --- ## 🎉 迁移后 迁移完成后: 1. ✅ 等待自动化检查运行 2. ✅ 处理评论中的任何反馈 3. ✅ 等待维护者审核 4. ✅ 合并时庆祝!🎉 **感谢你为 NOFX 做出贡献!** --- ### Community/MIGRATION ANNOUNCEMENT # 📢 PR Management System Update - What Contributors Need to Know **Language:** [English](MIGRATION_ANNOUNCEMENT.md) | [中文](MIGRATION_ANNOUNCEMENT.zh-CN.md) We're introducing a new PR management system to improve code quality and make contributing easier! This guide explains what's changing and what you need to do. --- ## 🎯 What's Changing? We're introducing: ✅ **Clear contribution guidelines** aligned with our [roadmap](../roadmap/README.md) ✅ **Automated checks** (tests, linting, security scans) ✅ **Better labeling** for organization and prioritization ✅ **Faster review turnaround** with pre-checks ✅ **Transparent process** so you know exactly what to expect --- ## 📅 Timeline ``` Week 1-2: Existing PR Review Period Week 3: Soft Launch (checks are advisory only) Week 4+: Full Launch (checks are required) ``` **Important:** This rollout is gradual. You'll have time to adapt! --- ## 🤔 What This Means for YOU ### If You Have an Existing Open PR **Good news:** Your PR will NOT be blocked by new rules! - ✅ Your PR will be reviewed under current (relaxed) standards - ✅ We'll review and provide feedback within 1-2 weeks - ✅ Some PRs may need a quick rebase or minor updates **What you might need to do:** 1. **Rebase on latest `dev` branch** if there are conflicts 2. **Respond to review comments** within 1 week 3. **Be patient** as we work through the backlog **What happens if I don't respond?** - We may close your PR after 2 weeks of inactivity - You can always reopen it later with updates! - No hard feelings - we're just cleaning up the backlog ### 🚀 Want to Check Your PR? (Optional) We've created a **PR health check tool** to help you see if your PR meets the new standards! **Run this in your local fork:** ```bash ./scripts/pr-check.sh ``` **What it does:** - 🔍 Analyzes your PR (doesn't modify anything) - ✅ Shows what's good - ⚠️ Points out issues - 💡 Gives you specific fix suggestions - 📊 Overall health score **Then fix issues and push:** ```bash # Fix the issues (see suggestions from script) # Run check again ./scripts/pr-check.sh # Push when ready git push -f origin ``` **📖 Full Guide:** [How to Migrate Your PR](HOW_TO_MIGRATE_YOUR_PR.md) **Remember:** This is completely **optional** for existing PRs! --- ### If You're Submitting a NEW PR **Timeline matters:** #### Week 3 (Soft Launch): - ✅ Automated checks will run (tests, linting, security) - ⚠️ **Checks are advisory only** - they won't block your PR - ✅ This is a learning period - we're here to help! - ✅ Get familiar with the new [Contributing Guidelines](../../CONTRIBUTING.md) #### Week 4+ (Full Launch): - ✅ All automated checks must pass before merge - ✅ PR must follow [Conventional Commits](https://www.conventionalcommits.org/) format - ✅ PR template must be filled out - ✅ Must align with [roadmap](../roadmap/README.md) priorities --- ## ✅ How to Prepare for New System ### 1. Read the Contributing Guidelines 📖 [CONTRIBUTING.md](../../CONTRIBUTING.md) **Key points:** - We accept PRs aligned with our roadmap (security, AI, exchanges, UI/UX) - PRs should be focused and small (<300 lines preferred) - Use Conventional Commits format: `feat(area): description` - Include tests for new features ### 2. Check the Roadmap 🗺️ [Roadmap](../roadmap/README.md) **Current priorities (Phase 1):** - 🔒 Security enhancements - 🧠 AI model integrations - 🔗 Exchange integrations (OKX, Bybit, Lighter, EdgeX) - 🎨 UI/UX improvements - ⚡ Performance optimizations - 🐛 Bug fixes **Lower priority (Phase 2+):** - Universal market expansion (stocks, futures) - Advanced AI features - Enterprise features 💡 **Pro tip:** If your PR aligns with Phase 1, it'll be reviewed faster! ### 3. Set Up Local Testing Before submitting a PR, test locally: ```bash # Backend tests go test ./... go fmt ./... go vet ./... # Frontend tests cd web npm run lint npm run type-check npm run build ``` This helps your PR pass automated checks on first try! --- ## 📝 PR Title Format Use [Conventional Commits](https://www.conventionalcommits.org/) format: ``` (): Examples: feat(exchange): add OKX futures support fix(trader): resolve position tracking bug docs(readme): update installation instructions perf(ai): optimize prompt generation ``` **Types:** - `feat` - New feature - `fix` - Bug fix - `docs` - Documentation - `refactor` - Code refactoring - `perf` - Performance improvement - `test` - Test updates - `chore` - Build/config changes - `security` - Security improvements --- ## 🎯 What Makes a Good PR? ### ✅ Good PR Example ``` Title: feat(exchange): add OKX exchange integration Description: Implements OKX exchange support with the following features: - Order placement and cancellation - Balance and position retrieval - Leverage configuration - Error handling and retry logic Closes #123 Testing: - [x] Unit tests added and passing - [x] Manually tested with real API - [x] Documentation updated ``` **Why it's good:** - ✅ Clear, descriptive title - ✅ Explains what and why - ✅ Links to issue - ✅ Includes testing details - ✅ Small, focused change ### ❌ Avoid These **Too vague:** ``` Title: update code Description: made some changes ``` **Too large:** ``` Title: feat: complete rewrite of entire trading system Files changed: 2,500+ ``` **Off roadmap:** ``` Title: feat: add support for stock trading (This is Phase 3, not current priority) ``` --- ## 🐛 If Your PR Fails Checks Don't panic! We're here to help. **Week 3 (Soft Launch):** - Checks are advisory - we'll help you fix issues - Ask questions in your PR comments - We can guide you through debugging **Week 4+ (Full Launch):** - Checks must pass, but we still help! - Common issues: - Test failures → Run `go test ./...` locally - Linting errors → Run `go fmt` and `npm run lint` - Merge conflicts → Rebase on latest `dev` **Need help?** Just ask! Comment in your PR or reach out: - [GitHub Discussions](https://github.com/NoFxAiOS/nofx/discussions) - [Telegram Community](https://t.me/nofx_dev_community) --- ## 💰 Special Note for Bounty Contributors If you're working on a bounty: ✅ **Your PRs get priority review** (24-48 hours) ✅ **Extra support** to meet requirements ✅ **Flexible during transition** - we'll work with you Just make sure to: - Reference the bounty issue number - Meet all acceptance criteria - Include demo video/screenshots --- ## ❓ FAQ ### Q: Will my existing PR be rejected? **A:** No! Existing PRs use relaxed standards. We may ask for minor updates (rebase, small fixes), but you won't be held to new strict requirements. ### Q: What if I can't pass the new CI checks? **A:** Week 3 is a learning period. We'll help you understand and fix issues. By Week 4, you'll be familiar with the process! ### Q: Will this slow down contributions? **A:** Actually, no! Automated checks catch issues early, making reviews faster. Clear guidelines help you submit better PRs on first try. ### Q: Can I still contribute if I'm a beginner? **A:** Absolutely! Look for issues labeled `good first issue`. We're here to mentor and help you succeed. ### Q: My PR is large (>1000 lines). What should I do? **A:** Consider breaking it into smaller PRs. This gets you: - ✅ Faster reviews - ✅ Easier testing - ✅ Higher chance of quick merge Need help planning? Just ask in your PR! ### Q: What if my feature isn't on the roadmap? **A:** Open an issue first to discuss! We're open to good ideas, but want to ensure alignment before you spend time coding. ### Q: When will this be fully active? **A:** Week 4+ (approximately 4 weeks from announcement date). Check the pinned Discussion post for exact dates. --- ## 🎉 Benefits for Contributors This new system helps YOU by: ✅ **Faster reviews** - Automated pre-checks reduce review time ✅ **Clear expectations** - You know exactly what's required ✅ **Better feedback** - Automated checks catch issues early ✅ **Fair prioritization** - Roadmap-aligned PRs reviewed faster ✅ **Recognition** - Contributor tiers and recognition program --- ## 📚 Resources ### Must Read - [Contributing Guidelines](../../CONTRIBUTING.md) - Complete guide - [Roadmap](../roadmap/README.md) - Current priorities ### Helpful Links - [Conventional Commits](https://www.conventionalcommits.org/) - Commit format - [Good First Issues](https://github.com/NoFxAiOS/nofx/labels/good%20first%20issue) - Beginner-friendly tasks - [Bounty Program](../bounty-guide.md) - Get paid to contribute ### Get Help - [GitHub Discussions](https://github.com/NoFxAiOS/nofx/discussions) - Ask questions - [Telegram](https://t.me/nofx_dev_community) - Community chat - [Twitter](https://x.com/nofx_official) - Updates and announcements --- ## 💬 Feedback Welcome! This is a new system and we want YOUR input: - 📝 What's unclear? - 🤔 What concerns do you have? - 💡 How can we improve? Share in the [Migration Feedback Discussion](https://github.com/NoFxAiOS/nofx/discussions) (link TBD) --- ## 🙏 Thank You! We appreciate your contributions and patience during this transition. Together, we're building something amazing! **Questions?** Don't hesitate to ask. We're here to help! 🚀 --- **Last Updated:** 2025-01-XX **Status:** Announcement (Week 0) **Full Launch:** Week 4+ (TBD) --- ### Community/MIGRATION ANNOUNCEMENT.Zh CN # 📢 PR 管理系统更新 - 贡献者须知 **语言:** [English](MIGRATION_ANNOUNCEMENT.md) | [中文](MIGRATION_ANNOUNCEMENT.zh-CN.md) 我们正在引入新的 PR 管理系统,以提高代码质量并让贡献变得更容易!本指南解释了变化内容以及你需要做什么。 --- ## 🎯 有什么变化? 我们正在引入: ✅ **清晰的贡献指南** 与我们的[路线图](../roadmap/README.zh-CN.md)对齐 ✅ **自动化检查**(测试、linting、安全扫描) ✅ **更好的标签** 用于组织和优先级排序 ✅ **更快的审核周转** 通过预检查 ✅ **透明的流程** 让你准确知道期望什么 --- ## 📅 时间表 ``` 第 1-2 周:现有 PR 审核期 第 3 周: 软启动(检查仅是建议性的) 第 4 周+: 完全启动(检查是必需的) ``` **重要:** 这个推出是渐进式的。你将有时间适应! --- ## 🤔 这对你意味着什么 ### 如果你有现有的打开的 PR **好消息:** 你的 PR 不会被新规则阻塞! - ✅ 你的 PR 将按照当前(宽松)标准进行审核 - ✅ 我们将在 1-2 周内审核并提供反馈 - ✅ 一些 PR 可能需要快速 rebase 或次要更新 **你可能需要做什么:** 1. **基于最新 `dev` 分支 rebase** 如果有冲突 2. **在 1 周内回应审核评论** 3. **保持耐心** 我们正在处理积压 **如果我不回应会怎样?** - 我们可能会在 2 周不活动后关闭你的 PR - 你随时可以稍后重新打开并更新! - 没有恶意 - 我们只是在清理积压 ### 🚀 想要检查你的 PR?(可选) 我们创建了一个 **PR 健康检查工具**来帮助你看 PR 是否符合新标准! **在你的本地 fork 中运行:** ```bash ./scripts/pr-check.sh ``` **它做什么:** - 🔍 分析你的 PR(不修改任何内容) - ✅ 显示什么是好的 - ⚠️ 指出问题 - 💡 给你具体的修复建议 - 📊 整体健康评分 **然后修复问题并推送:** ```bash # 修复问题(查看脚本的建议) # 再次运行检查 ./scripts/pr-check.sh # 准备好后推送 git push -f origin ``` **📖 完整指南:** [如何迁移你的 PR](HOW_TO_MIGRATE_YOUR_PR.zh-CN.md) **记住:** 对于现有 PR,这是完全**可选的**! --- ### 如果你要提交新的 PR **时间很重要:** #### 第 3 周(软启动): - ✅ 自动化检查将运行(测试、linting、安全性) - ⚠️ **检查仅是建议性的** - 不会阻塞你的 PR - ✅ 这是一个学习期 - 我们在这里帮助! - ✅ 熟悉新的[贡献指南](../../docs/i18n/zh-CN/CONTRIBUTING.md) #### 第 4 周+(完全启动): - ✅ 所有自动化检查必须通过才能合并 - ✅ PR 必须遵循 [Conventional Commits](https://www.conventionalcommits.org/) 格式 - ✅ 必须填写 PR 模板 - ✅ 必须与[路线图](../roadmap/README.zh-CN.md)优先级对齐 --- ## ✅ 如何为新系统做准备 ### 1. 阅读贡献指南 📖 [CONTRIBUTING.md](../../docs/i18n/zh-CN/CONTRIBUTING.md) **关键点:** - 我们接受与路线图对齐的 PR(安全性、AI、交易所、UI/UX) - PR 应该集中且小型(<300 行优先) - 使用 Conventional Commits 格式:`feat(area): description` - 为新功能包含测试 ### 2. 查看路线图 🗺️ [路线图](../roadmap/README.zh-CN.md) **当前优先级(Phase 1):** - 🔒 安全增强 - 🧠 AI 模型集成 - 🔗 交易所集成(OKX、Bybit、Lighter、EdgeX) - 🎨 UI/UX 改进 - ⚡ 性能优化 - 🐛 Bug 修复 **较低优先级(Phase 2+):** - 通用市场扩展(股票、期货) - 高级 AI 功能 - 企业功能 💡 **专业提示:** 如果你的 PR 与 Phase 1 对齐,它会被更快审核! ### 3. 设置本地测试 提交 PR 前,在本地测试: ```bash # 后端测试 go test ./... go fmt ./... go vet ./... # 前端测试 cd web npm run lint npm run type-check npm run build ``` 这有助于你的 PR 第一次就通过自动化检查! --- ## 📝 PR 标题格式 使用 [Conventional Commits](https://www.conventionalcommits.org/) 格式: ``` (): 示例: feat(exchange): add OKX futures support fix(trader): resolve position tracking bug docs(readme): update installation instructions perf(ai): optimize prompt generation ``` **类型:** - `feat` - 新功能 - `fix` - Bug 修复 - `docs` - 文档 - `refactor` - 代码重构 - `perf` - 性能改进 - `test` - 测试更新 - `chore` - 构建/配置变更 - `security` - 安全改进 --- ## 🎯 什么是好的 PR? ### ✅ 好的 PR 示例 ``` 标题:feat(exchange): add OKX exchange integration 描述: 使用以下功能实现 OKX 交易所支持: - 订单下达和取消 - 余额和仓位检索 - 杠杆配置 - 错误处理和重试逻辑 关闭 #123 测试: - [x] 单元测试已添加并通过 - [x] 使用真实 API 手动测试 - [x] 文档已更新 ``` **为什么好:** - ✅ 清晰、描述性标题 - ✅ 解释了什么和为什么 - ✅ 链接到 issue - ✅ 包含测试详情 - ✅ 小型、集中的变更 ### ❌ 避免这些 **太模糊:** ``` 标题:update code 描述:made some changes ``` **太大:** ``` 标题:feat: complete rewrite of entire trading system 文件变更:2,500+ ``` **不在路线图上:** ``` 标题:feat: add support for stock trading (这是 Phase 3,不是当前优先级) ``` --- ## 🐛 如果你的 PR 检查失败 不要恐慌!我们在这里帮助。 **第 3 周(软启动):** - 检查是建议性的 - 我们会帮你解决问题 - 在你的 PR 评论中提问 - 我们可以指导你进行调试 **第 4 周+(完全启动):** - 检查必须通过,但我们仍然会帮助! - 常见问题: - 测试失败 → 在本地运行 `go test ./...` - Linting 错误 → 运行 `go fmt` 和 `npm run lint` - 合并冲突 → 基于最新 `dev` rebase **需要帮助?** 只管问!在你的 PR 中评论或联系: - [GitHub Discussions](https://github.com/NoFxAiOS/nofx/discussions) - [Telegram 社区](https://t.me/nofx_dev_community) --- ## 💰 悬赏贡献者特别说明 如果你正在做悬赏任务: ✅ **你的 PR 获得优先审核**(24-48 小时) ✅ **额外支持** 以满足要求 ✅ **过渡期间灵活** - 我们会与你合作 只需确保: - 引用悬赏 issue 编号 - 满足所有验收标准 - 包含演示视频/截图 --- ## ❓ 常见问题 ### Q:我的现有 PR 会被拒绝吗? **A:** 不会!现有 PR 使用宽松标准。我们可能会要求次要更新(rebase、小修复),但你不会被要求满足新的严格要求。 ### Q:如果我无法通过新的 CI 检查怎么办? **A:** 第 3 周是学习期。我们会帮你理解和修复问题。到第 4 周,你将熟悉这个流程! ### Q:这会减慢贡献速度吗? **A:** 实际上不会!自动化检查尽早捕获问题,使审核更快。清晰的指南帮助你第一次就提交更好的 PR。 ### Q:如果我是初学者,我还能贡献吗? **A:** 绝对可以!查找标记为 `good first issue` 的 issue。我们在这里指导并帮助你成功。 ### Q:我的 PR 很大(>1000 行)。我应该怎么做? **A:** 考虑将其拆分为更小的 PR。这让你获得: - ✅ 更快的审核 - ✅ 更容易的测试 - ✅ 更高的快速合并机会 需要帮助规划?在你的 PR 中提问即可! ### Q:如果我的功能不在路线图上怎么办? **A:** 先开一个 issue 讨论!我们对好想法持开放态度,但在你花时间编码之前想确保对齐。 ### Q:这将何时完全激活? **A:** 第 4 周+(从公告日期起大约 4 周)。查看置顶的 Discussion 帖子了解确切日期。 --- ## 🎉 对贡献者的好处 这个新系统通过以下方式帮助你: ✅ **更快的审核** - 自动化预检查减少审核时间 ✅ **清晰的期望** - 你准确知道需要什么 ✅ **更好的反馈** - 自动化检查尽早捕获问题 ✅ **公平的优先级排序** - 路线图对齐的 PR 审核更快 ✅ **表彰** - 贡献者等级和表彰计划 --- ## 📚 资源 ### 必读 - [贡献指南](../../docs/i18n/zh-CN/CONTRIBUTING.md) - 完整指南 - [路线图](../roadmap/README.zh-CN.md) - 当前优先级 ### 有用链接 - [Conventional Commits](https://www.conventionalcommits.org/) - Commit 格式 - [Good First Issues](https://github.com/NoFxAiOS/nofx/labels/good%20first%20issue) - 适合初学者的任务 - [悬赏计划](../bounty-guide.md) - 获得报酬来贡献 ### 获取帮助 - [GitHub Discussions](https://github.com/NoFxAiOS/nofx/discussions) - 提问 - [Telegram](https://t.me/nofx_dev_community) - 社区聊天 - [Twitter](https://x.com/nofx_official) - 更新和公告 --- ## 💬 欢迎反馈! 这是一个新系统,我们想要你的意见: - 📝 什么不清楚? - 🤔 你有什么顾虑? - 💡 我们如何改进? 在[迁移反馈讨论](https://github.com/NoFxAiOS/nofx/discussions)中分享(链接待定) --- ## 🙏 谢谢你! 我们感谢你的贡献和在这次过渡期间的耐心。我们一起正在构建令人惊叹的东西! **问题?** 不要犹豫提问。我们在这里帮助!🚀 --- **最后更新:** 2025-01-XX **状态:** 公告(第 0 周) **完全启动:** 第 4 周+(待定) --- ### Community/OFFICIAL ACCOUNTS # ⚠️ Official Accounts & Anti-Impersonation Notice ## Legal Entity | Field | Details | |-------|---------| | Company Name | **Cryonic Holdings Limited** | | Company No. | 2193977 | | Jurisdiction | British Virgin Islands | | Address | Mandar House, 3rd Floor, P.O. Box 2196, Johnson's Ghut, Tortola, BVI | | Contact Email | 0xccfelix@gmail.com | ## Official Social Media & Channels | Platform | Official Account | Link | Status | |----------|-----------------|------|--------| | Twitter/X | **@nofx_official** | https://x.com/nofx_official | ✅ Official | | Twitter/X | **@Web3Tinkle** | https://x.com/Web3Tinkle | ✅ Founder | | GitHub | **NoFxAiOS** | https://github.com/NoFxAiOS | ✅ Official | | Website | **nofxai.com** | https://nofxai.com | ✅ Official | | Dashboard | **nofxos.ai** | https://nofxos.ai | ✅ Official | ## ⛔ Known Impersonation Accounts The following accounts are **NOT affiliated** with the NoFx project: | Platform | Account | Status | |----------|---------|--------| | Twitter/X | @nofx_ai | ❌ **NOT OFFICIAL** — Not affiliated with this project | > **Warning:** Any account claiming to represent NoFx that is not listed above is unauthorized. Please verify through this page before trusting any account claiming to be associated with NoFx. ## How to Verify Authenticity 1. Check this page (OFFICIAL_ACCOUNTS.md) in our official GitHub repository 2. Our GitHub repository sidebar links directly to our official Twitter 3. Our README.md lists all official accounts under "Core Team" and "Official Links" 4. Our operating entity is Cryonic Holdings Limited (BVI No. 2193977) 5. Official contact email: 0xccfelix@gmail.com ## Report Impersonation If you encounter accounts impersonating NoFx, please: 1. Report them on the respective platform 2. Open an issue in this repository to notify our team --- *Last updated: 2026-03-01* *This document is maintained by Cryonic Holdings Limited in the official NoFx GitHub repository (10,500+ ⭐)* --- ### Community/PR COMMENT TEMPLATE # 📢 PR Comment Template for Existing PRs This template is for maintainers to comment on existing PRs to introduce the new system. --- ## Template (English) ```markdown Hi @{username}! 👋 Thank you for your contribution to NOFX! ## 🚀 New PR Management System We're introducing a new PR management system to improve code quality and make reviews faster. Your PR will **not be blocked** by these changes - we'll review it under current standards. ### ✨ Optional: Want to check your PR against new standards? We've created a **PR health check tool** that analyzes your PR and gives you suggestions! **How to use:** ```bash # In your local fork, on your PR branch cd /path/to/your/nofx-fork git checkout # Run the health check (reads only, doesn't modify) ./scripts/pr-check.sh ``` **What it does:** - 🔍 Analyzes your PR (doesn't modify anything) - ✅ Shows what's already good - ⚠️ Points out issues - 💡 Gives specific suggestions on how to fix - 📊 Overall health score **Then fix and re-check:** ```bash # Fix the issues based on suggestions # Run check again to verify ./scripts/pr-check.sh # Push when everything looks good git push origin ``` ### 📖 Learn More - [Migration Announcement](https://github.com/NoFxAiOS/nofx/blob/dev/docs/community/MIGRATION_ANNOUNCEMENT.md) - [Contributing Guidelines](https://github.com/NoFxAiOS/nofx/blob/dev/CONTRIBUTING.md) ### ❓ Questions? Just ask here! We're happy to help. 🙏 --- **Note:** This migration is **completely optional** for existing PRs. We'll review and merge your PR either way! ``` --- ## Template (Chinese / 中文) ```markdown 嗨 @{username}!👋 感谢你为 NOFX 做出的贡献! ## 🚀 新的 PR 管理系统 我们正在引入新的 PR 管理系统,以提高代码质量并加快审核速度。你的 PR **不会被阻止** - 我们将按照当前标准审核它。 ### ✨ 可选:想要检查你的 PR 吗? 我们创建了一个 **PR 健康检查工具**来帮助你看 PR 是否符合新标准! **在你的本地 fork 中运行:** ```bash # 在你的本地 fork 中,切换到你的 PR 分支 cd /path/to/your/nofx-fork git checkout # 运行健康检查(只读,不修改任何内容) ./scripts/pr-check.sh ``` **它做什么:** - 🔍 分析你的 PR(不修改任何内容) - ✅ 显示什么是好的 - ⚠️ 指出问题 - 💡 给你具体的修复建议 - 📊 整体健康评分 **然后修复问题并推送:** ```bash # 修复问题(查看脚本的建议) # 再次运行检查 ./scripts/pr-check.sh # 准备好后推送 git push origin ``` ### 📖 了解更多 - [迁移公告](https://github.com/NoFxAiOS/nofx/blob/dev/docs/community/MIGRATION_ANNOUNCEMENT.zh-CN.md) - [贡献指南](https://github.com/NoFxAiOS/nofx/blob/dev/docs/i18n/zh-CN/CONTRIBUTING.md) ### ❓ 问题? 在这里提问即可!我们很乐意帮助。🙏 --- **注意:** 对于现有 PR,此迁移是**完全可选的**。无论如何我们都会审核和合并你的 PR! ``` --- ## Quick Copy-Paste Template For quick commenting on multiple PRs: ```markdown 👋 Hi! Thanks for your PR! We're introducing a new PR system. Your PR won't be blocked - we'll review it normally. **Want to check your PR?** Run this in your fork: ```bash ./scripts/pr-check.sh ``` [Learn more](https://github.com/NoFxAiOS/nofx/blob/dev/docs/community/MIGRATION_ANNOUNCEMENT.md) | This is optional! ``` --- ## Bulk Comment Script (for maintainers) ```bash #!/bin/bash # Comment on all open PRs gh pr list --state open --json number --jq '.[].number' | while read pr_number; do echo "Commenting on PR #$pr_number" gh pr comment "$pr_number" --body "👋 Hi! Thanks for your PR! We're introducing a new PR system. Your PR won't be blocked - we'll review it normally. **Want to check your PR?** Run this in your fork: \`\`\`bash ./scripts/pr-check.sh \`\`\` [Learn more](https://github.com/NoFxAiOS/nofx/blob/dev/docs/community/MIGRATION_ANNOUNCEMENT.md) | This is optional!" echo "✅ Commented on PR #$pr_number" sleep 2 # Be nice to GitHub API done ``` Save as `comment-all-prs.sh` and run: ```bash chmod +x comment-all-prs.sh ./comment-all-prs.sh ``` --- ### Community/README # 👥 NOFX Community Welcome to the NOFX community! This section contains everything you need to contribute and participate. --- ## 📢 Important Announcement **🚀 New PR Management System Coming Soon!** We're introducing a new PR management system to improve code quality and make contributing easier! **📖 Read:** [Migration Announcement](MIGRATION_ANNOUNCEMENT.md) | [迁移公告(中文)](MIGRATION_ANNOUNCEMENT.zh-CN.md) **Timeline:** 4-week gradual rollout starting soon **For existing PRs:** Don't worry! Your PRs will not be blocked by new rules. --- ## 🤝 How to Contribute ### Getting Started 1. **Read the Guides** - [Contributing Guide](../../CONTRIBUTING.md) - Complete contribution workflow - [Code of Conduct](../../CODE_OF_CONDUCT.md) - Community standards - [Security Policy](../../SECURITY.md) - Report vulnerabilities 2. **Find Something to Work On** - Browse [GitHub Issues](https://github.com/NoFxAiOS/nofx/issues) - Look for `good first issue` label - Check out [bounty tasks](#-bounty-program) 3. **Join the Community** - 💬 [Telegram Developer Community](https://t.me/nofx_dev_community) - 🐦 [Twitter @nofx_official](https://x.com/nofx_official) - 🐙 [GitHub Discussions](https://github.com/NoFxAiOS/nofx/discussions) --- ## 💰 Bounty Program ### Active Bounties NOFX offers bounties for valuable contributions: | Category | Reward Range | Examples | |----------|--------------|----------| | 🥇 Major Features | $500-1000 | Exchange integration, core architecture | | 🥈 Medium Features | $200-500 | WebSocket support, new AI models | | 🥉 Small Features | $50-200 | Bug fixes, UI improvements, documentation | ### How to Claim Bounties **📖 Complete Guide:** [bounty-guide.md](bounty-guide.md) **Quick Steps:** 1. Find issue tagged `[BOUNTY]` 2. Comment with your proposal 3. Wait for approval 4. Work on the task 5. Submit PR with demo 6. Get paid after merge! ### Current Bounty Tasks | Task | Reward | Difficulty | Status | |------|--------|------------|--------| | [Hyperliquid Integration](bounty-hyperliquid.md) | TBD | Hard | 🟡 Open | | [Aster DEX Integration](bounty-aster.md) | TBD | Medium | ✅ Completed | --- ## 🏆 Recognition ### Ways to Get Recognized **Contributor Levels:** - 🌟 **Active Contributor** - Submit quality PRs - ⭐ **Trusted Contributor** - 3+ merged PRs, given review rights - 💎 **Core Team** - Top contributors, invited by maintainers **Benefits:** - Listed in README and release notes - Direct access to maintainer discussions - Priority support for your issues - Invitation to private roadmap planning ### Hall of Fame **Top Contributors:** - Coming soon! Be the first! 🚀 --- ## 📋 Contribution Types ### Code Contributions - New exchange integrations - AI model adapters - Bug fixes and improvements - Performance optimizations **Required:** - ✅ Code compiles and runs - ✅ Follows code style guidelines - ✅ Includes basic tests (preferred) - ✅ Updates documentation if needed ### Documentation - Tutorial writing - Translation (中文, Русский, Українська) - FAQ updates - Video guides **Rewards:** - $50-200 for comprehensive guides - Recognition in docs - Contributor badge ### Testing & QA - Bug reports with reproduction steps - Security vulnerability reports (see [Security Policy](../../SECURITY.md)) - Testnet verification - Performance testing **Rewards:** - $50-500 for critical bug finds - Up to $1000 for security vulnerabilities - Recognition in security hall of fame --- ## 🌍 Community Channels ### Primary Channels | Platform | Purpose | Link | |----------|---------|------| | 💬 Telegram | Real-time chat, questions | [Join](https://t.me/nofx_dev_community) | | 🐙 GitHub | Issues, PRs, discussions | [Visit](https://github.com/NoFxAiOS/nofx) | | 🐦 Twitter | Announcements, updates | [@nofx_official](https://x.com/nofx_official) | ### Core Team - **Tinkle** - [@Web3Tinkle](https://x.com/Web3Tinkle) - **Tintin** - [@Tintinx2021](https://x.com/Tintinx2021) **Contact:** - Technical questions → Telegram or GitHub Issues - Business inquiries → Twitter DM to core team - Security reports → [SECURITY.md](../../SECURITY.md) --- ## 📅 Community Events ### Regular Activities - **Weekly Updates** - Development progress (Telegram) - **Monthly AMA** - Ask maintainers anything - **Quarterly Roadmap** - Future plans discussion ### Upcoming Events - *No scheduled events yet* **Want to organize an event?** - Contact core team on Telegram - Propose in GitHub Discussions - Tweet and tag @nofx_official --- ## 🎓 Learning Resources ### For Contributors **Understanding NOFX:** - [System Architecture](../architecture/README.md) *(coming soon)* - [API Reference](../architecture/api-reference.md) *(coming soon)* - [Database Schema](../architecture/database-schema.md) *(coming soon)* **Learning Materials:** - Go programming: [Tour of Go](https://go.dev/tour/) - React/TypeScript: [React Docs](https://react.dev/) - Trading basics: [Binance Academy](https://academy.binance.com/) ### Recommended Reading 1. **Before Contributing:** - [Contributing Guide](../../CONTRIBUTING.md) - [Code of Conduct](../../CODE_OF_CONDUCT.md) 2. **For Exchange Integration:** - [Hyperliquid Bounty](bounty-hyperliquid.md) - [Aster Bounty](bounty-aster.md) - Existing code: `trader/binance_futures.go` 3. **For AI Features:** - [Custom API Guide](../getting-started/custom-api.md) - MCP client code: `mcp/client.go` - Decision engine: `decision/engine.go` --- ## 🛡️ Community Guidelines ### Our Values - **Respect** - Treat everyone with courtesy - **Transparency** - Open communication and decisions - **Quality** - High standards for contributions - **Collaboration** - Work together, help each other ### Not Acceptable - ❌ Harassment or discrimination - ❌ Spam or self-promotion - ❌ Sharing malicious code - ❌ Violating [Code of Conduct](../../CODE_OF_CONDUCT.md) **Violations will result in:** 1. Warning 2. Temporary ban 3. Permanent ban (serious cases) --- ## 📊 Community Stats | Metric | Count | |--------|-------| | GitHub Stars | Check [repo](https://github.com/NoFxAiOS/nofx) | | Contributors | 21+ | | Open Issues | Check [issues](https://github.com/NoFxAiOS/nofx/issues) | | Merged PRs | Check [pulls](https://github.com/NoFxAiOS/nofx/pulls?q=is%3Apr+is%3Amerged) | --- ## 🚀 Quick Links - **Want to contribute code?** → [Contributing Guide](../../CONTRIBUTING.md) - **Want to claim bounty?** → [Bounty Guide](bounty-guide.md) - **Found a security issue?** → [Security Policy](../../SECURITY.md) - **Have questions?** → [Telegram Community](https://t.me/nofx_dev_community) - **Verify official accounts?** → [Official Accounts & Anti-Impersonation](OFFICIAL_ACCOUNTS.md) --- [← Back to Documentation Home](../README.md) --- ### Architecture/AGENT CURRENT DESIGN.Zh CN # NOFXi Agent 当前设计说明 ## 目的 本文描述当前 NOFXi Agent 的实际设计,而不是早期版本的理想设计。重点回答这些问题: - 用户消息从哪里进入 - 什么请求会进入 planner - 当前有哪些记忆层 - planner 如何生成与执行 plan - tool 现在是怎么设计的 - 动态快照和当前引用分别解决什么问题 - 为什么某些问题会出现“看起来有历史,但模型还是会追问” 本文对应的主要实现文件: - `agent/agent.go` - `agent/web.go` - `api/agent_routes.go` - `agent/planner_runtime.go` - `agent/execution_state.go` - `agent/memory.go` - `agent/history.go` - `agent/tools.go` ## 一句话总览 当前 Agent 的运行模型可以概括为: 1. 前端把消息发到 `/api/agent/chat/stream` 2. 后端把登录用户身份放进 context 3. Agent 除 `/clear` 和 `/status` 外,其他消息全部进入 planner 4. planner 结合多层记忆、动态快照和 tool schema 生成 plan 5. 执行 plan 中的 `tool / reason / ask_user / respond` 6. 在执行过程中持续更新执行态、短期原话、长期摘要和当前对象引用 ## 请求入口 ### 前端入口 前端 Agent 页面在: - `web/src/pages/AgentChatPage.tsx` 当前聊天使用: - `POST /api/agent/chat/stream` 请求体里会传: - `message` - `lang` - `user_key` ### 后端路由入口 路由注册在: - `api/agent_routes.go` 这里会: 1. 经过 `authMiddleware` 2. 从登录态里取出 `user_id` 3. 通过 `agent.WithStoreUserID(...)` 写入 request context ### Agent Web Handler 真正的 HTTP handler 在: - `agent/web.go` 主要入口: - `HandleChat(...)` - `HandleChatStream(...)` 再往下进入: - `HandleMessageForStoreUser(...)` - `HandleMessageStreamForStoreUser(...)` ## 最外层分流 当前外层分流已经被收口。 在 `agent/agent.go` 中,除了这两个命令之外,其他输入全部交给 planner: - `/clear` - `/status` 也就是说,现在这些都不再在外层直接处理: - setup flow - trade confirmation - direct trade regex - 自然语言配置流程 - 自然语言策略创建 这些都统一进入 planner。 这是当前设计里一个很重要的原则: - 外层分流越少,行为边界越清晰 - 自然语言理解尽量统一交给 planner + tool ## 当前的 5 层记忆 当前不是 3 层,也不是 4 层,而是 5 层: 1. `chatHistory` 2. `TaskState` 3. `ExecutionState` 4. `CurrentReferences` 5. `Persistent Preferences` ### 1. chatHistory 定义位置: - `agent/history.go` 作用: - 保存最近几轮用户 / assistant 原始消息 - 给模型保留最近原话上下文 - 为后续摘要成 `TaskState` 提供原始素材 特点: - 只保留短期原话 - 内存态 - `/clear` 时清空 适合存: - 最近几轮对话原文 - 用户的最新措辞 - 刚刚的自然语言上下文 不适合存: - 长期真相 - 当前外部系统状态 - 当前流程精确执行位置 ### 2. TaskState 定义位置: - `agent/memory.go` 作用: - 保存跨轮次仍然有意义的高层摘要 - 注入 planner / reasoning / final response 持久化 key: - `agent_task_state_` 字段: - `CurrentGoal` - `ActiveFlow` - `OpenLoops` - `ImportantFacts` - `LastDecision` - `UpdatedAt` 适合存: - 当前高层目标 - 跨轮次仍然成立的未闭环事项 - 关键事实 - 最近一次重要决策及其原因 不适合存: - step 级待办 - “下一步调用哪个 tool” - 动态余额、持仓、配置存在性 - 任何可以通过 tool 重新读取的实时状态 ### 3. ExecutionState 定义位置: - `agent/execution_state.go` 作用: - 保存当前 plan 的执行态 - 支持 `ask_user` 之后继续执行 - 保存 plan、当前步骤、执行日志、等待状态等 持久化 key: - `agent_execution_state_` 当前关键字段: - `SessionID` - `Goal` - `Status` - `PlanID` - `Steps` - `CurrentStepID` - `DynamicSnapshots` - `ExecutionLog` - `SummaryNotes` - `Waiting` - `CurrentReferences` - `FinalAnswer` - `LastError` ### 4. CurrentReferences 定义位置: - `agent/execution_state.go` 作用: - 记录当前对话里“这个 / 那个 / 刚才那个”到底指的是谁 当前支持的引用对象: - `strategy` - `trader` - `model` - `exchange` 这是为了解决一种常见问题: - 用户明明前一轮刚说过“激进策略” - 下一轮说“改一下这个策略” - 如果没有结构化引用,模型虽然有聊天历史,也容易重新追问 `CurrentReferences` 不是系统状态快照,而是: - 当前对话焦点对象 - 当前代词绑定对象 ### 5. Persistent Preferences 对应工具: - `get_preferences` - `manage_preferences` 作用: - 保存用户长期偏好 适合存: - 默认中文回复 - 偏好激进风格 - 更关注 BTC / ETH - 不喜欢高频 - 每天固定时间简报 它和 `TaskState` 的区别是: - `TaskState` 偏向当前任务摘要 - `Persistent Preferences` 偏向长期用户画像 ## DynamicSnapshots 是什么 `DynamicSnapshots` 是当前真实系统状态的快照。 它不是历史,也不是长期记忆,而是 planner 在规划前或执行中插入的“当前事实”。 当前会进入快照的典型信息包括: - 当前模型配置列表 - 当前交易所配置列表 - 当前策略列表 - 当前 trader 列表 - 当前余额 - 当前持仓 - 最近交易历史 作用: - 防止 planner 盲信旧结论 - 避免“之前没配置,现在其实已经配好了却还说没有” - 避免“之前余额是 A,现在拿旧 observation 继续回答” 一句话: - `DynamicSnapshots` = 当前世界里真实有什么 ## CurrentReferences 和 DynamicSnapshots 的区别 这两个容易混淆,但职责完全不同。 `DynamicSnapshots`: - 当前系统状态快照 - 是候选集合 / 当前事实 - 例如当前有两个策略:`激进`、`新策略` `CurrentReferences`: - 当前对话焦点对象 - 是“这个”到底指谁 - 例如用户现在说的“这个策略”就是 `激进` 可以这样理解: - `DynamicSnapshots` 是地图 - `CurrentReferences` 是你手指现在指着地图上的哪个点 ## Planner 的输入 planner 主逻辑在: - `agent/planner_runtime.go` 生成计划时,当前会把这些东西一起送给模型: - 当前用户请求 - tool schema - `Persistent Preferences` - `TaskState` - `ExecutionState` - `Resume context` - `Structured waiting state` - `Observation context` 其中 observation context 不是旧版单数组,而是分层后的: - `dynamic_snapshots` - `execution_log` - `summary_notes` ## Plan 的结构 当前 planner 只允许这 4 类 step: - `tool` - `reason` - `ask_user` - `respond` 这意味着现在的 Agent 不是一个“自由发挥的回复器”,而是: - 先规划 - 再执行步骤 - 必要时重规划 ## 步骤执行流程 `executePlan(...)` 的核心逻辑是: 1. 找下一个 pending step 2. 标记 step 为 running 3. 执行对应类型 4. 写回 `ExecutionState` 5. 必要时触发 replanning 不同 step 类型行为如下: ### tool - 调内部 tool - 把结果写入 `ExecutionLog` - 根据结果更新 `CurrentReferences` - 必要时触发 replanner ### reason - 发起一次短 reasoning 调用 - 生成一段简短中间推理 - 写入 `ExecutionLog` ### ask_user - 进入 `waiting_user` - 保存 `WaitingState` - 把问题直接回给用户 ### respond - 生成最终回答 - 标记当前执行完成 ## WaitingState 是什么 `WaitingState` 用来解决: - 用户回复 `是` - 用户回复 `继续` - 用户回复 `那个就行` 这类短回复如果没有结构化等待状态,很容易丢上下文。 当前字段包括: - `Question` - `Intent` - `PendingFields` - `ConfirmationTarget` - `CreatedAt` 它的作用是: - 告诉 planner 上一轮到底在等什么 - 让这轮短回复更容易被理解成“对上一问的回答” ## CurrentReferences 如何更新 当前是双路径更新: ### 1. 用户消息命中对象名时更新 如果用户说: - `修改激进策略` - `停止 lky` - `用 DeepSeek` 系统会去当前用户的策略 / trader / model / exchange 列表里尝试匹配名称或 ID。 匹配成功后,更新 `CurrentReferences`。 ### 2. tool 成功返回对象时更新 比如: - `manage_strategy(create/update/activate)` - `manage_trader(create/update)` - `manage_model_config(update)` - `manage_exchange_config(update)` 只要 tool 返回了具体对象,系统就会把对应 ID / name 写回当前引用。 ## Tool 设计 当前 tool 是“资源型 tool”设计,不是“页面动作型 tool”。 ### 当前主要工具 配置资源: - `get_exchange_configs` - `manage_exchange_config` - `get_model_configs` - `manage_model_config` 策略资源: - `get_strategies` - `manage_strategy` trader 资源: - `manage_trader` 交易 / 查询资源: - `search_stock` - `execute_trade` - `get_positions` - `get_balance` - `get_market_price` - `get_trade_history` ### 为什么这么设计 优点: - tool schema 稳定 - 行为边界清晰 - planner 更容易学会 - 资源增删改查统一 当前 `manage_strategy` 支持: - `list` - `get_default_config` - `create` - `update` - `delete` - `activate` - `duplicate` 当前 `manage_trader` 支持: - `list` - `create` - `update` - `delete` - `start` - `stop` ## 为什么“创建策略”不该默认依赖交易所和模型 当前设计里,策略模板应该是独立资源: - `strategy` 而运行态对象是: - `trader` 更合理的边界是: - 创建策略模板:用 `manage_strategy` - 把策略跑起来:用 `manage_trader` 也就是说: - 策略不默认依赖交易所和模型 - 只有当用户要求“运行 / 部署 / 创建 trader”时,才需要进一步关联 exchange / model / trader ## 当前一个完整例子 用户输入: `帮我创建一个新的激进策略模板,名字就叫激进。创建完后,再把这个策略绑定到 trader lky。` 当前大致流程: 1. 前端请求 `/api/agent/chat/stream` 2. 后端注入 `store_user_id` 3. Agent 进入 planner 4. planner 刷新动态快照: - 当前策略 - 当前 trader 5. 生成 plan,例如: - `get_strategies` - `manage_strategy(create)` - `manage_trader(update)` - `respond` 6. 执行 `manage_strategy(create)` 后: - 写入 `ExecutionLog` - 更新 `CurrentReferences.strategy` 7. 执行 `manage_trader(update)` 时: - 直接使用刚创建策略的 ID 8. 输出最终回复 如果此后用户继续说: `把这个策略的 prompt 改激进一点` 系统会优先从 `CurrentReferences.strategy` 理解“这个策略”。 ## 为什么看起来“有历史”,模型还是会追问 因为“有聊天历史”不等于“有结构化对象绑定”。 如果没有 `CurrentReferences`: - 模型只能依赖原话文本推断“这个策略”是谁 - 一旦中间插入多条消息,或者有多个候选策略 - 就容易重新追问 所以当前设计里,`CurrentReferences` 是补齐这一块的关键。 ## 当前已知限制 ### 1. 外层虽然已经大幅收口,但仍然不是纯 graph runtime 现在比之前更统一,但整体仍然是: - Agent 主入口 - Planner - Tool 执行 而不是完整 node-graph 引擎。 ### 2. ExecutionState 仍然是按 userID 单槽位 这意味着: - 同一用户的多个并行任务仍然可能相互影响 更彻底的方向应该是: - 按 thread / session 多实例存储 ### 3. CurrentReferences 目前还是轻量实现 当前只覆盖: - strategy - trader - model - exchange 后面如果要更强,需要考虑: - 多候选冲突消解 - 昵称映射 - 跨更长会话的稳定实体绑定 ## 当前设计的核心思想 一句话总结: - `chatHistory` 记原话 - `Persistent Preferences` 记长期偏好 - `TaskState` 记高层摘要 - `ExecutionState` 记当前流程 - `DynamicSnapshots` 记当前事实 - `CurrentReferences` 记当前指代对象 - `planner` 决定步骤 - `tools` 执行落地动作 这就是当前 NOFXi Agent 的实际运行设计。 --- ### Architecture/AGENT MEMORY AND PLANNING # NOFXi Agent Memory And Planning Design ## Purpose This document explains how the current NOFXi agent handles: - short-term conversation memory - durable task memory - durable execution / planning state - planner execution and replanning - state reset and resume behavior The implementation described here is primarily in: - `agent/history.go` - `agent/memory.go` - `agent/execution_state.go` - `agent/planner_runtime.go` - `agent/agent.go` ## High-Level Model The current agent uses three different layers of state: 1. `chatHistory` Recent in-memory user/assistant turns for the live conversation. 2. `TaskState` Durable summarized context that should survive beyond recent turns. 3. `ExecutionState` Durable workflow state for the currently running or recently blocked plan. These three layers serve different purposes and should not be treated as the same thing. ## State Layers ### 1. `chatHistory` Defined in `agent/history.go`. Role: - stores recent `user` / `assistant` messages in memory - keyed by `userID` - used as short-term conversational context - acts as the source material for later compression into `TaskState` Characteristics: - in-memory only - capped by `maxTurns` - cleared by `/clear` - not suitable as durable truth Typical contents: - the last few user questions - the last few assistant replies - temporary conversational wording ### 2. `TaskState` Defined in `agent/memory.go`. Role: - stores durable, structured, non-derivable context - persisted through `system_config` - injected into planning and reasoning prompts Storage key: - `agent_task_state_` Fields: - `CurrentGoal` - `ActiveFlow` - `OpenLoops` - `ImportantFacts` - `LastDecision` - `UpdatedAt` Intended contents: - user goal that still matters across turns - high-level unresolved issues that still matter across turns - facts that tools cannot cheaply re-fetch - latest important decision summary Explicitly not intended for: - step-level pending items such as "wait for API key" - execution actions such as "call get_exchange_configs" - live balances - current positions - current market prices - mutable configuration availability Those should be checked from tools at planning time instead of being trusted from old summaries. ### 3. `ExecutionState` Defined in `agent/execution_state.go`. Role: - stores the current execution workflow - allows the agent to resume after `ask_user` - persists plan steps, observations, and completion status Storage key: - `agent_execution_state_` Fields: - `SessionID` - `UserID` - `Goal` - `Status` - `PlanID` - `Steps` - `CurrentStepID` - `Observations` - `FinalAnswer` - `LastError` - `UpdatedAt` This is the planner's working state, not a general memory store. ## Data Flow ### Request Entry Entry points: - `HandleMessage(...)` - `HandleMessageStream(...)` Flow: 1. user message enters `agent` 2. slash commands and explicit direct branches are handled first 3. all other requests go into planner flow via `thinkAndAct(...)` / `thinkAndActStream(...)` ### Planner Flow The planner pipeline in `agent/planner_runtime.go` is: 1. append user message into `chatHistory` 2. emit `planning` SSE event 3. load `ExecutionState` 4. optionally reset stale `ExecutionState` 5. optionally refresh dynamic configuration snapshots 6. create a fresh execution plan with the LLM 7. execute steps one by one 8. persist `ExecutionState` after important transitions 9. append assistant answer into `chatHistory` 10. maybe compress old conversation into `TaskState` ## Short-Term vs Durable Memory ### What lives in `chatHistory` Good fits: - raw recent messages - conversational wording - latest assistant phrasing Bad fits: - long-lived truths - current external system state ### What lives in `TaskState` Good fits: - durable goal - high-level unfinished work that remains relevant across turns - important facts the user stated - previous decisions and why they were made Bad fits: - pending steps inside the current plan - execution-level reminders such as "wait for a field" or "call a tool" - old conclusions about whether tools exist - old conclusions about whether model/exchange config is present - live operational state that can change outside the chat ### What lives in `ExecutionState` Good fits: - current plan steps - observations from tool calls - blocked-on-user-input status - exact current workflow state - step-level pending work and block reasons Bad fits: - evergreen user profile - long-term semantic memory ## Planning Logic ### Plan Creation `createExecutionPlan(...)` sends the following into the planner model: - available tool definitions - persistent preferences - `TaskState` context - `ExecutionState` JSON - current user request The planner must return JSON only with step types: - `tool` - `reason` - `ask_user` - `respond` ### Step Execution `executePlan(...)` executes the plan loop: - `tool` call tool and append observation - `reason` run reasoning sub-call and append observation - `ask_user` save `waiting_user` state and return question - `respond` generate final answer and mark completed After each completed step, `replanAfterStep(...)` may: - continue - replace remaining steps - ask user - finish ## Resume Behavior When `ExecutionState.Status == waiting_user`, the next user turn is treated as a reply to the pending question. Current safeguards: - latest asked question is extracted from the stored plan - the user reply is appended as a `user_reply` observation - planner prompt receives explicit `Resume context` This prevents short replies like `是` from being misread as unrelated fresh intents as often as before. ## Dynamic State Refresh Configuration and trader management requests are dynamic by nature. Their truth can change outside the current chat, for example: - user configures exchange in the UI - user adds model in another tab - user creates trader elsewhere Because of that, configuration/trader requests should not trust stale model conclusions. Current protection in `planner_runtime.go`: - detects config / trader intent with `isConfigOrTraderIntent(...)` - clears `TaskState` context from the planner prompt for these requests - refreshes `ExecutionState.Observations` with fresh snapshots from: - `toolGetModelConfigs(...)` - `toolGetExchangeConfigs(...)` - `toolListTraders(...)` This makes the planner rely more on current system state and less on older narrative memory. ## Reset Strategy The system currently resets or weakens stale execution state when: - user says retry-like phrases such as `再试`, `继续`, `try again`, `continue` - request is config / trader related and old execution state is failed / completed / waiting Reset scope: - `ExecutionState` may be cleared - `TaskState` is not globally deleted, but it is intentionally ignored for config/trader planning Manual reset: - `/clear` This clears: - short-term chat history - task state - execution state ## Compression Design `maybeCompressHistory(...)` moves older short-term chat content into `TaskState` when: - recent message count exceeds the configured window - estimated token count exceeds the threshold Compression strategy: 1. keep recent conversation in `chatHistory` 2. summarize older turns into structured `TaskState` 3. persist new `TaskState` 4. replace `chatHistory` with recent slice Important design rule: - `TaskState` should keep durable context only - it should not become a stale copy of mutable operational state ## Current Architecture Diagram ```mermaid flowchart TD U[User Message] --> A[HandleMessage / HandleMessageStream] A --> B{Direct command?} B -->|Yes| C[Direct branch or slash command] B -->|No| D[thinkAndAct / thinkAndActStream] D --> E[Append user turn to chatHistory] D --> F[Load ExecutionState] F --> G{waiting_user?} G -->|Yes| H[Attach user_reply observation] G -->|No| I[Create fresh ExecutionState] H --> J[Refresh dynamic snapshots if config/trader intent] I --> J J --> K[createExecutionPlan via LLM] K --> L[Execution plan] L --> M[executePlan loop] M --> N[tool step] M --> O[reason step] M --> P[ask_user step] M --> Q[respond step] N --> R[Append Observation] O --> R R --> S[replanAfterStep] S --> M P --> T[Persist waiting_user ExecutionState] T --> UQ[Return question to user] Q --> V[Persist completed ExecutionState] V --> W[Append assistant turn to chatHistory] W --> X[maybeCompressHistory] X --> Y[Persist TaskState] Y --> Z[Final response] ``` ## Memory Relationship Diagram ```mermaid flowchart LR CH[chatHistory\nin-memory\nrecent turns] TS[TaskState\npersisted summary\nsystem_config] ES[ExecutionState\npersisted workflow\nsystem_config] PL[Planner Prompt] CH -->|recent raw turns| PL ES -->|current workflow JSON| PL TS -->|durable structured context| PL CH -->|old turns compressed| TS PL -->|plan / observations / status| ES ``` ## State Transition Diagram ```mermaid stateDiagram-v2 [*] --> planning planning --> running: plan created running --> waiting_user: ask_user step waiting_user --> planning: user replies running --> completed: respond step finished running --> failed: step error failed --> planning: retry / continue / config-trader reset completed --> planning: new relevant request or retry flow ``` ## Known Design Tradeoffs ### Strengths - separates short-term chat from durable task summary - allows blocked flows to resume - supports replanning after every meaningful step - can recover from stale assumptions better for dynamic config/trader requests ### Weaknesses - `TaskState` is still summary-driven, so summarization quality matters - planner still depends on model compliance for some transitions - `ExecutionState` is single-track per user, not multiple concurrent workflows - config/trader intent detection is heuristic and keyword-based ## Practical Guidance ### When to trust `TaskState` Trust it for: - user intent continuity - open loops - durable facts Do not trust it for: - whether current exchange/model/trader config exists now - whether a specific operational action is currently possible ### When to trust `ExecutionState` Trust it for: - current plan continuity - exact blocked step - latest observation chain Do not trust it blindly when: - user has changed configuration outside the chat - the system capabilities changed after deployment ### When to fetch live state again Always prefer fresh tool snapshots before answering about: - existing model configs - existing exchange configs - existing traders - whether trader creation can proceed ## Suggested Future Improvements - add workflow versioning so capability changes invalidate stale `ExecutionState` - separate `waiting_user_confirmation` from generic `waiting_user` - introduce code-level handling for short confirmations such as `是`, `好`, `继续` - move dynamic state refresh from heuristic to explicit planner preflight stage - support multiple concurrent execution sessions per user if needed --- ### Architecture/AGENT MEMORY AND PLANNING.Zh CN # NOFXi Agent 记忆与规划设计 ## 目的 本文说明当前 NOFXi agent 是如何处理以下能力的: - 短期对话记忆 - 持久化任务记忆 - 持久化执行态 / 规划态 - planner 的执行与重规划 - 状态重置与恢复 本文主要对应以下实现文件: - `agent/history.go` - `agent/memory.go` - `agent/execution_state.go` - `agent/planner_runtime.go` - `agent/agent.go` ## 总体模型 当前 agent 使用三层不同的状态: 1. `chatHistory` 用于保存当前会话最近几轮的原始用户/助手对话,驻留内存。 2. `TaskState` 用于保存跨轮次仍然有价值的结构化摘要,持久化存储。 3. `ExecutionState` 用于保存当前规划流程的执行态,支持流程中断后的继续执行。 这三层职责不同,不能混为一谈。 ## 三层状态 ### 1. `chatHistory` 定义位置:`agent/history.go` 作用: - 按 `userID` 保存最近的 `user` / `assistant` 消息 - 作为短期对话上下文 - 作为后续压缩进 `TaskState` 的原始素材 特性: - 仅在内存中存在 - 有 `maxTurns` 上限 - `/clear` 时会清空 - 不适合作为长期真相来源 典型内容: - 最近几轮用户问题 - 最近几轮助手回答 - 临时措辞与上下文表达 ### 2. `TaskState` 定义位置:`agent/memory.go` 作用: - 保存持久化、结构化、不可轻易从工具重新推导出的上下文 - 通过 `system_config` 持久化 - 注入到 planner / reasoning prompt 中 存储 key: - `agent_task_state_` 字段: - `CurrentGoal` - `ActiveFlow` - `OpenLoops` - `ImportantFacts` - `LastDecision` - `UpdatedAt` 适合存放: - 当前仍有效的用户目标 - 跨轮次仍然成立的高层未闭环问题 - 无法简单通过工具重新读取的重要事实 - 最近一次关键决策及原因 不适合存放: - “等用户提供 API Key” 这类 step 级待办 - “调用 get_exchange_configs” 这类执行动作 - 实时余额 - 当前持仓 - 当前行情价格 - 是否存在某个配置这类会变化的状态 这些动态信息应该在规划阶段通过工具重新检查,而不是相信旧摘要。 ### 3. `ExecutionState` 定义位置:`agent/execution_state.go` 作用: - 保存当前执行中的工作流状态 - 支持 `ask_user` 之后恢复执行 - 持久化保存计划步骤、观察结果和最终状态 存储 key: - `agent_execution_state_` 字段: - `SessionID` - `UserID` - `Goal` - `Status` - `PlanID` - `Steps` - `CurrentStepID` - `Observations` - `FinalAnswer` - `LastError` - `UpdatedAt` 它是 planner 的“工作态”,不是通用记忆仓库。 ## 数据流 ### 请求入口 入口函数: - `HandleMessage(...)` - `HandleMessageStream(...)` 流程: 1. 用户消息进入 `agent` 2. 优先处理 slash command 和显式直达分支 3. 其余请求进入 planner 流程:`thinkAndAct(...)` / `thinkAndActStream(...)` ### Planner 主流程 `agent/planner_runtime.go` 中的 planner 管线如下: 1. 把用户消息加入 `chatHistory` 2. 发出 `planning` SSE 事件 3. 加载 `ExecutionState` 4. 视情况重置过期的 `ExecutionState` 5. 视情况刷新动态配置快照 6. 调用 LLM 生成新的执行计划 7. 按步骤执行计划 8. 在关键状态变化后持久化 `ExecutionState` 9. 把助手回答加入 `chatHistory` 10. 视情况把旧对话压缩进 `TaskState` ## 短期记忆 vs 持久记忆 ### `chatHistory` 里应该放什么 适合: - 最近原始消息 - 对话措辞 - 最近一轮助手的表达方式 不适合: - 长期真相 - 外部系统当前状态 ### `TaskState` 里应该放什么 适合: - 持续目标 - 跨轮次仍有意义的高层未闭环事项 - 用户明确讲过的重要事实 - 历史关键决策和原因 不适合: - 当前 plan 中尚未执行的步骤 - “等待某个字段”“调用某个 tool” 这类执行级待办 - “系统有没有这个工具” 这种过时结论 - “当前有没有模型/交易所配置” 这种可变化状态 - 可以通过工具重新查询到的动态状态 ### `ExecutionState` 里应该放什么 适合: - 当前计划步骤 - 工具调用观察结果 - 当前是否卡在等用户补充信息 - 当前工作流的精确执行位置 - step 级待办和阻塞原因 不适合: - 长期用户画像 - 通用长期语义记忆 ## 规划逻辑 ### 计划生成 `createExecutionPlan(...)` 会把以下信息送给 planner 模型: - 当前可用 tool 定义 - 持久化用户偏好 - `TaskState` 上下文 - `ExecutionState` JSON - 当前用户请求 planner 必须返回 JSON,且步骤类型只能是: - `tool` - `reason` - `ask_user` - `respond` ### 步骤执行 `executePlan(...)` 的执行循环如下: - `tool` 调用工具并写入 observation - `reason` 发起 reasoning 子调用并写入 observation - `ask_user` 保存 `waiting_user` 状态并把问题返回给用户 - `respond` 生成最终回答并标记完成 每个步骤结束后,`replanAfterStep(...)` 还可以决定: - continue - replace_remaining - ask_user - finish ## 恢复执行 当 `ExecutionState.Status == waiting_user` 时,下一条用户消息会被视为对上一轮追问的回复。 当前保护机制: - 从已有 plan 中提取最近一次追问内容 - 将用户回复作为 `user_reply` observation 追加 - 在 planner prompt 中注入显式的 `Resume context` 这样可以减少用户只回复 `是` 这类短消息时,被错误理解成全新意图的情况。 ## 动态状态刷新 配置类与 trader 管理类请求本质上是动态请求,它们的真相可能在聊天之外发生变化,例如: - 用户在 Web UI 中配置了交易所 - 用户在另一个页面新增了模型 - 用户在别处创建了 trader 因此,这类请求不能依赖旧的模型结论。 当前在 `planner_runtime.go` 中的保护措施: - 通过 `isConfigOrTraderIntent(...)` 检测配置 / trader 意图 - 这类请求在 planner prompt 中不再注入旧 `TaskState` - 同时刷新 `ExecutionState.Observations` 中的实时快照: - `toolGetModelConfigs(...)` - `toolGetExchangeConfigs(...)` - `toolListTraders(...)` 这样 planner 会更多依赖当前系统状态,而不是依赖旧记忆中的描述。 ## 重置策略 当前系统在以下场景会重置或弱化旧执行态: - 用户说了类似 `再试`、`继续`、`try again`、`continue` - 当前请求是配置 / trader 相关,并且旧 `ExecutionState` 已经失败 / 完成 / 正在等待用户 重置范围: - `ExecutionState` 可能会被清空 - `TaskState` 不会整体删除,但在配置 / trader 请求中会被主动忽略 手动清理: - `/clear` 这条命令会清掉: - 短期 chat history - task state - execution state ## 压缩设计 `maybeCompressHistory(...)` 会在以下条件满足时把旧的短期对话压缩进 `TaskState`: - 最近消息数超过窗口 - 估算 token 数超过阈值 压缩流程: 1. 保留最近若干轮对话在 `chatHistory` 2. 把更早的内容总结成结构化 `TaskState` 3. 持久化新的 `TaskState` 4. 用最近消息切片替换 `chatHistory` 重要设计原则: - `TaskState` 只保留长期有效上下文 - 不能把它变成动态运营状态的陈旧副本 ## 当前架构图 ```mermaid flowchart TD U[用户消息] --> A[HandleMessage / HandleMessageStream] A --> B{是否命中直达分支?} B -->|是| C[直接处理 slash command 或快捷分支] B -->|否| D[thinkAndAct / thinkAndActStream] D --> E[写入 chatHistory] D --> F[加载 ExecutionState] F --> G{是否 waiting_user?} G -->|是| H[追加 user_reply observation] G -->|否| I[创建新的 ExecutionState] H --> J[若为配置或 trader 请求则刷新动态快照] I --> J J --> K[createExecutionPlan 调用 LLM] K --> L[得到 execution plan] L --> M[executePlan 循环执行] M --> N[tool step] M --> O[reason step] M --> P[ask_user step] M --> Q[respond step] N --> R[写入 Observation] O --> R R --> S[replanAfterStep] S --> M P --> T[持久化 waiting_user ExecutionState] T --> UQ[向用户返回追问] Q --> V[持久化 completed ExecutionState] V --> W[把 assistant 回复写入 chatHistory] W --> X[maybeCompressHistory] X --> Y[持久化 TaskState] Y --> Z[返回最终回答] ``` ## 记忆关系图 ```mermaid flowchart LR CH[chatHistory\n内存态\n最近对话] TS[TaskState\n持久化摘要\nsystem_config] ES[ExecutionState\n持久化执行态\nsystem_config] PL[Planner Prompt] CH -->|最近原始对话| PL ES -->|当前工作流 JSON| PL TS -->|长期结构化上下文| PL CH -->|旧消息压缩| TS PL -->|计划 / 观察 / 状态| ES ``` ## 状态转换图 ```mermaid stateDiagram-v2 [*] --> planning planning --> running: plan created running --> waiting_user: ask_user step waiting_user --> planning: user replies running --> completed: respond step finished running --> failed: step error failed --> planning: retry / continue / config-trader reset completed --> planning: new relevant request or retry flow ``` ## 当前设计的取舍 ### 优点 - 将短期对话与长期摘要分离 - 支持在 `ask_user` 之后恢复执行 - 每个关键步骤后都支持重规划 - 对配置 / 创建 trader 这类动态请求,已经能更好抵抗旧结论污染 ### 缺点 - `TaskState` 的质量仍然依赖总结效果 - 某些恢复逻辑仍依赖模型是否听话 - 每个用户当前只有一条 `ExecutionState`,不支持多个并发工作流 - 配置 / trader 意图识别目前仍是关键词启发式 ## 实践建议 ### 什么时候该相信 `TaskState` 应该相信它用于: - 延续用户目标 - 跟踪未完成事项 - 保留长期有效事实 不应该相信它用于: - 当前是否存在模型 / 交易所 / trader 配置 - 当前是否能够执行某个操作 ### 什么时候该相信 `ExecutionState` 应该相信它用于: - 当前工作流是否仍然连续 - 当前阻塞在哪一步 - 最近的 observation 链条 不应该盲信它用于: - 用户在聊天外已经修改过配置的场景 - 系统能力或工具集发生变化后的旧结论 ### 什么时候必须重新获取实时状态 以下场景应该优先重新通过工具获取: - 当前模型配置 - 当前交易所配置 - 当前 trader 列表 - 当前是否满足 trader 创建条件 ## 后续建议 - 为 `ExecutionState` 增加版本号或能力签名,能力变化时自动失效 - 将 `waiting_user_confirmation` 与通用 `waiting_user` 分开 - 对 `是`、`好`、`继续` 这类短确认增加代码级识别 - 将动态快照刷新从启发式升级为显式 planner 预检查阶段 - 如果后续需要,支持一个用户多条并发执行会话 --- ### Architecture/README # NOFX Architecture Documentation **Language:** [English](README.md) | [中文](README.zh-CN.md) Technical documentation for developers who want to understand NOFX internals. --- ## Overview NOFX is a full-stack AI trading platform for cryptocurrency and US stock markets: - **Backend:** Go (Gin framework, SQLite) - **Frontend:** React/TypeScript (Vite, TailwindCSS) - **AI Models:** DeepSeek, Qwen, OpenAI (GPT-5.2), Claude, Gemini, Grok, Kimi - **Exchanges:** Binance, Bybit, OKX, Hyperliquid, Aster, Lighter --- ## System Architecture ``` /* Detailed source-code truncated for AI context efficiency. */ ``` --- ## Module Documentation ### Core Modules | Module | Description | Documentation | |--------|-------------|---------------| | **Strategy Studio** | Strategy configuration, coin selection, data assembly, AI prompts | [STRATEGY_MODULE.md](STRATEGY_MODULE.md) | ### Module Overview #### Strategy Module Complete strategy configuration system including: - Coin source selection (static list, AI500 pool, OI ranking) - Market data indicators (K-lines, EMA, MACD, RSI, ATR) - Prompt construction (system prompt, user prompt, sections) - AI response parsing and decision execution - Risk control enforcement **[Read Full Documentation →](STRATEGY_MODULE.md)** --- ## Project Structure ``` nofx/ ├── main.go # Entry point ├── api/ # HTTP API (Gin framework) ├── trader/ # Trading execution layer ├── strategy/ # Strategy engine ├── market/ # Market data service ├── mcp/ # AI model clients ├── store/ # Database operations ├── auth/ # JWT authentication ├── manager/ # Multi-trader management └── web/ # React frontend ├── src/pages/ # Page components ├── src/components/ # Shared components └── src/lib/api.ts # API client ``` --- ## Core Dependencies ### Backend (Go) | Package | Purpose | |---------|---------| | `gin-gonic/gin` | HTTP API framework | | `adshao/go-binance` | Binance API client | | `markcheno/go-talib` | Technical indicators | | `golang-jwt/jwt` | JWT authentication | ### Frontend (React) | Package | Purpose | |---------|---------| | `react` | UI framework | | `recharts` | Charts and visualizations | | `swr` | Data fetching | | `zustand` | State management | | `tailwindcss` | CSS framework | --- ## Quick Links - [Strategy Module](STRATEGY_MODULE.md) - How strategies work - [Getting Started](../getting-started/README.md) - Setup guide - [FAQ](../faq/README.md) - Frequently asked questions --- ## For Developers **Want to contribute?** - Read the module documentation above - Check [Open Issues](https://github.com/NoFxAiOS/nofx/issues) - Join our community **Repository:** https://github.com/NoFxAiOS/nofx --- [← Back to Documentation](../README.md) --- ### Architecture/README.Zh CN # NOFX 架构文档 **语言:** [English](README.md) | [中文](README.zh-CN.md) 为希望了解 NOFX 内部实现的开发者提供的技术文档。 --- ## 概述 NOFX 是一个支持加密货币和美股市场的全栈 AI 交易平台: - **后端:** Go (Gin 框架, SQLite) - **前端:** React/TypeScript (Vite, TailwindCSS) - **AI 模型:** DeepSeek, Qwen, OpenAI (GPT-5.2), Claude, Gemini, Grok, Kimi - **交易所:** Binance, Bybit, OKX, Hyperliquid, Aster, Lighter --- ## 系统架构 ``` /* Detailed source-code truncated for AI context efficiency. */ ``` --- ## 模块文档 ### 核心模块 | 模块 | 描述 | 文档 | |------|------|------| | **策略工作室** | 策略配置、币种选择、数据组装、AI 提示词 | [STRATEGY_MODULE.md](STRATEGY_MODULE.md) | ### 模块概览 #### 策略模块 完整的策略配置系统,包括: - 币种来源选择(静态列表、AI500 币池、OI 排行) - 市场数据指标(K线、EMA、MACD、RSI、ATR) - 提示词构建(系统提示词、用户提示词、分段配置) - AI 响应解析和决策执行 - 风险控制强制执行 **[阅读完整文档 →](STRATEGY_MODULE.md)** --- ## 项目结构 ``` nofx/ ├── main.go # 程序入口 ├── api/ # HTTP API (Gin 框架) ├── trader/ # 交易执行层 ├── strategy/ # 策略引擎 ├── market/ # 行情数据服务 ├── mcp/ # AI 模型客户端 ├── store/ # 数据库操作 ├── auth/ # JWT 认证 ├── manager/ # 多交易员管理 └── web/ # React 前端 ├── src/pages/ # 页面组件 ├── src/components/ # 共享组件 └── src/lib/api.ts # API 客户端 ``` --- ## 核心依赖 ### 后端 (Go) | 包 | 用途 | |---------|---------| | `gin-gonic/gin` | HTTP API 框架 | | `adshao/go-binance` | Binance API 客户端 | | `markcheno/go-talib` | 技术指标计算 | | `golang-jwt/jwt` | JWT 认证 | ### 前端 (React) | 包 | 用途 | |---------|---------| | `react` | UI 框架 | | `recharts` | 图表可视化 | | `swr` | 数据获取 | | `zustand` | 状态管理 | | `tailwindcss` | CSS 框架 | --- ## 快速链接 - [策略模块](STRATEGY_MODULE.md) - 策略如何运作 - [快速开始](../getting-started/README.zh-CN.md) - 部署指南 - [常见问题](../faq/README.md) - FAQ --- ## 开发者资源 **想要贡献?** - 阅读上方的模块文档 - 查看 [Open Issues](https://github.com/NoFxAiOS/nofx/issues) - 加入我们的社区 **代码仓库:** https://github.com/NoFxAiOS/nofx --- [← 返回文档首页](../README.md) --- ### Architecture/STRATEGY MODULE # NOFX Strategy Module - Technical Documentation **Language:** [English](STRATEGY_MODULE.md) | [中文](STRATEGY_MODULE.zh-CN.md) ## Overview This document describes the complete data flow of the NOFX strategy module, including coin selection, data assembly, prompt construction, AI request, response parsing, and decision execution. --- ## Complete Data Flow ``` /* Detailed source-code truncated for AI context efficiency. */ ``` --- ## 1. Coin Selection **Core File:** `decision/engine.go:380-454` **Entry Method:** `StrategyEngine.GetCandidateCoins()` ### 1.1 Static Coin List ```go // decision/engine.go:395-403 if config.CoinSource.SourceType == "static" { for _, symbol := range config.CoinSource.StaticCoins { coins = append(coins, CandidateCoin{ Symbol: market.Normalize(symbol), Sources: []string{"static"}, }) } } ``` - **Config:** `StrategyConfig.CoinSource.StaticCoins` - **Usage:** Manually specify trading coins - **Tag:** `["static"]` ### 1.2 AI500 Coin Pool ```go // decision/engine.go:405-406, 456-474 func (e *StrategyEngine) getCoinPoolCoins(limit int) []CandidateCoin { coins, err := e.provider.GetTopRatedCoins(limit) // ... for _, coin := range coins { result = append(result, CandidateCoin{ Symbol: coin.Symbol, Sources: []string{"ai500"}, }) } } ``` - **API:** `config.CoinSource.CoinPoolAPIURL` - **Usage:** Get top N coins by AI rating - **Tag:** `["ai500"]` ### 1.3 OI Top Coins (Position Growth Ranking) ```go // decision/engine.go:408-409, 476-498 func (e *StrategyEngine) getOITopCoins() []CandidateCoin { positions, err := e.provider.GetOITopPositions() // ... for _, pos := range positions { result = append(result, CandidateCoin{ Symbol: pos.Symbol, Sources: []string{"oi_top"}, }) } } ``` - **API:** `config.CoinSource.OITopAPIURL` - **Usage:** Get coins with fastest OI growth - **Tag:** `["oi_top"]` ### 1.4 Mixed Mode ```go // decision/engine.go:411-449 if config.CoinSource.SourceType == "mixed" { if config.CoinSource.UseCoinPool { // Add AI500 coins } if config.CoinSource.UseOITop { // Add OI Top coins } if len(config.CoinSource.StaticCoins) > 0 { // Add static coins } // Deduplicate and merge, keep multi-source tags } ``` - **Feature:** Use multiple data sources simultaneously - **Tag Example:** `["ai500", "oi_top"]` (dual signal coin) --- ## 2. Data Assembly **Core File:** `trader/auto_trader.go:562-791`, `decision/engine.go:299-374` **Entry Method:** `AutoTrader.buildTradingContext()` ### 2.1 Account Data ```go // trader/auto_trader.go:565-583 balance, err := at.trader.GetBalance() equity := balance["total_equity"].(float64) available := balance["available_balance"].(float64) unrealizedPnL := balance["total_pnl"].(float64) ``` **Extracted Fields:** - `total_equity` - Total account equity - `available_balance` - Available balance - `total_pnl` - Unrealized PnL ### 2.2 Position Data ```go // trader/auto_trader.go:588-682 positions, err := at.trader.GetPositions() for _, pos := range positions { position := decision.Position{ Symbol: pos.Symbol, Side: pos.Side, // "long" / "short" EntryPrice: pos.EntryPrice, MarkPrice: pos.MarkPrice, Quantity: pos.Quantity, Leverage: pos.Leverage, UnrealizedPnL: pos.UnrealizedPnL, LiquidationPrice: pos.LiquidationPrice, } } ``` ### 2.3 Market Data Fetching ```go // decision/engine.go:299-374 func (e *StrategyEngine) fetchMarketDataWithStrategy(symbols []string) map[string]*market.Data { timeframes := config.Indicators.Klines.SelectedTimeframes // ["5m", "15m", "1h", "4h"] primaryTF := config.Indicators.Klines.PrimaryTimeframe // "5m" count := config.Indicators.Klines.PrimaryCount // 30 for _, symbol := range symbols { data := market.GetWithTimeframes(symbol, timeframes, primaryTF, count) result[symbol] = data } } ``` ### 2.4 Technical Indicator Calculation **File:** `market/data.go:59-98` | Indicator | Config | Calculation | |-----------|--------|-------------| | **EMA** | `EnableEMA`, `EMAPeriods` | `calculateEMA(klines, period)` | | **MACD** | `EnableMACD` | `calculateMACD(klines)` - 12/26/9 | | **RSI** | `EnableRSI`, `RSIPeriods` | `calculateRSI(klines, period)` | | **ATR** | `EnableATR`, `ATRPeriods` | `calculateATR(klines, period)` | | **Volume** | `EnableVolume` | Raw volume data | | **OI** | `EnableOI` | Open interest data | | **Funding Rate** | `EnableFundingRate` | Funding rate | ### 2.5 Quant Data (Optional) ```go // trader/auto_trader.go:759-778 if config.Indicators.EnableQuantData { quantData := provider.GetQuantData(symbol) // Contains: Capital flow, OI changes, Price changes } ``` **Data Structure:** ```go QuantData { Netflow { Institution: {Future, Spot}, // Institutional flow Personal: {Future, Spot} // Retail flow }, OI { CurrentOI: float64, Delta: {1h, 4h, 24h} // OI changes }, PriceChange { "1h", "4h", "24h": float64 // Price change % } } ``` --- ## 3. System Prompt **Core File:** `decision/engine.go:700-818` **Entry Method:** `StrategyEngine.BuildSystemPrompt(accountEquity, variant)` ### 3.1 Prompt Structure (8 Sections) ``` 1. Role Definition [Editable] 2. Trading Mode Variant [Runtime determined] 3. Hard Constraints [Code enforced + AI guided] 4. Trading Frequency [Editable] 5. Entry Standards [Editable] 6. Decision Process [Editable] 7. Output Format [Fixed XML + JSON structure] 8. Custom Prompt [Optional] ``` ### 3.2 Role Definition ```go // decision/engine.go:706-713 roleDefinition := config.PromptSections.RoleDefinition if roleDefinition == "" { roleDefinition = "You are a professional cryptocurrency trading AI..." } ``` ### 3.3 Trading Mode Variants | Mode | Characteristics | |------|-----------------| | `aggressive` | Trend breakout, higher position tolerance | | `conservative` | Multi-signal confirmation, conservative money management | | `scalping` | Short-term momentum, tight take-profit | ### 3.4 Hard Constraints **Code Enforced:** ```go // decision/engine.go:725-749 maxPositions := config.RiskControl.MaxPositions // Default: 3 altcoinMaxRatio := config.RiskControl.AltcoinMaxPositionValueRatio // Default: 1.0 btcethMaxRatio := config.RiskControl.BTCETHMaxPositionValueRatio // Default: 5.0 maxMarginUsage := config.RiskControl.MaxMarginUsage // Default: 90% minPositionSize := config.RiskControl.MinPositionSize // Default: 12 USDT ``` **AI Guided (Suggested Values):** ```go altcoinMaxLeverage := config.RiskControl.AltcoinMaxLeverage // Default: 5x btcethMaxLeverage := config.RiskControl.BTCETHMaxLeverage // Default: 5x minRiskRewardRatio := config.RiskControl.MinRiskRewardRatio // Default: 1:3 minConfidence := config.RiskControl.MinConfidence // Default: 75 ``` ### 3.5 Output Format Requirements ```xml [Chain of Thought analysis process] ```json [ { "symbol": "BTCUSDT", "action": "open_long", "leverage": 5, "position_size_usd": 100.00, "stop_loss": 65000.00, "take_profit": 72000.00, "confidence": 85, "risk_usd": 20.00, "reasoning": "..." } ] ``` ``` --- ## 4. User Prompt **Core File:** `decision/engine.go:884-1007` **Entry Method:** `StrategyEngine.BuildUserPrompt(ctx)` ### 4.1 Prompt Content Structure ``` 1. System Status [Time, cycle number, runtime] 2. BTC Market Overview [Price, change%, MACD, RSI] 3. Account Info [Equity, balance%, PnL%, margin%, positions] 4. Recent Trades [Last 10 closed trades] 5. Current Positions [Detailed position data + indicators] 6. Candidate Coins [Full market data] 7. Quant Data [Capital flow, OI data] (optional) 8. OI Ranking Data [Market OI change ranking] (optional) ``` ### 4.2 Account Info Format ``` Account: Equity 1000.00 | Balance 800.00 (80.0%) | PnL +5.5% | Margin 20.0% | Positions 2 ``` ### 4.3 Position Info Format ``` 1. BTCUSDT LONG | Entry 68000.0000 Current 69500.0000 Qty 0.0100 | Position Value $695.00 PnL +2.21% | Amount +$15.00 Peak PnL +3.50% | Leverage 5x Margin $139.00 | Liquidation Price 55000.0000 Holding Duration 2 hours 30 minutes Market: price=69500, ema20=68800, macd=150.5, rsi7=62.3 OI: Latest=15000000, Avg=14500000 Funding Rate: 0.0100% ``` ### 4.4 Candidate Coin Format ``` ### 1. ETHUSDT (AI500+OI_Top dual signal) current_price = 3500.00, current_ema20 = 3450.00, current_macd = 25.5, current_rsi7 = 58.0 Open Interest: Latest: 8500000.00 Average: 8200000.00 Funding Rate: 0.0050 === 5M TIMEFRAME (oldest → latest) === Prices: [3480, 3485, 3490, 3495, 3500] Volumes: [1000, 1200, 1100, 1300, 1150] EMA20: [3470, 3475, 3478, 3482, 3485] MACD: [20.1, 21.5, 22.8, 24.0, 25.5] RSI7: [55.0, 56.2, 57.1, 57.8, 58.0] === 15M TIMEFRAME === ... ``` --- ## 5. AI Request **Core File:** `decision/engine.go:222-293`, `mcp/client.go:136-150` ### 5.1 Request Flow ```go // decision/engine.go:263-268 aiCallStart := time.Now() aiResponse, err := mcpClient.CallWithMessages(systemPrompt, userPrompt) aiCallDuration := time.Since(aiCallStart) ``` ### 5.2 Supported AI Models | Model | Client File | Default Model | |-------|-------------|---------------| | **DeepSeek** | `mcp/deepseek_client.go` | deepseek-chat | | **Qwen** | `mcp/qwen_client.go` | qwen-max | | **Claude** | `mcp/claude_client.go` | claude-3-5-sonnet | | **Gemini** | `mcp/gemini_client.go` | gemini-pro | | **Grok** | `mcp/grok_client.go` | grok-beta | | **OpenAI** | `mcp/openai_client.go` | gpt-5.2 | | **Kimi** | `mcp/kimi_client.go` | moonshot-v1-8k | ### 5.3 Request Parameters ```go // mcp/client.go Timeout: 120 seconds MaxRetries: 3 RetryDelay: 2 seconds (exponential backoff) ``` --- ## 6. AI Response Parsing **Core File:** `decision/engine.go:1303-1604` **Entry Method:** `parseFullDecisionResponse(response, accountEquity, leverage, ratio)` ### 6.1 Parsing Flow ``` Raw AI Response (text) ↓ 1. Extract Chain of Thought [extractCoTTrace()] ↓ 2. Extract JSON Decision [extractDecisions()] ↓ 3. Validate JSON Format [validateJSONFormat()] ↓ 4. Parse JSON [json.Unmarshal()] ↓ 5. Validate Decisions [validateDecisions()] ↓ 6. Build FullDecision [Return structured result] ``` ### 6.2 Chain of Thought Extraction ```go // decision/engine.go:1327-1345 func extractCoTTrace(response string) string { // Priority 1: XML tag if match := reReasoningTag.FindStringSubmatch(response); len(match) > 1 { return strings.TrimSpace(match[1]) } // Priority 2: Text before tag // Priority 3: Text before JSON [ // Priority 4: Full response } ``` ### 6.3 JSON Decision Extraction ```go // decision/engine.go:1347-1408 func extractDecisions(response string) (string, error) { // 1. Remove invisible characters response = removeInvisibleRunes(response) // 2. Fix character encoding response = fixMissingQuotes(response) // 3. Extract JSON (priority) // - XML tag + ```json // - Standalone ```json code block // - Bare JSON array } ``` ### 6.4 Character Encoding Fix ```go // decision/engine.go:1410-1432 func fixMissingQuotes(s string) string { // Chinese quotes → ASCII s = strings.ReplaceAll(s, """, "\"") s = strings.ReplaceAll(s, """, "\"") // Chinese brackets → ASCII s = strings.ReplaceAll(s, "[", "[") s = strings.ReplaceAll(s, "]", "]") s = strings.ReplaceAll(s, "{", "{") s = strings.ReplaceAll(s, "}", "}") // Chinese punctuation → ASCII s = strings.ReplaceAll(s, ":", ":") s = strings.ReplaceAll(s, ",", ",") } ``` ### 6.5 Decision Validation ```go // decision/engine.go:1480-1602 func validateDecisions(decisions []Decision, equity, leverage, ratio float64) error { for _, d := range decisions { // 1. Validate action type validActions := []string{"open_long", "open_short", "close_long", "close_short", "hold", "wait"} // 2. Open position validation if isOpenAction(d.Action) { // Leverage range check // Position size check // Stop loss/take profit check // Risk/reward ratio check // Confidence check } // 3. Close position validation if isCloseAction(d.Action) { // Symbol must exist } } } ``` ### 6.6 Decision Structure ```go // decision/engine.go:128-143 type Decision struct { Symbol string // Trading pair: "BTCUSDT" Action string // "open_long", "open_short", "close_long", "close_short", "hold", "wait" Leverage int // Leverage multiplier PositionSizeUSD float64 // Position value (USDT) StopLoss float64 // Stop loss price TakeProfit float64 // Take profit price Confidence int // Confidence 0-100 RiskUSD float64 // Max risk (USDT) Reasoning string // Decision reasoning } ``` --- ## 7. Decision Execution **Core File:** `trader/auto_trader.go:392-560` ### 7.1 Decision Sorting ```go // trader/auto_trader.go:519-526 sort.SliceStable(decisions, func(i, j int) bool { priority := map[string]int{ "close_long": 1, "close_short": 1, // Highest priority "open_long": 2, "open_short": 2, // Second priority "hold": 3, "wait": 3, // Lowest priority } return priority[decisions[i].Action] < priority[decisions[j].Action] }) ``` ### 7.2 Risk Control Enforcement **File:** `trader/auto_trader.go:1769-1851` | Check | Method | Action | |-------|--------|--------| | Max positions | `enforceMaxPositions()` | Reject new opens | | Position value cap | `enforcePositionValueRatio()` | Auto reduce size | | Min position | `enforceMinPositionSize()` | Reject small orders | | Margin adjustment | Auto calculate | Adjust by available balance | ### 7.3 Order Execution ```go // trader/auto_trader.go:1631-1767 func (at *AutoTrader) recordAndConfirmOrder(orderID, symbol, side, action string) { // 1. Poll order status (5 retries, 500ms interval) for i := 0; i < 5; i++ { status := at.trader.GetOrderStatus(orderID) if status.Status == "FILLED" { break } time.Sleep(500 * time.Millisecond) } // 2. Extract fill info filledPrice := status.AvgPrice filledQty := status.FilledQty fee := status.Fee // 3. Record to database at.store.Position().SaveOrder(...) } ``` ### 7.4 Decision Log Saving ```go // trader/auto_trader.go:1235-1256 record := &store.DecisionRecord{ CycleNumber: cycleNumber, TraderID: traderID, Timestamp: time.Now(), SystemPrompt: systemPrompt, // Full system prompt InputPrompt: userPrompt, // Full user prompt CoTTrace: cotTrace, // AI chain of thought DecisionJSON: decisionsJSON, // Parsed decisions RawResponse: rawResponse, // Raw AI response ExecutionLog: executionResults, // Execution results CandidateCoins: candidateCoins, // Candidate coins Success: success, // Execution status } at.store.Decision().LogDecision(record) ``` --- ## Core File Index | Module | File | Key Methods | |--------|------|-------------| | **Main Loop** | `trader/auto_trader.go` | `Run()`, `runCycle()`, `buildTradingContext()` | | **Coin Selection** | `decision/engine.go:380-454` | `GetCandidateCoins()` | | **Data Fetching** | `market/data.go` | `Get()`, `GetWithTimeframes()` | | **Indicator Calc** | `market/data.go:59-98` | `calculateEMA()`, `calculateMACD()`, `calculateRSI()` | | **System Prompt** | `decision/engine.go:700-818` | `BuildSystemPrompt()` | | **User Prompt** | `decision/engine.go:884-1007` | `BuildUserPrompt()` | | **Market Format** | `decision/engine.go:1029-1099` | `formatMarketData()` | | **AI Request** | `decision/engine.go:222-293` | `GetFullDecisionWithStrategy()` | | **MCP Client** | `mcp/client.go:136-150` | `CallWithMessages()` | | **Response Parse** | `decision/engine.go:1303-1604` | `parseFullDecisionResponse()` | | **CoT Extract** | `decision/engine.go:1327-1345` | `extractCoTTrace()` | | **JSON Extract** | `decision/engine.go:1347-1408` | `extractDecisions()` | | **Decision Valid** | `decision/engine.go:1480-1602` | `validateDecisions()` | | **Risk Enforce** | `trader/auto_trader.go:1769-1851` | `enforceMaxPositions()`, `enforcePositionValueRatio()` | | **Strategy Config** | `store/strategy.go` | `StrategyConfig`, `RiskControlConfig` | | **Data Provider** | `provider/data_provider.go` | `GetAI500Data()`, `GetOITopPositions()` | --- ## Configuration Reference ### Strategy Config Structure ``` /* Detailed source-code truncated for AI context efficiency. */ ``` --- **Document Version:** 1.0.0 **Last Updated:** 2025-01-15 --- ### Architecture/STRATEGY MODULE.Zh CN # NOFX 策略模块技术文档 **语言:** [English](STRATEGY_MODULE.md) | [中文](STRATEGY_MODULE.zh-CN.md) ## 概述 本文档详细描述 NOFX 策略模块的完整数据流程,包括币种选择、数据组装、提示词构建、AI 请求、响应解析和决策执行。 --- ## 完整数据流程图 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 交易周期 (每 N 分钟) │ └─────────────────────────────────────────────────────────────────┘ 1. 币种选择 (GetCandidateCoins) ├─ Static (静态列表) ├─ AI500 Pool (AI评分池) ├─ OI Top (持仓增长榜) └─ Mixed (混合模式) ↓ 2. 数据组装 (buildTradingContext) ├─ 账户余额 → equity, available, unrealizedPnL ├─ 当前持仓 → symbol, side, entry, mark, qty, leverage ├─ K线数据 → OHLCV (5m, 15m, 1h, 4h) ├─ 技术指标 → EMA, MACD, RSI, ATR, Volume ├─ 链上数据 → OI, Funding Rate ├─ 量化数据 → 资金流向, OI变化 (可选) └─ 最近交易 → 最近10笔已平仓 ↓ 3. 系统提示词 (BuildSystemPrompt) ├─ 角色定义 ├─ 交易模式 (aggressive/conservative/scalping) ├─ 硬性约束 (代码强制执行) ├─ AI引导 (建议值) ├─ 交易频率 ├─ 入场标准 ├─ 决策流程 └─ 输出格式 (XML + JSON) ↓ 4. 用户提示词 (BuildUserPrompt) ├─ 系统状态 (时间, 周期号) ├─ BTC市场概览 ├─ 账户信息 ├─ 当前持仓 (含技术指标) ├─ 候选币种 (完整市场数据) └─ "请分析并输出决策..." ↓ 5. AI请求 (CallWithMessages) ├─ 选择AI模型 ├─ POST: system_prompt + user_prompt ├─ 超时: 120秒, 重试: 3次 └─ 返回原始响应 ↓ 6. AI解析 (parseFullDecisionResponse) ├─ 提取思维链 ├─ 提取JSON决策 ├─ 修复字符编码 ├─ 验证JSON格式 ├─ 解析决策数组 └─ 验证风控参数 ↓ 7. 决策执行 ├─ 排序: 平仓优先 → 开仓 → hold/wait ├─ 风控强制执行 ├─ 提交订单 ├─ 确认成交 └─ 记录到数据库 ``` --- ## 1. 币种选择 (Coin Selection) **核心文件:** `decision/engine.go:380-454` **入口方法:** `StrategyEngine.GetCandidateCoins()` ### 1.1 静态币种列表 (Static) ```go // decision/engine.go:395-403 if config.CoinSource.SourceType == "static" { for _, symbol := range config.CoinSource.StaticCoins { coins = append(coins, CandidateCoin{ Symbol: market.Normalize(symbol), Sources: []string{"static"}, }) } } ``` - **配置:** `StrategyConfig.CoinSource.StaticCoins` - **用途:** 手动指定交易币种 - **标签:** `["static"]` ### 1.2 AI500 币种池 (CoinPool) ```go // decision/engine.go:405-406, 456-474 func (e *StrategyEngine) getCoinPoolCoins(limit int) []CandidateCoin { coins, err := e.provider.GetTopRatedCoins(limit) // ... for _, coin := range coins { result = append(result, CandidateCoin{ Symbol: coin.Symbol, Sources: []string{"ai500"}, }) } } ``` - **API:** `config.CoinSource.CoinPoolAPIURL` (默认: `https://nofxos.ai/api/ai500/list`) - **用途:** 获取 AI 评分最高的 N 个币种 - **标签:** `["ai500"]` ### 1.3 OI Top 币种 (持仓增长榜) ```go // decision/engine.go:408-409, 476-498 func (e *StrategyEngine) getOITopCoins() []CandidateCoin { positions, err := e.provider.GetOITopPositions() // ... for _, pos := range positions { result = append(result, CandidateCoin{ Symbol: pos.Symbol, Sources: []string{"oi_top"}, }) } } ``` - **API:** `config.CoinSource.OITopAPIURL` - **用途:** 获取持仓量增长最快的币种 - **标签:** `["oi_top"]` ### 1.4 混合模式 (Mixed) ```go // decision/engine.go:411-449 if config.CoinSource.SourceType == "mixed" { if config.CoinSource.UseCoinPool { // 添加 AI500 币种 } if config.CoinSource.UseOITop { // 添加 OI Top 币种 } if len(config.CoinSource.StaticCoins) > 0 { // 添加静态币种 } // 去重合并,保留多来源标签 } ``` - **特点:** 同时使用多个数据源 - **标签示例:** `["ai500", "oi_top"]` (双信号币种) --- ## 2. 数据组装 (Data Assembly) **核心文件:** `trader/auto_trader.go:562-791`, `decision/engine.go:299-374` **入口方法:** `AutoTrader.buildTradingContext()` ### 2.1 账户数据 ```go // trader/auto_trader.go:565-583 balance, err := at.trader.GetBalance() equity := balance["total_equity"].(float64) available := balance["available_balance"].(float64) unrealizedPnL := balance["total_pnl"].(float64) ``` **提取字段:** - `total_equity` - 账户总权益 - `available_balance` - 可用余额 - `total_pnl` - 未实现盈亏 ### 2.2 持仓数据 ```go // trader/auto_trader.go:588-682 positions, err := at.trader.GetPositions() for _, pos := range positions { position := decision.Position{ Symbol: pos.Symbol, Side: pos.Side, // "long" / "short" EntryPrice: pos.EntryPrice, MarkPrice: pos.MarkPrice, Quantity: pos.Quantity, Leverage: pos.Leverage, UnrealizedPnL: pos.UnrealizedPnL, LiquidationPrice: pos.LiquidationPrice, } } ``` ### 2.3 市场数据获取 ```go // decision/engine.go:299-374 func (e *StrategyEngine) fetchMarketDataWithStrategy(symbols []string) map[string]*market.Data { timeframes := config.Indicators.Klines.SelectedTimeframes // ["5m", "15m", "1h", "4h"] primaryTF := config.Indicators.Klines.PrimaryTimeframe // "5m" count := config.Indicators.Klines.PrimaryCount // 30 for _, symbol := range symbols { data := market.GetWithTimeframes(symbol, timeframes, primaryTF, count) result[symbol] = data } } ``` ### 2.4 技术指标计算 **文件:** `market/data.go:59-98` | 指标 | 配置 | 计算方法 | |------|------|----------| | **EMA** | `EnableEMA`, `EMAPeriods` | `calculateEMA(klines, period)` | | **MACD** | `EnableMACD` | `calculateMACD(klines)` - 12/26/9 | | **RSI** | `EnableRSI`, `RSIPeriods` | `calculateRSI(klines, period)` | | **ATR** | `EnableATR`, `ATRPeriods` | `calculateATR(klines, period)` | | **Volume** | `EnableVolume` | 原始成交量数据 | | **OI** | `EnableOI` | 持仓量数据 | | **Funding Rate** | `EnableFundingRate` | 资金费率 | ### 2.5 量化数据 (可选) ```go // trader/auto_trader.go:759-778 if config.Indicators.EnableQuantData { quantData := provider.GetQuantData(symbol) // 包含: 资金流向、OI变化、价格变化 } ``` **数据结构:** ```go QuantData { Netflow { Institution: {Future, Spot}, // 机构资金流 Personal: {Future, Spot} // 散户资金流 }, OI { CurrentOI: float64, Delta: {1h, 4h, 24h} // OI变化 }, PriceChange { "1h", "4h", "24h": float64 // 价格变化百分比 } } ``` --- ## 3. 系统提示词 (System Prompt) **核心文件:** `decision/engine.go:700-818` **入口方法:** `StrategyEngine.BuildSystemPrompt(accountEquity, variant)` ### 3.1 提示词结构 (8个部分) ``` 1. 角色定义 [可编辑] 2. 交易模式变体 [运行时确定] 3. 硬性约束 [代码强制 + AI引导] 4. 交易频率 [可编辑] 5. 入场标准 [可编辑] 6. 决策流程 [可编辑] 7. 输出格式 [固定XML + JSON结构] 8. 自定义提示词 [可选] ``` ### 3.2 角色定义 ```go // decision/engine.go:706-713 roleDefinition := config.PromptSections.RoleDefinition if roleDefinition == "" { roleDefinition = "You are a professional cryptocurrency trading AI..." } ``` ### 3.3 交易模式变体 | 模式 | 特点 | |------|------| | `aggressive` | 趋势突破,较高仓位容忍度 | | `conservative` | 多信号确认,保守资金管理 | | `scalping` | 短线动量,紧止盈 | ### 3.4 硬性约束 **代码强制执行 (CODE ENFORCED):** ```go // decision/engine.go:725-749 maxPositions := config.RiskControl.MaxPositions // 默认: 3 altcoinMaxRatio := config.RiskControl.AltcoinMaxPositionValueRatio // 默认: 1.0 btcethMaxRatio := config.RiskControl.BTCETHMaxPositionValueRatio // 默认: 5.0 maxMarginUsage := config.RiskControl.MaxMarginUsage // 默认: 90% minPositionSize := config.RiskControl.MinPositionSize // 默认: 12 USDT ``` **AI引导 (建议值):** ```go altcoinMaxLeverage := config.RiskControl.AltcoinMaxLeverage // 默认: 5x btcethMaxLeverage := config.RiskControl.BTCETHMaxLeverage // 默认: 5x minRiskRewardRatio := config.RiskControl.MinRiskRewardRatio // 默认: 1:3 minConfidence := config.RiskControl.MinConfidence // 默认: 75 ``` ### 3.5 输出格式要求 ```xml [思维链分析过程] ```json [ { "symbol": "BTCUSDT", "action": "open_long", "leverage": 5, "position_size_usd": 100.00, "stop_loss": 65000.00, "take_profit": 72000.00, "confidence": 85, "risk_usd": 20.00, "reasoning": "..." } ] ``` ``` --- ## 4. 用户提示词 (User Prompt) **核心文件:** `decision/engine.go:884-1007` **入口方法:** `StrategyEngine.BuildUserPrompt(ctx)` ### 4.1 提示词内容结构 ``` 1. 系统状态 [时间, 周期号, 运行时长] 2. BTC市场概览 [价格, 涨跌幅, MACD, RSI] 3. 账户信息 [权益, 余额%, 盈亏%, 保证金%, 持仓数] 4. 最近成交 [最近10笔已平仓交易] 5. 当前持仓 [详细持仓数据 + 技术指标] 6. 候选币种 [完整市场数据] 7. 量化数据 [资金流向, OI数据] (可选) 8. OI排行数据 [市场OI变化排行] (可选) ``` ### 4.2 账户信息格式 ``` Account: Equity 1000.00 | Balance 800.00 (80.0%) | PnL +5.5% | Margin 20.0% | Positions 2 ``` ### 4.3 持仓信息格式 ``` 1. BTCUSDT LONG | Entry 68000.0000 Current 69500.0000 Qty 0.0100 | Position Value $695.00 PnL +2.21% | Amount +$15.00 Peak PnL +3.50% | Leverage 5x Margin $139.00 | Liquidation Price 55000.0000 Holding Duration 2 hours 30 minutes Market: price=69500, ema20=68800, macd=150.5, rsi7=62.3 OI: Latest=15000000, Avg=14500000 Funding Rate: 0.0100% ``` ### 4.4 候选币种格式 ``` ### 1. ETHUSDT (AI500+OI_Top dual signal) current_price = 3500.00, current_ema20 = 3450.00, current_macd = 25.5, current_rsi7 = 58.0 Open Interest: Latest: 8500000.00 Average: 8200000.00 Funding Rate: 0.0050 === 5M TIMEFRAME (oldest → latest) === Prices: [3480, 3485, 3490, 3495, 3500] Volumes: [1000, 1200, 1100, 1300, 1150] EMA20: [3470, 3475, 3478, 3482, 3485] MACD: [20.1, 21.5, 22.8, 24.0, 25.5] RSI7: [55.0, 56.2, 57.1, 57.8, 58.0] === 15M TIMEFRAME === ... ``` --- ## 5. AI请求 (AI Request) **核心文件:** `decision/engine.go:222-293`, `mcp/client.go:136-150` ### 5.1 请求流程 ```go // decision/engine.go:263-268 aiCallStart := time.Now() aiResponse, err := mcpClient.CallWithMessages(systemPrompt, userPrompt) aiCallDuration := time.Since(aiCallStart) ``` ### 5.2 支持的AI模型 | 模型 | 客户端文件 | 默认模型 | |------|-----------|----------| | **DeepSeek** | `mcp/deepseek_client.go` | deepseek-chat | | **Qwen** | `mcp/qwen_client.go` | qwen-max | | **Claude** | `mcp/claude_client.go` | claude-3-5-sonnet | | **Gemini** | `mcp/gemini_client.go` | gemini-pro | | **Grok** | `mcp/grok_client.go` | grok-beta | | **OpenAI** | `mcp/openai_client.go` | gpt-5.2 | | **Kimi** | `mcp/kimi_client.go` | moonshot-v1-8k | ### 5.3 请求参数 ```go // mcp/client.go Timeout: 120 seconds MaxRetries: 3 RetryDelay: 2 seconds (exponential backoff) ``` --- ## 6. AI响应解析 (Response Parsing) **核心文件:** `decision/engine.go:1303-1604` **入口方法:** `parseFullDecisionResponse(response, accountEquity, leverage, ratio)` ### 6.1 解析流程 ``` 原始AI响应 (文本) ↓ 1. 提取思维链 [extractCoTTrace()] ↓ 2. 提取JSON决策 [extractDecisions()] ↓ 3. 验证JSON格式 [validateJSONFormat()] ↓ 4. 解析JSON [json.Unmarshal()] ↓ 5. 验证决策 [validateDecisions()] ↓ 6. 构建FullDecision [返回结构化结果] ``` ### 6.2 思维链提取 ```go // decision/engine.go:1327-1345 func extractCoTTrace(response string) string { // 优先级1: XML标签 if match := reReasoningTag.FindStringSubmatch(response); len(match) > 1 { return strings.TrimSpace(match[1]) } // 优先级2: 标签之前的文本 // 优先级3: JSON [ 之前的文本 // 优先级4: 完整响应 } ``` ### 6.3 JSON决策提取 ```go // decision/engine.go:1347-1408 func extractDecisions(response string) (string, error) { // 1. 移除不可见字符 response = removeInvisibleRunes(response) // 2. 修复字符编码 response = fixMissingQuotes(response) // 3. 提取JSON (优先级) // - XML标签 + ```json // - 独立 ```json 代码块 // - 裸JSON数组 } ``` ### 6.4 字符编码修复 ```go // decision/engine.go:1410-1432 func fixMissingQuotes(s string) string { // 中文引号 → ASCII s = strings.ReplaceAll(s, """, "\"") s = strings.ReplaceAll(s, """, "\"") // 中文括号 → ASCII s = strings.ReplaceAll(s, "[", "[") s = strings.ReplaceAll(s, "]", "]") s = strings.ReplaceAll(s, "{", "{") s = strings.ReplaceAll(s, "}", "}") // 中文标点 → ASCII s = strings.ReplaceAll(s, ":", ":") s = strings.ReplaceAll(s, ",", ",") } ``` ### 6.5 决策验证 ```go // decision/engine.go:1480-1602 func validateDecisions(decisions []Decision, equity, leverage, ratio float64) error { for _, d := range decisions { // 1. 验证action类型 validActions := []string{"open_long", "open_short", "close_long", "close_short", "hold", "wait"} // 2. 开仓验证 if isOpenAction(d.Action) { // 杠杆范围检查 // 仓位大小检查 // 止损止盈检查 // 风险回报比检查 // 置信度检查 } // 3. 平仓验证 if isCloseAction(d.Action) { // Symbol必须存在 } } } ``` ### 6.6 Decision结构体 ```go // decision/engine.go:128-143 type Decision struct { Symbol string // 交易对: "BTCUSDT" Action string // "open_long", "open_short", "close_long", "close_short", "hold", "wait" Leverage int // 杠杆倍数 PositionSizeUSD float64 // 仓位价值 (USDT) StopLoss float64 // 止损价格 TakeProfit float64 // 止盈价格 Confidence int // 置信度 0-100 RiskUSD float64 // 最大风险 (USDT) Reasoning string // 决策理由 } ``` --- ## 7. 决策执行 (Execution) **核心文件:** `trader/auto_trader.go:392-560` ### 7.1 决策排序 ```go // trader/auto_trader.go:519-526 sort.SliceStable(decisions, func(i, j int) bool { priority := map[string]int{ "close_long": 1, "close_short": 1, // 最高优先级 "open_long": 2, "open_short": 2, // 次优先级 "hold": 3, "wait": 3, // 最低优先级 } return priority[decisions[i].Action] < priority[decisions[j].Action] }) ``` ### 7.2 风控强制执行 **文件:** `trader/auto_trader.go:1769-1851` | 检查项 | 方法 | 动作 | |--------|------|------| | 最大持仓数 | `enforceMaxPositions()` | 拒绝新开仓 | | 仓位价值上限 | `enforcePositionValueRatio()` | 自动缩减仓位 | | 最小仓位 | `enforceMinPositionSize()` | 拒绝过小订单 | | 保证金调整 | 自动计算 | 根据可用余额调整 | ### 7.3 订单执行 ```go // trader/auto_trader.go:1631-1767 func (at *AutoTrader) recordAndConfirmOrder(orderID, symbol, side, action string) { // 1. 轮询订单状态 (5次重试, 500ms间隔) for i := 0; i < 5; i++ { status := at.trader.GetOrderStatus(orderID) if status.Status == "FILLED" { break } time.Sleep(500 * time.Millisecond) } // 2. 提取成交信息 filledPrice := status.AvgPrice filledQty := status.FilledQty fee := status.Fee // 3. 记录到数据库 at.store.Position().SaveOrder(...) } ``` ### 7.4 决策日志保存 ```go // trader/auto_trader.go:1235-1256 record := &store.DecisionRecord{ CycleNumber: cycleNumber, TraderID: traderID, Timestamp: time.Now(), SystemPrompt: systemPrompt, // 完整系统提示词 InputPrompt: userPrompt, // 完整用户提示词 CoTTrace: cotTrace, // AI思维链 DecisionJSON: decisionsJSON, // 解析后的决策 RawResponse: rawResponse, // 原始AI响应 ExecutionLog: executionResults, // 执行结果 CandidateCoins: candidateCoins, // 候选币种 Success: success, // 执行状态 } at.store.Decision().LogDecision(record) ``` --- ## 核心文件索引 | 模块 | 文件 | 关键方法 | |------|------|----------| | **主循环** | `trader/auto_trader.go` | `Run()`, `runCycle()`, `buildTradingContext()` | | **币种选择** | `decision/engine.go:380-454` | `GetCandidateCoins()` | | **数据获取** | `market/data.go` | `Get()`, `GetWithTimeframes()` | | **指标计算** | `market/data.go:59-98` | `calculateEMA()`, `calculateMACD()`, `calculateRSI()` | | **系统提示词** | `decision/engine.go:700-818` | `BuildSystemPrompt()` | | **用户提示词** | `decision/engine.go:884-1007` | `BuildUserPrompt()` | | **市场数据格式化** | `decision/engine.go:1029-1099` | `formatMarketData()` | | **AI请求** | `decision/engine.go:222-293` | `GetFullDecisionWithStrategy()` | | **MCP客户端** | `mcp/client.go:136-150` | `CallWithMessages()` | | **响应解析** | `decision/engine.go:1303-1604` | `parseFullDecisionResponse()` | | **思维链提取** | `decision/engine.go:1327-1345` | `extractCoTTrace()` | | **JSON提取** | `decision/engine.go:1347-1408` | `extractDecisions()` | | **决策验证** | `decision/engine.go:1480-1602` | `validateDecisions()` | | **风控执行** | `trader/auto_trader.go:1769-1851` | `enforceMaxPositions()`, `enforcePositionValueRatio()` | | **策略配置** | `store/strategy.go` | `StrategyConfig`, `RiskControlConfig` | | **数据提供者** | `provider/data_provider.go` | `GetAI500Data()`, `GetOITopPositions()` | --- ## 配置参考 ### 策略配置结构 ``` /* Detailed source-code truncated for AI context efficiency. */ ``` --- **文档版本:** 1.0.0 **最后更新:** 2025-01-15 --- ### Architecture/X402 STREAMING PAYMENT # x402 Streaming Payment Architecture ## Overview NOFX calls AI models (DeepSeek, GPT, Claude, etc.) through the claw402 gateway, using the [x402 protocol](https://github.com/coinbase/x402) to pay per request with USDC on Base L2. This document describes the full implementation of the SSE streaming call mode, including client, server, and billing logic. ## Why Streaming Is Needed ``` NOFX (client) ──→ Cloudflare (100s idle limit) ──→ claw402 (gateway) ──→ AI upstream ``` - DeepSeek inference takes 60–180 seconds (up to 5 minutes) - Cloudflare enforces a **100-second hard limit** on idle connections, returning 520/EOF on timeout - Non-streaming mode: the client receives no data until inference completes — Cloudflare disconnects after 100 seconds - Streaming mode: the first byte arrives within seconds, subsequent chunks flow continuously, keeping Cloudflare alive ## End-to-End Request Flow ``` /* Detailed source-code truncated for AI context efficiency. */ ``` ## Client Implementation (NOFX) ### File Structure | File | Responsibility | |------|----------------| | `mcp/payment/claw402.go` | Claw402Client — model routing, wallet management | | `mcp/payment/x402.go` | x402 payment flow core — DoX402RequestStream, X402CallStream | | `mcp/client.go` | ParseSSEStream — shared SSE parsing function | ### Call Chain ``` Claw402Client.Call() └→ X402CallStream() // x402.go:380 ├→ Build request body + inject stream:true ├→ DoX402RequestStream() // x402.go:239 │ ├→ Send initial request (no payment header) │ ├→ Receive 402 → parse Payment-Required header │ ├→ signFn() → EIP-712 signature │ └→ Send retry request with X-Payment header → return open *http.Response │ ├→ Start idle timeout watchdog (90s with no data → disconnect) ├→ TeeReader: simultaneous SSE parsing + raw byte buffering ├→ ParseSSEStream() // client.go:703 │ ├→ bufio.Scanner line-by-line read │ ├→ Parse "data: {...}" → OpenAI chunk format │ └→ Accumulate text + call onChunk callback │ └→ Fallback: if SSE yields nothing, try JSON parsing on buffered bodyBuf ``` ### Request Identification Every request carries an `X-Client-ID: nofx` header (`x402.go:473`), allowing claw402 to identify the request source for logging and monitoring. ### Model Routing `claw402ModelEndpoints` maps user-friendly model names to API paths: ```go "deepseek" → "/api/v1/ai/deepseek/chat" "gpt-5.4" → "/api/v1/ai/openai/chat/5.4" "claude-opus" → "/api/v1/ai/anthropic/messages/opus" "qwen-max" → "/api/v1/ai/qwen/chat/max" // ... more ``` Anthropic endpoints (containing `/anthropic/`) automatically switch to the Messages API wire format. ## Server Implementation (claw402) ### Core Problem: ginmw Is Incompatible with SSE Coinbase's standard Gin middleware `ginmw.PaymentMiddlewareFromConfig` internally works as follows: ``` 1. Wrap c.Writer with responseCapture (all writes go to buffer) 2. c.Next() — handler runs, SSE chunks all go into buffer 3. Settle payment after handler completes 4. Write buffered content to client only after successful settlement ``` Problems: - SSE chunks are buffered — the client receives no data for minutes - Cloudflare disconnects after 100 seconds → 520 error - Handler runs too long (5 min), settlement context expires ### Solution: streamAwareX402Middleware Dual-path design (`internal/gateway/x402.go`): ```go func streamAwareX402Middleware(streamServer, standardMW) { return func(c *gin.Context) { if !isStreamingBody(c) { standardMW(c) // Non-streaming → standard ginmw (battle-tested) return } // Streaming → custom path } } ``` #### Non-Streaming Path Delegates entirely to `ginmw.PaymentMiddlewareFromConfig` with no custom logic. #### Streaming Path (Pre-Settlement) ``` 1. isStreamingBody(c) — read body to check for {"stream": true}, restore body 2. streamServer.RequiresPayment(reqCtx) — does this route require payment? 3. streamServer.ProcessHTTPRequest() — verify X-Payment signature 4. handleStreamingPayment(): a. ProcessSettlement() — settle USDC on-chain (collect payment first) b. c.Next() — pass to HandleAPIKeyStream c. SSE chunks write directly to c.Writer (no responseCapture buffer) ``` Key differences: | | Standard ginmw (non-streaming) | Custom path (streaming) | |---|---|---| | Settlement timing | **After** handler completes | **Before** handler starts | | Response buffer | `responseCapture` buffers everything | No buffer, writes directly to client | | Timeout risk | Slow handler causes context expiry | Settlement uses `context.Background()` | | SSE compatible | No | Yes | ## Billing Logic ### x402 Protocol Flow x402 is an HTTP 402 payment protocol proposed by Coinbase. Core roles: - **Resource Server** (claw402) — provides paid APIs - **Client** (NOFX) — consumer, holds an EVM wallet - **Facilitator** (Coinbase CDP) — verifies signatures, executes on-chain settlement ### Payment Signing (EIP-712) Client signature type: USDC `TransferWithAuthorization` ``` 1. Receive Payment-Required header from 402 response (base64 JSON) 2. Decode to get: - scheme: "exact" - network: "eip155:8453" (Base L2) - amount: USDC amount (e.g., "3000" = $0.003) - asset: USDC contract address - payTo: claw402 recipient address 3. Sign with wallet private key using EIP-712, authorizing USDC transfer from user wallet to payTo 4. Place signature in X-Payment + Payment-Signature headers ``` ### Pricing Models Each AI model route has its own price configured in claw402: | Mode | Description | Example | |------|-------------|---------| | Fixed price | Specified directly via `user_price` field | `$0.003` per request | | Token-based dynamic pricing | Calculated from request token count | `$0.001` per 1K tokens | | Dispatch fallback | Default price for SDK-compatible routes | `$0.01` per request | ```go // Fixed price price := fmt.Sprintf("$%s", route.UserPrice) // Dynamic pricing price = DynamicPriceFunc(func(ctx, reqCtx) (Price, error) { return resolveDynamicPrice(ctx, reqCtx, rule) }) ``` ### Retry Logic and Double-Charge Prevention ```go const X402MaxPaymentRetries = 5 const X402RetryBaseWait = 3 * time.Second ``` - **5xx errors** → exponential backoff retry (3s, 6s, 9s...), no re-signing (same payment authorization) - **Another 402** → previous signature expired, re-sign and retry (on-chain authorization auto-invalidates, **no double charge**) - **4xx (non-402)** → non-retryable, fail immediately - Outer retry is set to 1 (`WithMaxRetries(1)`) to prevent outer retries from causing duplicate payments ### Settlement Timing: Streaming vs Non-Streaming | | Non-Streaming | Streaming | |---|---|---| | Settlement timing | After receiving full response | Before streaming begins | | Risk | Low (content confirmed before charge) | Slightly higher (charge before seeing content) | | Necessity | Standard mode | Must charge first, otherwise SSE is buffered | ## Timeout Configuration | Location | Timeout | Purpose | |----------|---------|---------| | NOFX `X402Timeout` | 5 min | HTTP client overall timeout | | NOFX `x402StreamIdleTimeout` | 90s | SSE idle disconnect (prevent hangs) | | NOFX `CallWithRequestStream` idle | 60s | Idle timeout for non-x402 streaming | | claw402 `ResponseHeaderTimeout` | 120s | Wait for first byte from AI upstream | | claw402 `streamingHTTP.Timeout` | 0 (unlimited) | SSE stream can last indefinitely | | claw402 `standardMW WithTimeout` | 10 min | Non-streaming ginmw overall timeout | | claw402 `x402PaymentTimeout` | 30s | Payment verification/settlement timeout | ## SSE Fault Tolerance ### TeeReader Dual Parsing ```go var bodyBuf bytes.Buffer tee := io.TeeReader(resp.Body, &bodyBuf) text, sseErr := ParseSSEStream(tee, onChunk, onLine) if text != "" { return text, nil // SSE succeeded } // SSE yielded nothing → try JSON parsing on bodyBuf (server may have returned non-streaming JSON) jsonText, _ := ParseMCPResponse(bodyBuf.Bytes()) ``` ### Idle Timeout Watchdog ```go go func() { t := time.NewTimer(90s) for { select { case <-t.C: cancel() // timeout → cancel context → close TCP → body.Read() returns error case <-resetCh: t.Reset(90s) // received SSE line → reset timer } } }() ``` Every incoming SSE line resets the timer. If no data arrives for 90 seconds, the context is cancelled and the TCP connection is closed, preventing indefinite blocking. ## Related Files ### NOFX (Client) - `mcp/payment/claw402.go` — Claw402Client entry point - `mcp/payment/x402.go` — x402 payment flow (DoX402Request, DoX402RequestStream, X402CallStream) - `mcp/payment/x402_sign.go` — EIP-712 signing implementation - `mcp/client.go` — ParseSSEStream, CallWithRequestStream ### claw402 (Server) - `internal/gateway/x402.go` — x402 middleware (streamAwareX402Middleware) - `internal/gateway/proxy/stream.go` — SSE proxy (HandleAPIKeyStream) - `internal/config/` — Route configuration (pricing, model mapping) --- ### Api/API REFERENCE # CryptoMaster API 接口文档 ## 概述 ### 基础信息 - **Base URL**: `https://nofxos.ai` - **响应格式**: JSON - **缓存时间**: 15秒(所有数据接口) - **限流**: 每个IP每秒最多30次请求 ### 认证方式 所有数据接口需要认证,支持两种方式: #### 方式1: Query参数(推荐) ``` GET /api/ai500/list?auth=your_api_key ``` #### 方式2: Authorization Header ``` GET /api/ai500/list Authorization: Bearer your_api_key ``` ### 响应格式 **成功响应:** ```json { "success": true, "data": { ... } } ``` **错误响应:** ```json { "success": false, "error": "错误信息" } ``` --- ## 重要:数值格式说明 ### 百分比字段格式 不同接口的百分比字段使用不同的格式,请注意区分: | 字段名 | 格式 | 示例 | 说明 | |--------|------|------|------| | `price_delta` (涨跌幅榜/币种详情) | **小数** | `0.05` = 5% | 需要 ×100 转换为百分比 | | `oi_delta_percent` | **已×100** | `5.0` = 5% | 直接使用,无需转换 | | `price_delta_percent` (OI接口) | **已×100** | `5.0` = 5% | 直接使用,无需转换 | | `increase_percent` (AI500) | **已×100** | `7.14` = 7.14% | 直接使用,无需转换 | ### 金额字段 | 字段名 | 单位 | 说明 | |--------|------|------| | `oi_delta_value` | USDT | 持仓价值变化 | | `amount` / `future_flow` / `spot_flow` | USDT | 资金流量 | | `price` | USDT | 当前价格 | ### 持仓量字段 | 字段名 | 单位 | 说明 | |--------|------|------| | `oi_delta` | 张/个 | 持仓量变化 | | `current_oi` / `oi` | 张/个 | 当前持仓量 | | `net_long` / `net_short` | 张/个 | 净多头/空头持仓 | --- ## 时间范围参数说明 所有接口支持的 `duration` 参数值: | 参数值 | 说明 | 备注 | |--------|------|------| | `1m` | 1分钟 | | | `5m` | 5分钟 | | | `15m` | 15分钟 | | | `30m` | 30分钟 | | | `1h` | 1小时 | 默认值 | | `4h` | 4小时 | | | `8h` | 8小时 | | | `12h` | 12小时 | | | `24h` / `1d` | 24小时 | 两种写法均可 | | `2d` | 2天 | | | `3d` | 3天 | | | `5d` | 5天 | | | `7d` | 7天 | | --- ## 1. AI500 智能评分接口 AI500 是基于多维度量化指标的智能评分系统,用于筛选具有上涨潜力的币种。 ### 1.1 获取AI500推荐币种列表 获取经过严格筛选的优质币种列表。 **请求** ``` GET /api/ai500/list ``` **过滤条件** - AI评分 > 70 - 币安OI持仓价值 > 15M USDT - 现价 > 上榜起始价格(只返回上涨中的币种) - 资金没有持续流出(1h/4h/12h/24h不能全为负) **响应示例** ```json { "success": true, "data": { "count": 5, "coins": [ { "pair": "BTCUSDT", "score": 85.234, "start_time": 1704067200, "start_price": 42000.5, "last_score": 83.5, "max_score": 87.2, "max_price": 45000.0, "increase_percent": 7.14 } ] } } ``` **字段说明** | 字段 | 类型 | 说明 | |------|------|------| | `pair` | string | 交易对名称,如 BTCUSDT | | `score` | float | 当前AI评分(0-100) | | `start_time` | int64 | 上榜时间戳(Unix秒) | | `start_price` | float | 上榜时价格(USDT) | | `last_score` | float | 上次记录的评分 | | `max_score` | float | 在榜期间最高评分 | | `max_price` | float | 在榜期间最高价格(USDT) | | `increase_percent` | float | 最大涨幅百分比(**已×100**,7.14 = 7.14%) | --- ### 1.2 获取单个币种AI500信息 **请求** ``` GET /api/ai500/:symbol ``` **路径参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `symbol` | string | 是 | 币种符号,支持 `BTCUSDT` 或 `BTC` 格式 | **示例** ``` GET /api/ai500/BTC GET /api/ai500/ETHUSDT ``` **响应示例** ```json { "success": true, "data": { "info": { "pair": "BTCUSDT", "score": 85.234, "start_time": 1704067200, "start_price": 42000.5, "last_score": 83.5, "max_score": 87.2, "max_price": 45000.0, "increase_percent": 7.14 }, "current_price": 44500.0, "score": 85.234 } } ``` --- ### 1.3 获取AI500统计信息 获取AI500整体统计数据。 **请求** ``` GET /api/ai500/stats ``` **响应示例** ```json { "success": true, "data": { "statistics": { "total_count": 50, "average_score": 72.5, "max_score": 95.2, "min_score": 55.3, "average_increase": 12.5 }, "top_coins": [...], "bottom_coins": [...] } } ``` --- ## 2. 持仓量(OI)排行接口 监控各币种的合约持仓量变化,用于判断市场资金动向。 ### 2.1 获取OI增加排行榜 返回持仓价值增加最多的币种排行。 **请求** ``` GET /api/oi/top-ranking ``` **查询参数** | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `limit` | int | 20 | 返回数量,最大100 | | `duration` | string | `1h` | 时间范围,见[时间范围参数](#时间范围参数说明) | **示例** ``` GET /api/oi/top-ranking?limit=50&duration=4h ``` **响应示例** ```json { "success": true, "data": { "count": 20, "exchange": "binance", "time_range": "4小时", "time_range_param": "4h", "rank_type": "top", "limit": 50, "positions": [ { "rank": 1, "symbol": "BTCUSDT", "price": 44500.0, "oi_delta": 1500.5, "oi_delta_value": 65000000, "oi_delta_percent": 2.5, "current_oi": 62000, "price_delta_percent": 1.2, "net_long": 35000, "net_short": 27000 } ] } } ``` **字段说明** | 字段 | 类型 | 格式 | 说明 | |------|------|------|------| | `rank` | int | - | 排名 | | `symbol` | string | - | 交易对名称 | | `price` | float | USDT | 当前价格 | | `oi_delta` | float | 张/个 | 持仓量变化 | | `oi_delta_value` | float | USDT | 持仓价值变化(**排序依据**) | | `oi_delta_percent` | float | **已×100** | 持仓量变化百分比,2.5 = 2.5% | | `current_oi` | float | 张/个 | 当前持仓量 | | `price_delta_percent` | float | **已×100** | 价格变化百分比,1.2 = 1.2% | | `net_long` | float | 张/个 | 净多头持仓 | | `net_short` | float | 张/个 | 净空头持仓 | --- ### 2.2 获取OI减少排行榜 返回持仓价值减少最多的币种排行。 **请求** ``` GET /api/oi/low-ranking ``` **查询参数** 同 [OI增加排行榜](#21-获取oi增加排行榜) **示例** ``` GET /api/oi/low-ranking?limit=30&duration=24h ``` --- ### 2.3 获取OI Top20(向后兼容) **请求** ``` GET /api/oi/top ``` 固定返回1小时内OI增加最多的Top20,用于向后兼容。 --- ## 3. 资金流量(NetFlow)排行接口 监控机构和散户的资金流向。 ### 3.1 获取资金流入排行榜 **请求** ``` GET /api/netflow/top-ranking ``` **查询参数** | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `limit` | int | 20 | 返回数量,最大100 | | `duration` | string | `1h` | 时间范围,见[时间范围参数](#时间范围参数说明) | | `type` | string | `institution` | 资金类型:`institution`(机构), `personal`(散户) | | `trade` | string | `future` | 交易类型:`future`(合约), `spot`(现货) | **示例** ``` GET /api/netflow/top-ranking?limit=30&duration=4h&type=institution&trade=future ``` **响应示例** ```json { "success": true, "data": { "count": 30, "type": "institution", "trade": "合约", "time_range": "4h", "rank_type": "top", "limit": 30, "netflows": [ { "rank": 1, "symbol": "BTCUSDT", "amount": 15000000.5, "price": 44500.0 } ] } } ``` **字段说明** | 字段 | 类型 | 格式 | 说明 | |------|------|------|------| | `rank` | int | - | 排名 | | `symbol` | string | - | 交易对名称 | | `amount` | float | USDT | 资金流量,**正数=流入,负数=流出** | | `price` | float | USDT | 当前价格 | --- ### 3.2 获取资金流出排行榜 **请求** ``` GET /api/netflow/low-ranking ``` **查询参数** 同 [资金流入排行榜](#31-获取资金流入排行榜) **示例** ``` GET /api/netflow/low-ranking?limit=20&duration=1h&type=personal&trade=spot ``` --- ### 3.3 获取资金流入Top20(向后兼容) **请求** ``` GET /api/netflow/top ``` 固定返回1小时内机构合约资金流入最多的Top20。 --- ## 4. 涨跌幅榜接口 ### 4.1 获取涨跌幅榜 同时返回涨幅榜(top)和跌幅榜(low),支持多个时间周期同时查询。 **请求** ``` GET /api/price/ranking ``` **查询参数** | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `duration` | string | `1h` | 时间范围,可多选逗号分隔:`1h,4h,24h` | | `limit` | int | 20 | 每个榜单返回数量,最大100 | | `exchange` | string | `binance` | 交易所 | **示例** ``` GET /api/price/ranking?duration=1h,4h,24h&limit=20 ``` **响应示例** ```json { "success": true, "data": { "durations": ["1h", "4h", "24h"], "limit": 20, "data": { "1h": { "top": [ { "pair": "MOGUSDT", "symbol": "MOG", "price_delta": 0.0723, "price": 0.00123, "future_flow": 201500, "spot_flow": 0, "oi": 15000000, "oi_delta": 500000, "oi_delta_value": 615 } ], "low": [ { "pair": "XYZUSDT", "symbol": "XYZ", "price_delta": -0.0512, "price": 1.234, "future_flow": -50000, "spot_flow": -10000, "oi": 8000000, "oi_delta": -200000, "oi_delta_value": -246800 } ] }, "4h": { ... }, "24h": { ... } } } } ``` **字段说明** | 字段 | 类型 | 格式 | 说明 | |------|------|------|------| | `pair` | string | - | 完整交易对名称,如 BTCUSDT | | `symbol` | string | - | 币种符号(去除USDT),如 BTC | | `price_delta` | float | **小数** | 价格变动比例,**0.0723 = 7.23%**(需×100显示) | | `price` | float | USDT | 当前价格 | | `future_flow` | float | USDT | 合约资金流量,正数=流入 | | `spot_flow` | float | USDT | 现货资金流量,正数=流入 | | `oi` | float | 张/个 | 当前持仓量 | | `oi_delta` | float | 张/个 | 持仓变化量 | | `oi_delta_value` | float | USDT | 持仓变化价值 | > **注意**:`price_delta` 使用小数格式,与 OI 接口的 `price_delta_percent` 不同! --- ## 5. 币种详情接口 ### 5.1 获取单币种完整数据 获取指定币种的所有统计信息,一次调用获取全部数据。 **请求** ``` GET /api/coin/:symbol ``` **路径参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `symbol` | string | 是 | 币种符号,支持 `BTC` 或 `BTCUSDT` 格式 | **查询参数** | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `include` | string | `netflow,oi,price,ai500` | 包含的数据类型,逗号分隔 | **include 参数选项** | 值 | 说明 | |------|------| | `netflow` | 资金流量数据(机构/散户,合约/现货) | | `oi` | 持仓量数据(币安/Bybit) | | `price` | 价格变化数据 | | `ai500` | AI500评分 | **示例** ``` GET /api/coin/BTC?include=netflow,oi,price,ai500 GET /api/coin/ETHUSDT?include=netflow,oi ``` **响应示例** ```json { "success": true, "data": { "symbol": "BTCUSDT", "price": 44500.0, "ai500": { "score": 85.234, "is_active": true, "start_time": 1704067200, "start_price": 42000.5, "increase_percent": 5.95 }, "netflow": { "institution": { "future": { "1m": 50000, "5m": 200000, "15m": 500000, "30m": 800000, "1h": 1500000, "4h": 5000000, "8h": 8000000, "12h": 10000000, "24h": 15000000, "2d": 25000000, "3d": 35000000, "5d": 50000000, "7d": 75000000 }, "spot": { ... } }, "personal": { "future": { ... }, "spot": { ... } } }, "oi": { "binance": { "current_oi": 62000, "net_long": 35000, "net_short": 27000, "delta": { "1m": { "oi_delta": 50, "oi_delta_value": 2225000, "oi_delta_percent": 0.08 }, "5m": { ... }, "1h": { ... }, "4h": { ... }, "24h": { ... } } }, "bybit": { ... } }, "price_change": { "1m": 0.001, "5m": 0.005, "15m": 0.008, "30m": 0.012, "1h": 0.015, "4h": 0.025, "8h": 0.035, "12h": 0.042, "24h": 0.055, "2d": 0.08, "3d": 0.12, "5d": 0.18, "7d": 0.25 } } } ``` **字段说明** **price_change 对象** | 字段 | 类型 | 格式 | 说明 | |------|------|------|------| | `{duration}` | float | **小数** | 价格变化比例,**0.015 = 1.5%**(需×100显示) | **netflow 对象** | 路径 | 类型 | 格式 | 说明 | |------|------|------|------| | `institution.future.{duration}` | float | USDT | 机构合约资金流量 | | `institution.spot.{duration}` | float | USDT | 机构现货资金流量 | | `personal.future.{duration}` | float | USDT | 散户合约资金流量 | | `personal.spot.{duration}` | float | USDT | 散户现货资金流量 | **oi 对象** | 路径 | 类型 | 格式 | 说明 | |------|------|------|------| | `binance.current_oi` | float | 张/个 | 币安当前持仓量 | | `binance.net_long` | float | 张/个 | 币安净多头 | | `binance.net_short` | float | 张/个 | 币安净空头 | | `binance.delta.{duration}.oi_delta` | float | 张/个 | 持仓量变化 | | `binance.delta.{duration}.oi_delta_value` | float | USDT | 持仓价值变化 | | `binance.delta.{duration}.oi_delta_percent` | float | **已×100** | 持仓变化百分比,0.08 = 0.08% | | `bybit.*` | - | - | Bybit数据,结构同上 | **ai500 对象** | 字段 | 类型 | 格式 | 说明 | |------|------|------|------| | `score` | float | 0-100 | AI综合评分 | | `is_active` | bool | - | 是否为活跃高分币种 | | `start_time` | int64 | Unix秒 | 上榜时间 | | `start_price` | float | USDT | 上榜时价格 | | `increase_percent` | float | **已×100** | 最大涨幅,5.95 = 5.95% | --- ## 错误码说明 | HTTP状态码 | 说明 | 常见原因 | |------------|------|----------| | 200 | 成功 | - | | 400 | 请求参数错误 | 参数格式不正确、缺少必填参数 | | 401 | 未授权 | 缺少认证信息或API Key无效 | | 404 | 资源不存在 | 币种不存在或未被追踪 | | 429 | 请求过于频繁 | 超过限流阈值(30次/秒) | | 500 | 服务器内部错误 | 服务端异常 | **错误响应示例** ```json { "success": false, "error": "unauthorized" } ``` --- ## 使用示例 ### cURL 示例 ```bash # 方式1: Query参数认证 curl "https://nofxos.ai/api/ai500/list?auth=your_api_key" # 方式2: Header认证 curl "https://nofxos.ai/api/ai500/list" \ -H "Authorization: Bearer your_api_key" # 获取1小时涨跌幅榜 curl "https://nofxos.ai/api/price/ranking?duration=1h&limit=20&auth=your_api_key" # 获取多个时间周期涨跌幅榜 curl "https://nofxos.ai/api/price/ranking?duration=1h,4h,24h&limit=10&auth=your_api_key" # 获取BTC详细数据 curl "https://nofxos.ai/api/coin/BTC?auth=your_api_key" # 只获取BTC的资金流和OI数据 curl "https://nofxos.ai/api/coin/BTC?include=netflow,oi&auth=your_api_key" # 获取4小时OI增加排行Top50 curl "https://nofxos.ai/api/oi/top-ranking?duration=4h&limit=50&auth=your_api_key" # 获取24小时OI减少排行Top30 curl "https://nofxos.ai/api/oi/low-ranking?duration=24h&limit=30&auth=your_api_key" # 获取机构合约资金流入排行 curl "https://nofxos.ai/api/netflow/top-ranking?type=institution&trade=future&duration=1h&auth=your_api_key" # 获取散户现货资金流出排行 curl "https://nofxos.ai/api/netflow/low-ranking?type=personal&trade=spot&duration=4h&auth=your_api_key" ``` ### Python 示例 ``` /* Detailed source-code truncated for AI context efficiency. */ ``` ### JavaScript/TypeScript 示例 ```typescript const BASE_URL = "https://nofxos.ai"; const API_KEY = "your_api_key"; // 通用请求函数 async function apiRequest(endpoint: string, params: Record = {}): Promise { const url = new URL(`${BASE_URL}${endpoint}`); params.auth = API_KEY; Object.entries(params).forEach(([key, value]) => { url.searchParams.append(key, String(value)); }); const response = await fetch(url.toString()); return response.json(); } // 获取涨跌幅榜 interface PriceRankingItem { pair: string; symbol: string; price_delta: number; // 小数格式,0.05 = 5% price: number; future_flow: number; spot_flow: number; } async function getPriceRanking(durations = "1h", limit = 20) { const data = await apiRequest("/api/price/ranking", { duration: durations, limit }); return data; } // 使用示例 async function main() { const ranking = await getPriceRanking("1h,4h", 10); for (const coin of ranking.data.data["1h"].top) { // 转换为百分比显示 const pctChange = (coin.price_delta * 100).toFixed(2); console.log(`${coin.symbol}: ${pctChange}%`); } } ``` --- ## 常见问题 ### Q: 为什么有些百分比字段格式不同? A: 这是历史原因造成的: - **OI接口**的 `oi_delta_percent` 和 `price_delta_percent` 是**已乘100**的格式(5.0 = 5%) - **涨跌幅榜和币种详情**的 `price_delta` / `price_change` 是**小数**格式(0.05 = 5%) 建议在前端显示时统一处理。 ### Q: duration 参数支持哪些值? A: 支持以下值:`1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `8h`, `12h`, `24h`(或`1d`), `2d`, `3d`, `5d`, `7d` ### Q: 如何判断资金是流入还是流出? A: `amount`、`future_flow`、`spot_flow` 等字段: - **正数** = 资金流入 - **负数** = 资金流出 ### Q: API缓存时间是多久? A: 所有数据接口缓存15秒,相同请求在15秒内返回缓存数据。 ### Q: 限流规则是什么? A: 每个IP每秒最多30次请求,超过会返回 429 错误。 --- ### Agent Skills/Diagnostic Skills.Zh CN # NOFXi 诊断与配置 Skills(第一批) 这份文档用于沉淀交易智能助手的第一批高频诊断与配置 skill。 目标不是让模型“更会想”,而是让它面对常见问题时,优先走稳定、可复用的排查路径。 ## 设计原则 - 优先按 skill 回答,不要对高频问题重复自由规划 - 先归类问题,再给出原因、检查项和修复建议 - 能通过工具验证当前状态时,先查再下结论 - 敏感信息只指导填写,不完整回显 - 对结论不确定时,要明确标注为“更可能”或“优先怀疑” ## skill_model_api_setup ### 适用场景 - 用户问某个大模型的 API key 去哪里申请 - 用户问 base URL 怎么填 - 用户问 model name 怎么填 - 用户问 OpenAI / Claude / Gemini / DeepSeek / Qwen / Kimi / Grok / MiniMax 怎么接入 ### 处理策略 1. 先确认用户要配置哪个 provider 2. 告诉用户需要准备的最少字段: - provider - API key - custom_api_url - custom_model_name 3. 如果系统已有默认地址和默认模型名,优先给推荐值 4. 回答按步骤组织,不要泛泛解释概念 ### 已知实现事实 - 系统内置 provider 默认运行配置,见 `agent.resolveModelRuntimeConfig(...)` - 常见 provider 已有默认 URL 和默认 model name ## skill_model_config_diagnosis ### 适用场景 - 模型保存成功但 agent 仍然不可用 - 提示 AI unavailable - 提示模型没启用 - 提示 custom_api_url 不合法 - 配置后 trader 不生效 ### 优先排查 1. 是否存在已启用模型 2. API key 是否为空 3. custom_api_url 是否为合法 HTTPS 地址 4. custom_model_name 是否为空或不匹配 5. 当前 trader 是否绑定了这个模型 6. 更新模型后是否已触发 trader reload ### 已知实现事实 - 非 HTTPS 的 `custom_api_url` 会被后端拒绝,见 `api/handler_ai_model.go` - 已启用模型如果缺少 API Key 或 URL,会导致 agent 无法就绪,见 `agent.ensureAIClientForStoreUser(...)` - 更新模型配置后,系统会尝试移除并重载相关 trader,使新配置立即生效 ### 输出格式 - 现象 - 更可能原因 - 先检查什么 - 下一步怎么修复 ## skill_exchange_api_setup ### 适用场景 - 用户要新建交易所 API - 用户不知道交易所需要哪些权限 - 用户问 API key / secret / passphrase 分别填什么 ### 通用处理策略 1. 先确认交易所类型 2. 告知必须权限与禁止权限 3. 告知是否需要额外字段 4. 强调 IP 白名单与权限配置 5. 引导用户回到系统内完成绑定 ### 特殊规则 - OKX 除 API Key 和 Secret 外,还需要 passphrase - Bybit 永续/合约交易需要合约权限 - 不建议开启提现权限 ### 参考文档 - `docs/getting-started/okx-api.md` - `docs/getting-started/bybit-api.md` ## skill_exchange_api_diagnosis ### 适用场景 - `invalid signature` - `timestamp` 错误 - `IP not allowed` - `permission denied` - 交易所连接不上 ### 优先排查 1. 系统时间是否同步 2. API Key / Secret 是否正确 3. 是否遗漏额外字段,如 OKX passphrase 4. IP 白名单是否包含当前服务器 5. 是否启用了交易或合约权限 6. 密钥是否过期或已重建 ### 已知实现事实 - 时间不同步是 `invalid signature` / `timestamp` 的高频根因,见 `docs/guides/TROUBLESHOOTING.zh-CN.md` - OKX 的 passphrase 缺失会导致签名相关问题,见 `docs/getting-started/okx-api.md` ### 输出格式 - 报错现象 - 最常见根因 - 优先检查顺序 - 修复步骤 ## skill_trader_start_diagnosis ### 适用场景 - trader 启动不了 - trader 启动了但没开始交易 - 页面显示已启动但一直没有动作 - 用户怀疑 strategy / model / exchange 绑定有问题 ### 优先排查 1. 是否有已启用的模型配置 2. 是否有已启用的交易所配置 3. trader 是否绑定了 exchange_id / strategy_id / ai_model_id 4. 交易所余额和权限是否满足下单条件 5. AI 最近的决策到底是 wait、hold 还是下单失败 ### 回答原则 - 要区分“没启动”“启动了但 AI 选择不交易”“尝试下单但失败”这三类 - 不要把“没开仓”直接等同于“系统故障” ## skill_order_execution_diagnosis ### 适用场景 - 下单失败 - 只开空不开户 / 只开单边 - 杠杆报错 - position side mismatch ### 优先排查 1. 账户模式是否匹配,例如 Binance 是否为 Hedge Mode 2. 是否为子账户杠杆限制 3. 合约权限是否开启 4. 余额、保证金、可交易 symbol 是否满足条件 ### 已知实现事实 - Binance 在 One-way Mode 下,可能出现 `position side mismatch` 或单边行为 - 某些子账户杠杆上限较低,超过限制会直接失败 - 这些问题在 `docs/guides/TROUBLESHOOTING.md` 已有明确说明 ## skill_strategy_diagnosis ### 适用场景 - 用户说策略没生效 - 用户说 prompt 预览和实际不一致 - 用户说修改策略后 trader 行为没有变化 ### 优先排查 1. 当前编辑的是策略模板,还是 trader 的 custom prompt 2. 策略是否真的保存成功 3. 是否需要重新读取当前配置做对比 4. 用户说的“没生效”是指未保存、未绑定,还是运行结果与预期不一致 ### 回答原则 - 先明确“对象”再排查:strategy template / trader / prompt override - 如果能读取当前保存值,就不要凭印象判断 ## 后续扩展方向 下一批可以继续补: - `skill_balance_and_position_diagnosis` - `skill_market_data_diagnosis` - `skill_prompt_generation_diagnosis` - `skill_strategy_test_run_diagnosis` - `skill_exchange_specific_setup_` - `skill_model_provider_setup_` --- ### Guides/Faq.En # Frequently Asked Questions (FAQ) Quick answers to common questions. For detailed troubleshooting, see [Troubleshooting Guide](TROUBLESHOOTING.md). --- ## General Questions ### What is NOFX? NOFX is an AI-powered cryptocurrency trading bot that uses large language models (LLMs) to make trading decisions on futures markets. ### Which exchanges are supported? - ✅ Binance Futures - ✅ Hyperliquid - 🚧 More exchanges coming soon ### Is NOFX profitable? AI trading is **experimental** and **not guaranteed** to be profitable. Always start with small amounts and never invest more than you can afford to lose. ### Can I run multiple traders simultaneously? Yes! NOFX supports running multiple traders with different configurations, AI models, and trading strategies. --- ## Setup & Configuration ### What are the system requirements? - **OS**: Linux, macOS, or Windows (Docker recommended) - **RAM**: 2GB minimum, 4GB recommended - **Disk**: 1GB for application + logs - **Network**: Stable internet connection ### Do I need coding experience? No! NOFX has a web UI for all configuration. However, basic command line knowledge helps with setup and troubleshooting. ### How do I get API keys? 1. **Binance**: Account → API Management → Create API → Enable Futures 2. **Hyperliquid**: Visit [Hyperliquid App](https://app.hyperliquid.xyz/) → API Settings ### Should I use a subaccount? **Recommended**: Yes, use a subaccount dedicated to NOFX for better risk isolation. However, note that some subaccounts have restrictions (e.g., 5x max leverage on Binance). --- ## Trading Questions ### Why isn't my trader making any trades? Common reasons: - AI decided to "wait" due to market conditions - Insufficient balance or margin - Position limits reached (default: max 3 positions) - See detailed diagnostics in [Troubleshooting Guide](TROUBLESHOOTING.md#-ai-always-says-wait--hold) ### How often does the AI make decisions? Configurable! Default is every **3-5 minutes**. Too frequent = overtrading, too slow = missed opportunities. ### Can I customize the trading strategy? Yes! You can: - Adjust leverage settings - Modify coin selection pool - Change decision intervals - Customize system prompts (advanced) ### What's the maximum number of concurrent positions? Default: **3 positions**. This is a soft limit defined in the AI prompt, not hard-coded. See `decision/engine.go:266`. --- ## Technical Issues ### Binance Position Mode Error (code=-4061) **Error**: `Order's position side does not match user's setting` **Solution**: Switch to **Hedge Mode** (双向持仓) 1. Login to [Binance Futures](https://www.binance.com/en/futures/BTCUSDT) 2. Click **⚙️ Preferences** (top right) 3. Select **Position Mode** → **Hedge Mode** 4. ⚠️ Close all positions first **Why**: NOFX uses `PositionSide(LONG/SHORT)` which requires Hedge Mode. See [Issue #202](https://github.com/NoFxAiOS/nofx/issues/202) and [Troubleshooting Guide](TROUBLESHOOTING.md#-only-opening-short-positions-issue-202). --- ### Backend won't start / Port already in use **Solution**: ```bash # Check what's using port 8080 lsof -i :8080 # Change port in .env NOFX_BACKEND_PORT=8081 ``` --- ### Frontend shows "Loading..." forever **Quick Check**: ```bash # Is backend running? curl http://localhost:8080/api/health # Should return: {"status":"ok"} ``` If not, check [Troubleshooting Guide](TROUBLESHOOTING.md#-frontend-cant-connect-to-backend). --- ### Database locked error **Solution**: ```bash # Stop all NOFX processes docker compose down # OR pkill nofx # Restart docker compose up -d ``` --- ## AI & Model Questions ### Which AI models are supported? - **DeepSeek** (recommended for cost/performance) - **Qwen** (Alibaba Cloud Tongyi Qianwen) - **Custom OpenAI-compatible APIs** (can be used for OpenAI, Claude via proxy, or other providers) ### How much do API calls cost? Depends on your model and decision frequency: - **DeepSeek**: ~$0.10-0.50 per day (1 trader, 5min intervals) - **Qwen**: ~$0.20-0.80 per day - **Custom API** (e.g., OpenAI GPT-4): ~$2-5 per day *Estimates based on typical usage. Actual costs vary by provider and usage.* ### Can I use multiple AI models? Yes! Each trader can use a different AI model. You can even A/B test different models. ### Does the AI learn from its mistakes? Yes, to some extent. NOFX provides historical performance feedback in each decision prompt, allowing the AI to adjust its strategy. --- ## Data & Privacy ### Where is my data stored? All data is stored **locally** in PostgreSQL (Docker volume `postgres_data`) plus: - `decision_logs/` - AI decision records ### Is my API key secure? API keys are stored in local databases. Never share your databases or `.env` files. We recommend using API keys with IP whitelist restrictions. ### Can I export my trading history? Yes! Use `pg_dump` or `psql` to export data: ```bash docker compose exec postgres \ psql -U nofx -d nofx -c "SELECT * FROM trades;" ``` --- ## Troubleshooting ### Where can I find detailed troubleshooting? See the comprehensive [Troubleshooting Guide](TROUBLESHOOTING.md) for: - Step-by-step diagnostics - Log collection methods - Common error solutions - Emergency reset procedures ### How do I report a bug? 1. Check [Troubleshooting Guide](TROUBLESHOOTING.md) first 2. Search [existing issues](https://github.com/NoFxAiOS/nofx/issues) 3. If not found, use our [Bug Report Template](../../.github/ISSUE_TEMPLATE/bug_report.md) ### Where can I get help? - [GitHub Discussions](https://github.com/NoFxAiOS/nofx/discussions) - [Telegram Community](https://t.me/nofx_dev_community) - [GitHub Issues](https://github.com/NoFxAiOS/nofx/issues) --- ## Contributing ### Can I contribute to NOFX? Yes! We welcome contributions: - Bug fixes and features - Documentation improvements - Translations - See [Contributing Guide](../CONTRIBUTING.md) ### How do I suggest new features? Open a [Feature Request](https://github.com/NoFxAiOS/nofx/issues/new/choose) with your idea! --- **Last Updated:** 2025-11-02 --- ### Guides/Faq.Zh CN # 常见问题(FAQ) 快速解答常见问题。详细故障排查请参考[故障排查指南](TROUBLESHOOTING.zh-CN.md)。 --- ## 基础问题 ### NOFX 是什么? NOFX 是一个 AI 驱动的加密货币交易机器人,使用大语言模型(LLM)在期货市场进行交易决策。 ### 支持哪些交易所? - ✅ 币安合约(Binance Futures) - ✅ Hyperliquid - 🚧 更多交易所开发中 ### NOFX 能盈利吗? AI 交易是**实验性**的,**不保证盈利**。请始终用小额资金测试,不要投入超过您承受能力的资金。 ### 可以同时运行多个交易员吗? 可以!NOFX 支持运行多个交易员,每个可配置不同的 AI 模型和交易策略。 --- ## 安装与配置 ### 系统要求是什么? - **操作系统**:Linux、macOS 或 Windows(推荐 Docker) - **内存**:最低 2GB,推荐 4GB - **硬盘**:应用 + 日志需要 1GB - **网络**:稳定的互联网连接 ### 需要编程经验吗? 不需要!NOFX 有 Web 界面进行所有配置。但基础的命令行知识有助于安装和故障排查。 ### 如何获取 API 密钥? 1. **币安**:账户 → API 管理 → 创建 API → 启用合约 2. **Hyperliquid**:访问 [Hyperliquid App](https://app.hyperliquid.xyz/) → API 设置 ### 应该使用子账户吗? **推荐**:是的,使用专门的子账户运行 NOFX 可以更好地隔离风险。但请注意,某些子账户有限制(例如币安子账户最高 5 倍杠杆)。 --- ## 交易问题 ### 为什么我的交易员不开仓? 常见原因: - AI 根据市场情况决定"等待" - 余额或保证金不足 - 达到持仓上限(默认最多 3 个仓位) - 详细诊断请查看[故障排查指南](TROUBLESHOOTING.zh-CN.md#-ai-总是说等待持有) ### AI 多久做一次决策? 可配置!默认是每 **3-5 分钟**。太频繁 = 过度交易,太慢 = 错过机会。 ### 可以自定义交易策略吗? 可以!您可以: - 调整杠杆设置 - 修改币种选择池 - 更改决策间隔 - 自定义系统提示词(高级) ### 最多可以同时持有多少个仓位? 默认:**3 个仓位**。这是 AI 提示词中的软限制,不是硬编码。参见 `decision/engine.go:266`。 --- ## 技术问题 ### 币安持仓模式错误 (code=-4061) **错误信息**:`Order's position side does not match user's setting` **解决方法**:切换为**双向持仓**模式 1. 登录[币安合约](https://www.binance.com/zh-CN/futures/BTCUSDT) 2. 点击右上角 **⚙️ 偏好设置** 3. 选择 **持仓模式** → **双向持仓** 4. ⚠️ 先平掉所有持仓 **原因**:NOFX 使用 `PositionSide(LONG/SHORT)`,需要双向持仓模式。 参见 [Issue #202](https://github.com/NoFxAiOS/nofx/issues/202) 和[故障排查指南](TROUBLESHOOTING.zh-CN.md#-只开空单-issue-202)。 --- ### 后端无法启动 / 端口被占用 **解决方法**: ```bash # 查看占用端口的进程 lsof -i :8080 # 修改 .env 中的端口 NOFX_BACKEND_PORT=8081 ``` --- ### 前端一直显示"加载中..." **快速检查**: ```bash # 后端是否运行? curl http://localhost:8080/api/health # 应该返回:{"status":"ok"} ``` 如果不是,查看[故障排查指南](TROUBLESHOOTING.zh-CN.md#-前端无法连接后端)。 --- ### 数据库锁定错误 **解决方法**: ```bash # 停止所有 NOFX 进程 docker compose down # 或 pkill nofx # 重启 docker compose up -d ``` --- ## AI 与模型问题 ### 支持哪些 AI 模型? - **DeepSeek**(推荐性价比) - **Qwen**(阿里云通义千问) - **自定义 OpenAI 兼容 API**(可用于 OpenAI、通过代理的 Claude 或其他提供商) ### API 调用成本是多少? 取决于您的模型和决策频率: - **DeepSeek**:每天约 $0.10-0.50(1 个交易员,5 分钟间隔) - **Qwen**:每天约 $0.20-0.80 - **自定义 API**(例如 OpenAI GPT-4):每天约 $2-5 *基于典型使用的估算。实际成本因提供商和使用量而异。* ### 可以使用多个 AI 模型吗? 可以!每个交易员可以使用不同的 AI 模型。您甚至可以 A/B 测试不同模型。 ### AI 会从错误中学习吗? 会的,在一定程度上。NOFX 在每次决策提示中提供历史表现反馈,允许 AI 调整策略。 --- ## 数据与隐私 ### 我的数据存储在哪里? 所有数据都**本地存储**在 PostgreSQL(Docker 卷 `postgres_data`)中,另有: - `decision_logs/` - AI 决策记录 ### API 密钥安全吗? API 密钥存储在本地数据库中。永远不要分享您的数据库或 `.env` 文件。我们建议使用带 IP 白名单限制的 API 密钥。 ### 可以导出交易历史吗? 可以!使用 `pg_dump` 或 `psql` 导出数据: ```bash docker compose exec postgres \ psql -U nofx -d nofx -c "SELECT * FROM trades;" ``` --- ## 故障排查 ### 在哪里可以找到详细的故障排查? 查看全面的[故障排查指南](TROUBLESHOOTING.zh-CN.md),包含: - 分步诊断方法 - 日志收集方法 - 常见错误解决方案 - 紧急重置步骤 ### 如何报告 Bug? 1. 先查看[故障排查指南](TROUBLESHOOTING.zh-CN.md) 2. 搜索[现有 Issues](https://github.com/NoFxAiOS/nofx/issues) 3. 如果没找到,使用我们的 [Bug 报告模板](../../.github/ISSUE_TEMPLATE/bug_report.md) ### 在哪里可以获得帮助? - [GitHub Discussions](https://github.com/NoFxAiOS/nofx/discussions) - [Telegram 社区](https://t.me/nofx_dev_community) - [GitHub Issues](https://github.com/NoFxAiOS/nofx/issues) --- ## 贡献 ### 可以为 NOFX 贡献代码吗? 可以!我们欢迎贡献: - Bug 修复和新功能 - 文档改进 - 翻译 - 查看[贡献指南](../CONTRIBUTING.md) ### 如何建议新功能? 提交 [Feature Request](https://github.com/NoFxAiOS/nofx/issues/new/choose) 说明您的想法! --- **最后更新:** 2025-11-02 --- ### Guides/README # 📘 NOFX User Guides **Language:** [English](README.md) | [中文](README.zh-CN.md) Comprehensive guides to help you use NOFX effectively. --- ## 📚 Available Guides ### 🔧 Basic Usage | Guide | Description | Status | |-------|-------------|--------| | [FAQ (English)](faq.en.md) | Frequently asked questions | ✅ Available | | [FAQ (中文)](faq.zh-CN.md) | 常见问题解答 | ✅ Available | | Configuration Guide | Advanced settings and options | 🚧 Coming Soon | | Trading Strategies | AI trading strategy examples | 🚧 Coming Soon | --- ## 🐛 Troubleshooting ### Common Issues **Issue: TA-Lib not found** ```bash # macOS brew install ta-lib # Ubuntu/Debian sudo apt-get install libta-lib0-dev ``` **Issue: Precision error** - System auto-handles LOT_SIZE from exchange - Check network connection - Verify exchange API is accessible **Issue: AI API timeout** - Check API key validity - Verify network connection - Check API balance/credits - Timeout is set to 120 seconds **Issue: Frontend can't connect** - Ensure backend is running (http://localhost:8080) - Check if port 8080 is available - Check browser console for errors --- ## 📖 Usage Tips ### Best Practices **1. Risk Management** - Start with small amounts (100-500 USDT) - Use subaccounts for additional safety - Set reasonable leverage limits - Monitor daily loss limits **2. Performance Monitoring** - Check decision logs regularly - Analyze win rate and profit factor - Review AI reasoning (Chain of Thought) - Track equity curve trends **3. Configuration** - Test on testnet first - Gradually increase trading amounts - Adjust scan intervals (3-5 minutes recommended) - Use default coin list for beginners --- ## 🎯 Advanced Topics ### Multi-Trader Competition Run multiple AI models simultaneously: - Qwen vs DeepSeek head-to-head - Compare performance in real-time - Identify best-performing strategies ### Custom Coin Pools - Use external API for coin selection - Combine AI500 + OI Top data - Filter by liquidity and volume ### Exchange Integration - Binance Futures (CEX) - Hyperliquid (DEX) - Aster DEX (Binance-compatible) --- ## 📊 Understanding Metrics ### Key Performance Indicators **Win Rate** - Percentage of profitable trades - Target: >50% for consistent profit **Profit Factor** - Ratio of gross profit to gross loss - Target: >1.5 (1.5:1 or better) **Sharpe Ratio** - Risk-adjusted return measure - Higher is better (>1.0 is good) **Maximum Drawdown** - Largest peak-to-trough decline - Keep under 20% for safety --- ## 🔗 Related Documentation - [Getting Started (EN)](../getting-started/README.md) - Initial setup - [Getting Started (中文)](../getting-started/README.zh-CN.md) - 初始设置 - [Community](../community/README.md) - Contributing and bounties - [FAQ (English)](faq.en.md) - Common questions - [FAQ (中文)](faq.zh-CN.md) - 常见问题 --- ## 🆘 Need Help? **Can't find what you need?** - 💬 [Telegram Community](https://t.me/nofx_dev_community) - 🐛 [GitHub Issues](https://github.com/NoFxAiOS/nofx/issues) - 🐦 [Twitter @nofx_official](https://x.com/nofx_official) --- [← Back to Documentation Home](../README.md) --- ### Guides/README.Zh CN # 📘 NOFX 使用指南 **语言:** [English](README.md) | [中文](README.zh-CN.md) 帮助您有效使用 NOFX 的综合指南。 --- ## 📚 可用指南 ### 🔧 基础使用 | 指南 | 描述 | 状态 | |------|------|------| | [FAQ (中文)](faq.zh-CN.md) | 常见问题解答 | ✅ 可用 | | [FAQ (English)](faq.en.md) | Frequently asked questions | ✅ 可用 | | 配置指南 | 高级设置和选项 | 🚧 即将推出 | | 交易策略 | AI 交易策略示例 | 🚧 即将推出 | --- ## 🐛 故障排除 ### 常见问题 **问题:找不到 TA-Lib** ```bash # macOS brew install ta-lib # Ubuntu/Debian sudo apt-get install libta-lib0-dev ``` **问题:精度错误** - 系统自动处理交易所的 LOT_SIZE - 检查网络连接 - 验证交易所 API 可访问 **问题:AI API 超时** - 检查 API 密钥有效性 - 验证网络连接 - 检查 API 余额/额度 - 超时设置为 120 秒 **问题:前端无法连接** - 确保后端正在运行 (http://localhost:8080) - 检查端口 8080 是否可用 - 检查浏览器控制台错误 --- ## 📖 使用技巧 ### 最佳实践 **1. 风险管理** - 从小金额开始(100-500 USDT) - 使用子账户增加安全性 - 设置合理的杠杆限制 - 监控每日亏损限制 **2. 性能监控** - 定期检查决策日志 - 分析胜率和盈利因子 - 审查 AI 推理(思维链) - 跟踪权益曲线趋势 **3. 配置** - 先在测试网测试 - 逐步增加交易金额 - 调整扫描间隔(推荐 3-5 分钟) - 初学者使用默认币种列表 --- ## 🎯 进阶主题 ### 多交易员竞赛 同时运行多个 AI 模型: - Qwen vs DeepSeek 对决 - 实时比较性能 - 识别表现最佳的策略 ### 自定义币种池 - 使用外部 API 进行币种选择 - 结合 AI500 + OI Top 数据 - 按流动性和交易量过滤 ### 交易所集成 - Binance Futures(中心化交易所) - Hyperliquid(去中心化交易所) - Aster DEX(兼容 Binance) --- ## 📊 理解指标 ### 关键性能指标 **胜率(Win Rate)** - 盈利交易的百分比 - 目标:>50% 以获得稳定盈利 **盈利因子(Profit Factor)** - 总盈利与总亏损的比率 - 目标:>1.5(1.5:1 或更好) **夏普比率(Sharpe Ratio)** - 风险调整后的收益衡量 - 越高越好(>1.0 为良好) **最大回撤(Maximum Drawdown)** - 从峰值到谷值的最大跌幅 - 为安全起见保持在 20% 以下 --- ## 🔗 相关文档 - [快速开始](../getting-started/README.zh-CN.md) - 初始设置 - [社区](../community/README.md) - 贡献和悬赏 - [FAQ 中文](faq.zh-CN.md) - 常见问题 - [FAQ English](faq.en.md) - Common questions --- ## 🆘 需要帮助? **找不到您需要的内容?** - 💬 [Telegram 社区](https://t.me/nofx_dev_community) - 🐛 [GitHub Issues](https://github.com/NoFxAiOS/nofx/issues) - 🐦 [Twitter @nofx_official](https://x.com/nofx_official) --- [← 返回文档首页](../README.md) --- ### Guides/TROUBLESHOOTING # 🔧 Troubleshooting Guide This guide helps you diagnose and fix common issues before submitting a bug report. --- ## 📋 Quick Diagnostic Checklist Before reporting a bug, please check: 1. ✅ **Backend is running**: `docker compose ps` or `ps aux | grep nofx` 2. ✅ **Frontend is accessible**: Open http://localhost:3000 in browser 3. ✅ **API is responding**: `curl http://localhost:8080/api/health` 4. ✅ **Check logs for errors**: See [How to Capture Logs](#how-to-capture-logs) below --- ## 🐛 Common Issues & Solutions ### 1. Trading Issues #### ❌ Only Opening Short Positions (Issue #202) **Symptom:** AI only opens short positions, never long positions, even when market is bullish. **Root Cause:** Binance account is in **One-way Mode** instead of **Hedge Mode**. **Solution:** 1. Login to [Binance Futures](https://www.binance.com/futures/BTCUSDT) 2. Click **⚙️ Preferences** (top right) 3. Select **Position Mode** 4. Switch to **Hedge Mode** (双向持仓) 5. ⚠️ **Important:** Close all positions before switching **Why this happens:** - Code uses `PositionSide(LONG)` and `PositionSide(SHORT)` parameters - These only work in Hedge Mode - In One-way Mode, orders fail or only one direction works **For Subaccounts:** - Some Binance subaccounts may not have permission to change position mode - Use main account or contact Binance support to enable this permission --- #### ❌ Order Error: `code=-4061` Position Side Mismatch **Error Message:** `Order's position side does not match user's setting` **Solution:** Same as above - switch to Hedge Mode. --- #### ❌ Leverage Error: `Subaccounts restricted to 5x leverage` **Symptom:** Orders fail with leverage error when trying to use >5x leverage. **Solution:** 1. Open Web UI → Trader Settings 2. Set leverage to 5x or lower: ```json { "btc_eth_leverage": 5, "altcoin_leverage": 5 } ``` 3. Or use main account (supports up to 50x BTC/ETH, 20x altcoins) --- #### ❌ Positions Not Executing **Check these:** 1. **API Permissions**: - Go to Binance → API Management - Verify "Enable Futures" is checked - Check IP whitelist (if enabled) 2. **Account Balance**: - Ensure sufficient USDT in Futures wallet - Check margin usage is not at 100% 3. **Symbol Status**: - Verify trading pair is active on exchange - Check if symbol is in maintenance mode 4. **Decision Logs**: ```bash # Check latest decision ls -lt decision_logs/your_trader_id/ | head -5 cat decision_logs/your_trader_id/latest_file.json ``` - Look for AI decision: was it "wait", "hold", or actual trade? - Check if position_size_usd is within limits --- ### 2. AI Decision Issues #### ❌ AI Always Says "Wait" / "Hold" **Possible Causes:** 1. **Market Conditions**: AI may genuinely see no good opportunities 2. **Risk Limits**: Account equity too low, margin usage too high 3. **Historical Performance**: AI being cautious after losses **How to Check:** ```bash # View latest decision reasoning cat decision_logs/your_trader_id/$(ls -t decision_logs/your_trader_id/ | head -1) ``` Look at the AI's Chain-of-Thought reasoning section. **Solutions:** - Wait for better market conditions - Check if all candidate coins have low liquidity - Verify `use_default_coins: true` or coin pool API is working --- #### ❌ AI Making Bad Decisions **Remember:** AI trading is experimental and not guaranteed to be profitable. **Things to Check:** 1. **Decision Interval**: Is it too short? (Recommended: 3-5 minutes) 2. **Leverage Settings**: Too aggressive? 3. **Historical Feedback**: Check performance logs to see if AI is learning 4. **Market Volatility**: High volatility = higher risk **Adjustments:** - Reduce leverage for more conservative trading - Increase decision interval to reduce over-trading - Use smaller initial balance for testing --- ### 3. Connection & API Issues #### ❌ Docker Image Pull Failed (China Mainland) **Error:** `ERROR [internal] load metadata for docker.io/library/...` **Symptoms:** - `docker compose build` or `docker compose up` hangs - Timeout errors: `timeout`, `connection refused` - Cannot pull images from Docker Hub **Root Cause:** Access to Docker Hub is restricted or extremely slow in mainland China. **Solution 1: Configure Docker Registry Mirror (Recommended)** 1. **Edit Docker configuration file:** ```bash # Linux sudo nano /etc/docker/daemon.json # macOS (Docker Desktop) # Settings → Docker Engine ``` 2. **Add China registry mirrors:** ```json { "registry-mirrors": [ "https://docker.m.daocloud.io", "https://docker.1panel.live", "https://hub.rat.dev", "https://dockerpull.com", "https://dockerhub.icu" ] } ``` 3. **Restart Docker:** ```bash # Linux sudo systemctl restart docker # macOS/Windows # Restart Docker Desktop ``` 4. **Rebuild:** ```bash docker compose build --no-cache docker compose up -d ``` **Solution 2: Use VPN** 1. Connect to VPN (Taiwan nodes recommended) 2. Ensure **global mode** instead of rule-based mode 3. Re-run `docker compose build` **Solution 3: Offline Image Download** If above methods don't work: 1. **Use image proxy websites:** - https://proxy.vvvv.ee/images.html (offline download available) - https://github.com/dongyubin/DockerHub (mirror list) 2. **Manually import images:** ```bash # After downloading image files docker load -i golang-1.25-alpine.tar docker load -i node-20-alpine.tar docker load -i nginx-alpine.tar ``` 3. **Verify images are loaded:** ```bash docker images | grep golang docker images | grep node docker images | grep nginx ``` **Verify registry mirror is working:** ```bash # Check Docker info docker info | grep -A 10 "Registry Mirrors" # Should show your configured mirrors ``` **Related Issue:** [#168](https://github.com/NoFxAiOS/nofx/issues/168) --- #### ❌ Backend Won't Start **Error:** `port 8080 already in use` **Solution:** ```bash # Find what's using the port lsof -i :8080 # OR netstat -tulpn | grep 8080 # Kill the process or change port in .env NOFX_BACKEND_PORT=8081 ``` --- #### ❌ Frontend Can't Connect to Backend **Symptoms:** - UI shows "Loading..." forever - Browser console shows 404 or network errors **Solutions:** 1. **Check backend is running:** ```bash docker compose ps # Should show backend as "Up" # OR curl http://localhost:8080/api/health # Should return {"status":"ok"} ``` 2. **Check port configuration:** - Backend default: 8080 - Frontend default: 3000 - Verify `.env` settings match 3. **CORS Issues:** - If running frontend and backend on different ports/domains - Check browser console for CORS errors - Backend should allow frontend origin --- #### ❌ Exchange API Errors **Common Errors:** - `code=-1021, msg=Timestamp for this request is outside of the recvWindow` - `invalid signature` - `timestamp` errors **Root Cause:** System time is inaccurate, differing from Binance server time by more than allowed range (typically 5 seconds). **Solution 1: Sync System Time (Recommended)** ```bash # Method 1: Use ntpdate (most common) sudo ntpdate pool.ntp.org # Method 2: Use other NTP servers sudo ntpdate -s time.nist.gov sudo ntpdate -s ntp.aliyun.com # Aliyun NTP (fast in China) # Method 3: Enable automatic time sync (Linux) sudo timedatectl set-ntp true # Verify time is correct date # Should show current accurate time ``` **Docker Environment Special Note:** If using Docker, container time may be out of sync with host: ```bash # Check container time docker exec nofx-backend date # If time is wrong, restart Docker service sudo systemctl restart docker # Or add timezone in docker-compose.yml environment: - TZ=Asia/Shanghai # or your timezone ``` **Solution 2: Verify API Keys** If errors persist after time sync: 1. **Check API Keys:** - Not expired - Have correct permissions (Futures enabled) - IP whitelist includes your server IP 2. **Regenerate API Keys:** - Login to Binance → API Management - Delete old key - Create new key - Update NOFX configuration **Solution 3: Check Rate Limits** Binance has strict API rate limits: - **Requests per minute limit** - Reduce number of traders - Increase decision interval (e.g., from 1min to 3-5min) **Related Issue:** [#60](https://github.com/NoFxAiOS/nofx/issues/60) --- ### 4. Frontend Issues #### ❌ UI Not Updating / Showing Old Data **Solutions:** 1. **Hard Refresh:** - Chrome/Firefox: `Ctrl+Shift+R` (Windows/Linux) or `Cmd+Shift+R` (Mac) - Safari: `Cmd+Option+R` 2. **Clear Browser Cache:** - Settings → Privacy → Clear browsing data - Or open in Incognito/Private mode 3. **Check SWR Polling:** - Frontend uses SWR with 5-10s intervals - Data should auto-refresh - Check browser console for fetch errors --- #### ❌ Charts Not Rendering **Possible Causes:** 1. No historical data yet (system just started) 2. JavaScript errors in console 3. Browser compatibility issues **Solutions:** - Wait 5-10 minutes for data to accumulate - Check browser console (F12) for errors - Try different browser (Chrome recommended) - Ensure backend API endpoints are returning data --- ### 5. Database Issues #### ❌ `database is locked` Error **Cause:** SQLite database being accessed by multiple processes. **Solution:** ```bash # Stop all NOFX processes docker compose down # OR pkill nofx # Restart docker compose up -d # OR ./nofx ``` --- #### ❌ Trader Configuration Not Saving **Check:** 1. **PostgreSQL container health** ```bash docker compose ps postgres docker compose exec postgres pg_isready -U nofx -d nofx ``` 2. **Inspect data directly** ```bash ./scripts/view_pg_data.sh # quick overview docker compose exec postgres \ psql -U nofx -d nofx -c "SELECT COUNT(*) FROM traders;" ``` 3. **Disk space** ```bash df -h # Ensure disk not full ``` --- ## 📊 How to Capture Logs ### Backend Logs **Docker:** ```bash # View last 100 lines docker compose logs backend --tail=100 # Follow live logs docker compose logs -f backend # Save to file docker compose logs backend --tail=500 > backend_logs.txt ``` **Manual binary:** ```bash # If running without Docker, the terminal running ./nofx prints logs ``` --- ### Frontend Logs (Browser Console) 1. **Open DevTools:** - Press `F12` or Right-click → Inspect 2. **Console Tab:** - See JavaScript errors and warnings - Look for red error messages 3. **Network Tab:** - Filter by "XHR" or "Fetch" - Look for failed requests (red status codes) - Click on failed request → Preview/Response to see error details 4. **Capture Screenshot:** - Windows: `Win+Shift+S` - Mac: `Cmd+Shift+4` - Or use browser DevTools screenshot feature --- ### Decision Logs (Trading Issues) ```bash # List recent decision logs ls -lt decision_logs/your_trader_id/ | head -10 # View latest decision cat decision_logs/your_trader_id/$(ls -t decision_logs/your_trader_id/ | head -1) | jq . # Search for specific symbol grep -r "BTCUSDT" decision_logs/your_trader_id/ # Find decisions that resulted in trades grep -r '"action": "open_' decision_logs/your_trader_id/ ``` **What to look for in decision logs:** - `chain_of_thought`: AI's reasoning process - `user_prompt`: Market data AI received - `decision`: Final decision (action, symbol, leverage, etc.) - `account_state`: Account balance, margin, positions at decision time - `execution_result`: Whether trade succeeded or failed --- ## 🔍 Diagnostic Commands ### System Health Check ```bash # Backend health curl http://localhost:8080/api/health # List all traders curl http://localhost:8080/api/traders # Check specific trader status curl http://localhost:8080/api/status?trader_id=your_trader_id # Get account info curl http://localhost:8080/api/account?trader_id=your_trader_id ``` ### Docker Status ```bash # Check all containers docker compose ps # Check resource usage docker stats # Restart specific service docker compose restart backend docker compose restart frontend ``` ### Database Queries ```bash # Check traders in database docker compose exec postgres \ psql -U nofx -d nofx -c "SELECT id, name, ai_model_id, exchange_id, is_running FROM traders;" # Check AI models docker compose exec postgres \ psql -U nofx -d nofx -c "SELECT id, name, provider, enabled FROM ai_models;" # Check system config docker compose exec postgres \ psql -U nofx -d nofx -c "SELECT key, value FROM system_config;" ``` --- ## 📝 Still Having Issues? If you've tried all the above and still have problems: 1. **Gather Information:** - Backend logs (last 100 lines) - Frontend console screenshot - Decision logs (if trading issue) - Your environment details 2. **Submit Bug Report:** - Use the [Bug Report Template](../../.github/ISSUE_TEMPLATE/bug_report.md) - Include all logs and screenshots - Describe what you've already tried 3. **Join Community:** - [Telegram Developer Community](https://t.me/nofx_dev_community) - [GitHub Discussions](https://github.com/NoFxAiOS/nofx/discussions) --- ## 🆘 Emergency: System Completely Broken **Complete Reset (⚠️ Will lose trading history):** ```bash # Stop everything docker compose down # Optional: back up PostgreSQL data docker compose exec postgres \ pg_dump -U nofx -d nofx > backup_nofx.sql # Remove all persisted volumes (fresh start) docker compose down -v # Restart docker compose up -d --build # Reconfigure through web UI open http://localhost:3000 ``` **Partial Reset (Keep configuration, clear logs):** ```bash # Clear decision logs rm -rf decision_logs/* # Clear Docker cache and rebuild docker compose down docker compose build --no-cache docker compose up -d ``` --- ## 📚 Additional Resources - **[FAQ](faq.en.md)** - Frequently Asked Questions - **[Getting Started](../getting-started/README.md)** - Setup guide - **[Architecture Docs](../architecture/README.md)** - How the system works - **[CLAUDE.md](../../CLAUDE.md)** - Developer documentation --- **Last Updated:** 2025-11-02 ---