{"id":"6187d976-2365-4235-bed4-5eb04e7ef198","entityType":"agent","slug":"clawhub-jeffersonling1217-png-futu-trading-bot","name":"futu-trading-bot","canonicalUrl":"https://www.xpersona.co/agent/clawhub-jeffersonling1217-png-futu-trading-bot","canonicalPath":"/agent/clawhub-jeffersonling1217-png-futu-trading-bot","generatedAt":"2026-10-10T07:22:56.150Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T21:51:03.969Z","emptyReason":null},"description":"Use Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 2K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s178bcyctp44ydnda4m1apj4hx83hv3f:futu-trading-bot","sourceUrl":"https://clawhub.ai/jeffersonling1217-png/futu-trading-bot","homepage":"https://clawhub.ai/jeffersonling1217-png/skills/futu-trading-bot","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/jeffersonling1217-png/futu-trading-bot","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/jeffersonling1217-png/skills/futu-trading-bot","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":55,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"futu-trading-bot technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T21:51:03.969Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T21:51:03.969Z","emptyReason":null},"stars":null,"forks":null,"downloads":1961,"packageName":null,"latestVersion":"1.0.9","tractionLabel":"2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T21:51:03.969Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T21:51:03.969Z","lastCrawledAt":"2026-10-09T21:51:03.969Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T21:51:03.969Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.9","createdAt":"2026-08-06T09:43:55.466Z","changelog":"Pin pydantic==2.12.5 to satisfy supply-chain scanner (SC4); keep 1.0.8 security confirm gates","fileCount":20,"zipByteSize":45131},{"version":"1.0.8","createdAt":"2026-08-06T09:28:13.368Z","changelog":"Security: confirm gates for REAL trades/unlock/cancel_all; opt-in account persist; remove stdin password; pin deps; strengthen SKILL/README warnings and agent triggers","fileCount":20,"zipByteSize":45014},{"version":"1.0.7","createdAt":"2026-03-24T02:29:59.800Z","changelog":"Docs: sync latest README/docs; add strategy helpers and runtime; add unified quote/orderbook stream startup","fileCount":20,"zipByteSize":43755},{"version":"1.0.6","createdAt":"2026-03-23T06:03:44.887Z","changelog":"Fix: reinitialize trade contexts for modify/cancel flows; explicit close for account/quote/trade contexts; add preflight checks and runtime guidance","fileCount":13,"zipByteSize":32067},{"version":"1.0.5","createdAt":"2026-03-19T07:23:41.501Z","changelog":"Fix: add explicit context close to avoid hanging threads; add preflight environment checks; improve sandbox/runtime guidance","fileCount":13,"zipByteSize":32069},{"version":"1.0.4","createdAt":"2026-03-19T01:41:28.640Z","changelog":"**Summary:** Major update with expanded codebase, simplified documentation, and more robust workflow guidance. - Added over 50 new files, including sample scripts, tests, and project modules for trading strategy automation. - Documentation ('SKILL.md') now clearer, with concise usage guides, module mapping, runtime conventions, and explicit error handling instructions. - Sample configurations and real trading script templates provided. - Updated license to MIT and clarified password handling and account information caching. - Improved developer experience for both interactive and script-based usage.","fileCount":66,"zipByteSize":84127},{"version":"1.0.3","createdAt":"2026-03-16T06:14:16.979Z","changelog":"Docs: add generic strategy template + backend exec guidance","fileCount":12,"zipByteSize":27157},{"version":"1.0.2","createdAt":"2026-03-16T05:42:17.693Z","changelog":"update to enable strategy running on the backend","fileCount":12,"zipByteSize":27090}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s178bcyctp44ydnda4m1apj4hx83hv3f:futu-trading-bot","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s178bcyctp44ydnda4m1apj4hx83hv3f:futu-trading-bot` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/jeffersonling1217-png/futu-trading-bot before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeffersonling1217-png-futu-trading-bot/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeffersonling1217-png-futu-trading-bot/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeffersonling1217-png-futu-trading-bot/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jeffersonling1217-png-futu-trading-bot/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jeffersonling1217-png-futu-trading-bot/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jeffersonling1217-png-futu-trading-bot/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T07:22:56.148Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeffersonling1217-png-futu-trading-bot/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeffersonling1217-png-futu-trading-bot/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeffersonling1217-png-futu-trading-bot/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jeffersonling1217-png-futu-trading-bot/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T21:51:03.969Z","emptyReason":null},"readme":"Skill: futu-trading-bot\n\nOwner: jeffersonling1217-png\n\nSummary: Use Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.\n\nTags: latest:1.0.9\n\nVersion history:\n\nv1.0.9 | 2026-08-06T09:43:55.466Z | user\n\nPin pydantic==2.12.5 to satisfy supply-chain scanner (SC4); keep 1.0.8 security confirm gates\n\nv1.0.8 | 2026-08-06T09:28:13.368Z | user\n\nSecurity: confirm gates for REAL trades/unlock/cancel_all; opt-in account persist; remove stdin password; pin deps; strengthen SKILL/README warnings and agent triggers\n\nv1.0.7 | 2026-03-24T02:29:59.800Z | user\n\nDocs: sync latest README/docs; add strategy helpers and runtime; add unified quote/orderbook stream startup\n\nv1.0.6 | 2026-03-23T06:03:44.887Z | user\n\nFix: reinitialize trade contexts for modify/cancel flows; explicit close for account/quote/trade contexts; add preflight checks and runtime guidance\n\nv1.0.5 | 2026-03-19T07:23:41.501Z | user\n\nFix: add explicit context close to avoid hanging threads; add preflight environment checks; improve sandbox/runtime guidance\n\nv1.0.4 | 2026-03-19T01:41:28.640Z | auto\n\n**Summary:** Major update with expanded codebase, simplified documentation, and more robust workflow guidance.\n\n- Added over 50 new files, including sample scripts, tests, and project modules for trading strategy automation.\n- Documentation ('SKILL.md') now clearer, with concise usage guides, module mapping, runtime conventions, and explicit error handling instructions.\n- Sample configurations and real trading script templates provided.\n- Updated license to MIT and clarified password handling and account information caching.\n- Improved developer experience for both interactive and script-based usage.\n\nv1.0.3 | 2026-03-16T06:14:16.979Z | user\n\nDocs: add generic strategy template + backend exec guidance\n\nv1.0.2 | 2026-03-16T05:42:17.693Z | user\n\nupdate to enable strategy running on the backend\n\nv1.0.1 | 2026-03-09T09:07:42.926Z | user\n\nUpdate LICENSE file\n\nv0.1.9 | 2026-03-08T14:22:53.080Z | user\n\n最终版本：包含所有安全修复和文档更新。MIT许可证，无敏感信息。\n\nv0.1.8 | 2026-03-08T13:08:04.894Z | user\n\n紧急安全修复：1. 彻底删除真实的config.json和account_info.json；2. 只保留config_example.json；3. 确保发布包中没有任何敏感信息。\n\nv0.1.7 | 2026-03-08T13:07:27.785Z | user\n\n安全修复：1. 删除真实的config.json和account_info.json；2. 只保留config_example.json；3. 确保没有敏感信息泄露。\n\nv0.1.6 | 2026-03-08T13:05:29.828Z | user\n\n添加MIT许可证：1. 创建LICENSE文件；2. 更新pyproject.toml；3. 在README.md和SKILL.md中添加许可证说明。\n\nv0.1.5 | 2026-03-08T12:44:25.426Z | user\n\n文档更新：1. 添加中英文概述，提升吸引力；2. 优化快速开始指南；3. 完善使用说明。\n\nv0.1.4 | 2026-03-08T12:43:57.663Z | user\n\n文档更新：1. 添加中英文概述，提升吸引力；2. 优化快速开始指南；3. 完善使用说明。\n\nv0.1.3 | 2026-03-08T12:40:00.533Z | user\n\n清理版本：1. 删除futu api旧文件夹；2. 移除冗余文件；3. 优化目录结构。\n\nv0.1.2 | 2026-03-08T12:39:08.374Z | auto\n\n**Streamlined configuration and removed unused demo files**\n\n- Simplified README and SKILL documentation for quicker setup and clearer config instructions.\n- Added `json/config.json` and `json/account_info.json` for explicit configuration and account info storage.\n- Introduced `docs/development_plan.md` for development tracking.\n- Removed 11 legacy/demonstration files from the futu api directory to reduce clutter.\n- No interface or runtime changes to core trading, account, or quote functionality.\n\nv0.1.1 | 2026-03-08T12:18:43.780Z | auto\n\n- Added comprehensive documentation in SKILL.md covering setup, workflows, and usage examples for account, quote, and trade operations with Futu OpenD and real HK market data.\n- Detailed module and function mapping provided for easy integration.\n- Included canonical Python import examples and API call samples for each workflow stage.\n- Provided configuration instructions and error handling best-practices.\n\nArchive index:\n\nArchive v1.0.9: 20 files, 45131 bytes\n\nFiles: _meta.json (135b), docs/account.md (1889b), docs/config.md (1531b), docs/development_plan.md (3458b), docs/quote.md (1516b), docs/strategy.md (1091b), docs/trade.md (1967b), json/config_example.json (306b), pyproject.toml (570b), README.md (6563b), requirements.txt (38b), skill-card.md (2859b), SKILL.md (17937b), src/account_manager.py (15211b), src/config_manager.py (7404b), src/preflight_check.py (8558b), src/quote_service.py (20690b), src/strategy_runtime.py (2934b), src/strategy.py (3776b), src/trade_service.py (36331b)\n\nFile v1.0.9:SKILL.md\n\n---\r\nname: futu-trading-bot\r\ndescription: Use Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.\r\nlicense: MIT-0\r\nmetadata:\r\n  openclaw:\r\n    emoji: \"📈\"\r\n    requires:\r\n      bins: [\"python3\", \"pip\"]\r\n    permissions:\r\n      - local-network  # Futu OpenD (default 127.0.0.1:11111)\r\n      - filesystem-read  # json/config.json and skill modules\r\n      - filesystem-write  # optional account_info.json / strategy logs / PID files when user opts in\r\n      - process  # optional background strategy only after explicit user confirmation\r\n---\r\n\r\n# Futu Trade Bot Skills 📈\r\n\r\n## ⚠️ Security & Safety (READ FIRST)\r\n\r\nThis skill can control a **live brokerage account** via Futu OpenD. Misuse can cause **irreversible financial loss**.\r\n\r\n**Hard rules for the agent:**\r\n1. **Default to SIMULATE.** Never use `trd_env=\"REAL\"` unless the user explicitly requests live trading and confirms the exact order parameters.\r\n2. **State-changing actions require explicit user approval**, then pass `confirm=True`:\r\n   - `unlock_trade` / `lock_trade`\r\n   - `submit_order` when `trd_env=\"REAL\"`\r\n   - `modify_order` / `cancel_order` when `trd_env=\"REAL\"`\r\n   - `cancel_all_orders` in **any** environment\r\n3. **Read-only actions** (quotes, `get_account_info(persist=False)`) may run without `confirm`.\r\n4. **Do not** collect trading passwords via interactive stdin. Use config (`trade_password_md5` preferred) or an explicit parameter the user already provided out-of-band.\r\n5. **Do not** write `json/account_info.json` unless the user asks to cache accounts (`persist=True`).\r\n6. **Background strategies** (write script / start process / stop process) only after the user clearly asks and confirms symbol, qty, `SIMULATE`/`REAL`, and log/PID paths.\r\n7. If a restricted sandbox blocks OpenD or `~/.com.futunn.FutuOpenD/Log`, **tell the user** before suggesting `host` / `elevated` mode — never silently escalate.\r\n\r\n**中文硬规则：** 默认模拟盘；真金白银/解锁/全部撤单必须先复述参数并得到用户明确同意，再传 `confirm=True`；禁止 stdin 要密码；默认不把账户信息写盘。\r\n\r\n## 🎯 Overview / 概述\r\n\r\n**English Version:**\r\nA trading bot skill based on Futu OpenAPI that enables natural language trading. This skill encapsulates Futu's market quote and order execution APIs, allowing agents to perform real-time trading operations through simple commands or scripts. Perfect for implementing natural language trading strategies and automated workflows.\r\n\r\n**Important**: Always use the encapsulated functions provided in this skill (e.g., `submit_order`, `get_market_snapshot`). **Never call Futu SDK functions directly** (`ctx.place_order`, `ctx.get_market_snapshot`), as this will bypass connection management, parameter validation, and error handling, leading to unpredictable failures and resource leaks.\r\n\r\n**中文版本:**\r\n基于富途牛牛API接口的交易机器人技能，帮助用户用自然语言进行交易。本技能已将富途牛牛的行情报价、下单交易等功能做了完整封装，可供智能助手随时调用。建议通过命令行或脚本来实现自然语言的策略生成和交易执行。\r\n\r\n**重要提示**：请始终使用本技能提供的封装函数（如 `submit_order`、`get_market_snapshot`）。**切勿直接调用富途SDK的原始函数**（例如 `ctx.place_order`），否则会绕过连接管理、参数校验和错误处理，导致不可预料的失败和资源泄漏。\r\n\r\n---\r\n\r\n## When to Use This Skill / 使用场景\r\n\r\n### Read-only (no confirm required)\r\n- **行情查询**：“腾讯现在多少钱？”、“查港股报价”、“看 K 线 / 逐笔”\r\n- **账户列表查询**：“看看我有哪些账户”（`get_account_info()`，默认不落盘）\r\n\r\n### State-changing (require explicit user intent + confirmation)\r\n- **解锁 / 锁定交易**：“解锁交易”、“锁定账户” → 复述风险后 `unlock_trade(confirm=True)` / `lock_trade(confirm=True)`\r\n- **下单 / 改单 / 撤单**：“帮我买 100 股腾讯限价 350” → 复述 code/side/qty/price/`SIMULATE|REAL`，用户确认后再调用；`REAL` 必须 `confirm=True`\r\n- **全部撤单**：“撤销全部订单” → 高风险，**任何环境**都要 `cancel_all_orders(..., confirm=True)`\r\n- **策略启停**：仅当用户明确说启动/停止策略；先确认参数与环境，默认 `SIMULATE`\r\n\r\n**Do not** map vague chat like “看看市场怎么样” to unlock/order/cancel.\r\n\r\n**Note to agent**: Always use this skill's wrappers (`get_account_info`, `get_market_snapshot`, `submit_order`, …). **Never call Futu SDK functions directly**. Never skip `confirm` gates for privileged actions.\r\n\r\n## Quick Start / 快速开始\r\n\r\n**Prerequisites / 前提条件:**\r\n- Ensure Futu OpenD is running and HK quote entitlement is available.\r\n- 确保富途OpenD正在运行且拥有港股行情权限。\r\n- Futu OpenD must be reachable (default `127.0.0.1:11111`). The SDK may also need write access to `~/.com.futunn.FutuOpenD/Log`.\r\n- If a restricted sandbox blocks OpenD/log access, **ask the user** whether to rerun in `host` / `elevated` mode. Do not silently escalate privileges.\r\n- 若沙箱导致 OpenD/日志目录不可用，先告知用户再征得同意后使用 `host` / `elevated`，不要静默提权。\r\n\r\n**Setup Steps / 安装步骤:**\r\n1. Install this skill via ClawHub (if not installed yet):\r\n   ```bash\r\n   clawhub install futu-trading-bot\r\n   ```\r\n\r\n2. Enter the skill folder (default OpenClaw workspace path):\r\n   ```bash\r\n   cd ~/.openclaw/workspace/skills/futu-trading-bot\r\n   ```\r\n   If you installed to a different location, `cd` into that folder instead.\r\n\r\n3. Create virtual environment (recommended):\r\n   ```bash\r\n   python3 -m venv .venv\r\n   source .venv/bin/activate\r\n   ```\r\n\r\n4. Install package:\r\n   ```bash\r\n   pip install -e .\r\n   ```\r\n\r\n5. Configure credentials:\r\n   ```bash\r\n   cp json/config_example.json json/config.json\r\n   # Edit json/config.json with your Futu credentials\r\n   # 编辑json/config.json填写你的富途账户信息\r\n   ```\r\n\r\n## 依赖项\r\n\r\n本技能通过 `pip install -e .` 安装（版本见 `requirements.txt` / `pyproject.toml`）：\r\n- `futu-api==9.6.5608`\r\n- `pydantic>=2.7.0,<3`\r\n\r\n## Module Map\r\n\r\n- **Account**: `account_manager`\r\n  - `get_account_info(persist=False)` — default no disk write\r\n  - `unlock_trade(..., confirm=True)` — privileged\r\n  - `lock_trade(..., confirm=True)` — privileged\r\n- **Quote**: `quote_service` (read-oriented)\r\n  - Stage 1: `get_stock_basicinfo`, `get_market_state`\r\n  - Stage 2: `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, callbacks\r\n  - Stage 3: `get_market_snapshot`, `get_cur_kline`, `request_history_kline`, `get_rt_ticker`\r\n  - Stage 4: `start_quote_stream`, `start_orderbook_stream`\r\n- **Trade**: `trade_service` (privileged)\r\n  - `submit_order(..., confirm=)` — REAL requires confirm\r\n  - `modify_order` / `cancel_order` — REAL requires confirm\r\n  - `cancel_all_orders(..., confirm=True)` — always requires confirm\r\n- **Strategy Runtime**: `strategy_runtime` / `strategy` helpers\r\n\r\n## Standard Workflow\r\n\r\n1. Run `preflight_check` first.\r\n2. `get_account_info()` (no persist) and select `acc_id`.\r\n3. Quote/snapshot for target symbol (e.g. `HK.00700`).\r\n4. For live trading only after user confirmation: `unlock_trade(confirm=True)`.\r\n5. Orders with explicit `acc_id` + `trd_env` (prefer `SIMULATE`; REAL needs `confirm=True`).\r\n6. After live ops, `lock_trade(confirm=True)` if the user wants trading locked again.\r\n\r\n## Connection Lifecycle\r\n\r\n- Pull-style quote functions such as `get_market_snapshot`, `get_stock_basicinfo`, `get_market_state`, `get_cur_kline`, `request_history_kline`, and `get_rt_ticker` now close their quote context automatically after returning.\r\n- Trade functions such as `submit_order`, `modify_order`, and `cancel_all_orders` now close their trade/quote contexts automatically after returning.\r\n- Account functions such as `get_account_info`, `unlock_trade`, and `lock_trade` now close their contexts automatically after returning.\r\n- Subscription/callback flows keep the quote context open on purpose. For `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, `set_quote_callback`, and `set_orderbook_callback`, call `close_quote_service()` explicitly when you are done with the session.\r\n\r\n## Canonical Imports\r\n\r\n```python\r\n# Always use these import paths – do not import from futu directly\r\nfrom preflight_check import run_preflight\r\nfrom strategy import (\r\n    StrategyState, TradeGuard, in_trading_window,\r\n    trading_window_status, cooldown_elapsed, holding_timeout_exceeded\r\n)\r\nfrom strategy_runtime import run_strategy\r\nfrom account_manager import get_account_info, unlock_trade, lock_trade\r\nfrom quote_service import (\r\n    get_stock_basicinfo, get_market_state, get_market_snapshot,\r\n    get_cur_kline, request_history_kline, get_rt_ticker,\r\n    subscribe, unsubscribe, unsubscribe_all, query_subscription,\r\n    set_quote_callback, set_orderbook_callback,\r\n    start_quote_stream, start_orderbook_stream\r\n)\r\nfrom trade_service import submit_order, modify_order, cancel_order, cancel_all_orders\r\n```\r\n\r\n## Account Usage\r\n\r\n### Preflight\r\n```python\r\npreflight = run_preflight()\r\nif not preflight[\"success\"]:\r\n    print(preflight)\r\n    raise SystemExit(\"Preflight failed\")\r\n```\r\n\r\n```python\r\n# Get list of accounts (in-memory only by default)\r\ninfo = get_account_info()  # persist=False\r\nif info['success']:\r\n    accounts = info['accounts']\r\n    print(accounts)\r\n\r\n# Optional: cache accounts locally only if user asked\r\n# info = get_account_info(persist=True)\r\n\r\n# Unlock trade ONLY after explicit user approval\r\nunlock_trade(confirm=True)  # loads trade_password_md5 / trade_password from config\r\n\r\n# Lock trade after user approval\r\nlock_trade(confirm=True)\r\n```\r\n\r\n## Quote Usage\r\n\r\n### Basic Info / Market State\r\n```python\r\nget_stock_basicinfo(market=\"HK\", sec_type=\"STOCK\", code_list=[\"HK.00700\"])\r\nget_market_state([\"HK.00700\"])\r\n```\r\n\r\n### Snapshot (no subscription needed)\r\n```python\r\nsnap = get_market_snapshot([\"HK.00700\"])\r\nif snap['success']:\r\n    price = snap['data'][0]['last_price']\r\n```\r\n\r\n### K-Line\r\n```python\r\n# Current K-line (requires subscription, will auto-subscribe if needed)\r\nkline = get_cur_kline(code=\"HK.00700\", num=5, ktype=\"K_DAY\", autype=\"QFQ\")\r\n\r\n# Historical K-line\r\nhist = request_history_kline(\r\n    code=\"HK.00700\",\r\n    start=\"2026-02-20\",\r\n    end=\"2026-03-06\",\r\n    ktype=\"K_DAY\"\r\n)\r\n```\r\n\r\n### Ticker\r\n```python\r\ntickers = get_rt_ticker(code=\"HK.00700\", num=10)\r\n```\r\n\r\n### Subscription & Callbacks\r\n```python\r\ndef on_quote(payload):\r\n    print(payload)\r\n\r\nset_quote_callback(on_quote)\r\nsubscribe([\"HK.00700\"], [\"QUOTE\"], is_first_push=True, subscribe_push=True)\r\nquery_subscription()\r\nunsubscribe([\"HK.00700\"], [\"QUOTE\"])\r\nunsubscribe_all()\r\nclose_quote_service()\r\n```\r\n\r\n### Unified Stream Startup\r\n```python\r\ndef on_quote(payload):\r\n    print(payload)\r\n\r\nstart_quote_stream([\"HK.00700\"], on_quote)\r\n```\r\n\r\n### Strategy Helpers\r\n```python\r\nstate = StrategyState()\r\nguard = TradeGuard()\r\n\r\nif in_trading_window(start_time=\"09:30\", end_time=\"16:00\"):\r\n    with guard.locked():\r\n        pass\r\n```\r\n\r\n## Trade Usage\r\n\r\n```python\r\n# Preferred: SIMULATE (no confirm required by the gate)\r\nresult = submit_order(\r\n    code=\"HK.00700\",\r\n    side=\"BUY\",\r\n    qty=200,\r\n    acc_id=6017237,\r\n    trd_env=\"SIMULATE\",\r\n    price=150,\r\n    order_type=\"NORMAL\",\r\n)\r\n\r\n# REAL only after user explicitly approves the exact parameters\r\n# result = submit_order(..., trd_env=\"REAL\", confirm=True)\r\n\r\nmodify_order(\r\n    op=\"NORMAL\",\r\n    order_id=\"123456789\",\r\n    trd_env=\"SIMULATE\",\r\n    price=151,\r\n    qty=200,\r\n    acc_id=6017237,\r\n)\r\n\r\ncancel_order(order_id=\"123456789\", trd_env=\"SIMULATE\", acc_id=6017237)\r\n\r\n# Bulk cancel ALWAYS requires confirm=True\r\ncancel_all_orders(trd_env=\"SIMULATE\", acc_id=6017237, confirm=True)\r\n```\r\n\r\n## Running a Background Trading Strategy (Optional, User-Confirmed Only)\r\n\r\nThis skill does **not** auto-start long-running processes. Only if the user **explicitly** asks to start/stop a strategy:\r\n\r\n1. Run preflight.\r\n2. Restate parameters: symbol, account, qty, buy/sell rules, **SIMULATE (default) or REAL**, log path.\r\n3. Wait for user confirmation.\r\n4. Write a **fixed-parameter** strategy script from the template below (no arbitrary remote code).\r\n5. Start it with the platform process tools the user already authorized; record PID + log path.\r\n6. Stop only when the user asks; then terminate that PID and clean the PID file.\r\n\r\nDo **not** launch background strategies for vague requests. Do **not** use elevated/host mode without telling the user why.\r\n\r\n### Natural Language Triggers\r\n\r\n| User Request | Agent Action |\r\n|--------------|--------------|\r\n| “Start a strategy…” (explicit) | Confirm params → write template script → start after approval → return PID/log |\r\n| “How is my strategy doing?” | Read the agreed log file / check PID → summarize |\r\n| “Stop my strategy” | Confirm → stop the recorded PID → clean up |\r\n\r\n### 4.3 Script Template (for Agent Reference)\r\n\r\nWhen generating a strategy script, use the following template. It handles signals, logging, and state persistence correctly.\r\n\r\n```python\r\n#!/usr/bin/env python3\r\nimport sys\r\nimport time\r\nimport json\r\nimport os\r\nimport signal\r\nimport logging\r\nfrom pathlib import Path\r\n\r\n# If you installed the skill with `pip install -e .`, you can import modules directly.\r\n# Only use sys.path/PYTHONPATH hacks when you didn't install the package.\r\n\r\nfrom trade_service import submit_order\r\nfrom quote_service import get_market_snapshot\r\n\r\n# ===== Strategy parameters – fill by agent =====\r\n# Replace these placeholders with your own strategy settings.\r\nSYMBOL = \"HK.00700\"\r\nACC_ID = 0                 # fill from get_account_info()\r\nTRD_ENV = \"SIMULATE\"       # default to SIMULATE; use REAL only with explicit confirmation\r\nQTY = 0                    # position sizing / order quantity\r\nLOG_FILE = Path(\"strategy.log\")\r\nPID_FILE = Path(\"strategy.pid\")\r\n# ===============================================\r\n\r\nlogging.basicConfig(\r\n    filename=LOG_FILE,\r\n    level=logging.INFO,\r\n    format='%(asctime)s - %(levelname)s - %(message)s'\r\n)\r\n\r\n# Handle termination signals\r\ndef handle_exit(signum, frame):\r\n    logging.info(\"Received signal, stopping strategy\")\r\n    sys.exit(0)\r\n\r\nsignal.signal(signal.SIGTERM, handle_exit)\r\nsignal.signal(signal.SIGINT, handle_exit)\r\n\r\n# Write PID file\r\nwith open(PID_FILE, \"w\") as f:\r\n    f.write(str(os.getpid()))\r\n\r\nlogging.info(f\"Strategy started: {SYMBOL}\")\r\n\r\ntry:\r\n    while True:\r\n        snap = get_market_snapshot([SYMBOL])\r\n        if not snap[\"success\"]:\r\n            logging.error(f\"Quote failed: {snap['message']}\")\r\n            time.sleep(60)\r\n            continue\r\n        price = snap[\"data\"][0][\"last_price\"]\r\n        logging.info(f\"Current price: {price}\")\r\n\r\n        # --- Insert your strategy logic here ---\r\n        # Decide whether to trade based on your own signals/logic, then call submit_order(...).\r\n\r\n        time.sleep(60)   # check every minute\r\nexcept Exception as e:\r\n    logging.exception(\"Strategy crashed\")\r\nfinally:\r\n    if PID_FILE.exists():\r\n        PID_FILE.unlink()\r\n```\r\n\r\n### 4.4 Agent Execution Steps\r\n\r\n**User**: “Start a range strategy for Tencent, buy below 540, sell above 550.”\r\n\r\n**Agent**:\r\n1. Restate strategy params; default `TRD_ENV=SIMULATE`. Ask for confirmation.\r\n2. After approval, `get_account_info()` for `acc_id`.\r\n3. Write the template script with fixed parameters (e.g. `range_00700.py`).\r\n4. Start only the approved script; capture PID and log path.\r\n5. Reply with PID/log and remind the user how to stop it.\r\n\r\n### 4.5 Check Status\r\n\r\n**User**: “How is my strategy doing?”\r\n\r\n**Agent**:\r\n- Read last lines of log: `tail -n 20 strategy_00700.log`.\r\n- Check if process still running: `ps -p 12345`.\r\n- Summarize: “Strategy is running, last price was 542.5 at 10:30.”\r\n\r\n### 4.6 Stop Strategy\r\n\r\n**User**: “Stop my strategy.”\r\n\r\n**Agent**:\r\n- Confirm the user wants to stop the recorded PID.\r\n- Terminate that process, clean the PID file, reply with status.\r\n\r\n---\r\n\r\n## Error Handling\r\n\r\n- All functions return a dictionary with at least `success` (bool) and `message` (str).\r\n- On success, additional fields like `data` or `order_id` may be present.\r\n- Always check `success` first before using other fields.\r\n\r\nExample:\r\n```python\r\nresult = submit_order(...)\r\nif result[\"success\"]:\r\n    print(f\"Order ID: {result['order_id']}\")\r\nelse:\r\n    print(f\"Error: {result['message']}\")\r\n```\r\n\r\nIf OpenD connection fails, recheck:\r\n- OpenD is running (check port 11111 with `lsof -i :11111`)\r\n- Host/port in `config.json` matches OpenD\r\n- Account has necessary permissions\r\n\r\nIf the skill fails before quote/trade functions are even called, recheck:\r\n- Whether the current agent/tool is running in a restricted sandbox\r\n- Whether you should rerun in `host` / `elevated` mode\r\n- Whether the runtime can access the local Futu OpenD log directory under `~/.com.futunn.FutuOpenD/Log`\r\n- Run `PYTHONPATH=src python -m preflight_check` first and follow its suggestions\r\n\r\n## Configuration\r\n\r\n- **Config file**: `json/config.json`\r\n- **Required fields**:\r\n  - `futu_api.host` (default: 127.0.0.1)\r\n  - `futu_api.port` (default: 11111)\r\n  - `futu_api.security_firm` (e.g., `FUTUSECURITIES`)\r\n- **Password handling**:\r\n  - Prefer `trade_password_md5` (32-char lowercase MD5)\r\n  - Optional empty `trade_password` fallback (MD5 at runtime)\r\n  - Never commit real credentials; keep `json/config.json` private\r\n- **Account cache**: `json/account_info.json` only when `get_account_info(persist=True)`\r\n\r\n## 📜 License\r\n\r\nThis skill is licensed under **MIT-0** (MIT No Attribution).\r\n\r\n---\r\n\r\n**Copyright © 2026 jeffersonling1217-png**\r\n```\n\nFile v1.0.9:README.md\n\n# Futu Trading Bot Skills\r\n\r\n> **⚠️ Safety first**\r\n>\r\n> This skill can unlock a Futu brokerage account and place, modify, or cancel **real-money** orders via local OpenD.\r\n> - Prefer **`SIMULATE`** until you fully trust the setup.\r\n> - `REAL` orders, unlock/lock, and **`cancel_all_orders`** require explicit human approval and API `confirm=True`.\r\n> - Do not store plaintext passwords in git; prefer `trade_password_md5`.\r\n> - `get_account_info()` does **not** write disk by default (`persist=False`).\r\n\r\n这是一个为 AI Agent 打造的自然语言交易执行工具。它将富途 OpenAPI 的底层逻辑封装为语义能力，支持通过自然语言驱动账户解锁、下单及风控管理。系统支持（模拟/实盘）环境隔离，能够将“帮我买 200 股腾讯”或“清仓一半持仓”这类模糊意图，转化为符合金融规范的执行动作。\r\n\r\nA robust trade execution tool designed for AI Agents. It abstracts Futu OpenAPI logic into high-level semantic capabilities, enabling natural language control over account unlocking, order placement, and risk management. With native support for MD5 credential handling and environment isolation (Simulated/Real), it accurately translates vague intents—such as \"buy 200 shares of Tencent\" or \"close half of my positions\"—into execution actions that comply with financial standards.\r\n\r\n适用对象：配合 OpenClaw 使用，或任何能通过命令行调用工具并能编写 Python 脚本的 Agent/LLM。\r\n\r\n核心代码在 `src/`，配置与运行数据在 `json/`。\r\n\r\n## 功能\r\n- 账户查询：`get_account_info()`\r\n- 交易解锁：`unlock_trade(password=None, password_md5=None)`\r\n- 交易锁定：`lock_trade(password=None, password_md5=None)`\r\n- 预检：`run_preflight()`\r\n- 行情拉取：`get_stock_basicinfo()`、`get_market_state()`、`get_market_snapshot()`、`get_cur_kline()`、`request_history_kline()`、`get_rt_ticker()`\r\n- 行情统一启动：`start_quote_stream()`、`start_orderbook_stream()`\r\n- 下单：`submit_order(...)`\r\n- 改单/撤单：`modify_order(...)`、`cancel_order(...)`、`cancel_all_orders(...)`\r\n- 策略运行：`run_strategy(...)`\r\n- 策略辅助：状态、交易锁、交易时段判断、回调 payload 解析\r\n\r\n## 当前行为说明\r\n- `submit_order` 必须显式传入 `acc_id` 和 `trd_env`（`REAL` / `SIMULATE`）。`REAL` 还需要 `confirm=True`。\r\n- `cancel_all_orders` 在任何环境下都需要 `confirm=True`。\r\n- `get_account_info(persist=False)` 默认只返回内存结果；仅当 `persist=True` 时写入 `json/account_info.json`。\r\n- `unlock_trade` / `lock_trade` 需要 `confirm=True`，支持 MD5 密码：\r\n  - 优先使用 `password_md5` / 配置 `trade_password_md5`\r\n  - 若仅提供明文 `password`，会在运行时自动转 MD5 后调用富途接口\r\n  - **不提供** stdin 交互式输密码接口\r\n- 拉取型 quote 函数会在返回后自动关闭 quote context。\r\n- trade/account 对外函数会在返回后自动关闭各自 context。\r\n- 订阅/回调模式不会自动关闭 quote context，调用方结束时应显式 `close_quote_service()`。\r\n- `modify_order` / `cancel_order` / `cancel_all_orders` 会自行重新初始化交易 context，不依赖上一次调用留下的连接。\r\n\r\n## 安装\r\n### 方式 A：作为 ClawHub Skill 安装（推荐给 Agent 用户）\r\n不需要手动下载整个仓库，直接安装 skill 文件夹即可：\r\n```bash\r\nclawhub install futu-trading-bot\r\n```\r\n\r\n安装完成后，在该 skill 目录中创建虚拟环境并安装依赖（否则无法 `import` / 调用）：\r\n```bash\r\npython3 -m venv .venv\r\nsource .venv/bin/activate\r\npip install -r requirements.txt\r\npip install -e .\r\n```\r\n\r\n### 方式 B：从 GitHub 源码安装（推荐给开发者）\r\n如果你是要开发/改代码，直接 clone 本仓库后：\r\n```bash\r\npip install -r requirements.txt\r\n```\r\n\r\n推荐（开发环境）：\r\n```bash\r\npip install -e .\r\n```\r\n安装后可直接 `import quote_service/trade_service/account_manager/config_manager`，\r\n无需再手动设置 `PYTHONPATH` 或在脚本里写 `sys.path`。\r\n\r\n额外可直接导入：\r\n- `preflight_check`\r\n- `strategy_runtime`\r\n- `strategy`\r\n\r\n## 配置\r\n配置文件路径：`json/config.json`\r\n\r\n最小模板：\r\n```json\r\n{\r\n  \"futu_api\": {\r\n    \"host\": \"127.0.0.1\",\r\n    \"port\": 11111,\r\n    \"security_firm\": \"FUTUSECURITIES\",\r\n    \"trade_password\": \"\",\r\n    \"trade_password_md5\": \"\",\r\n    \"default_env\": \"SIMULATE\"\r\n  }\r\n}\r\n```\r\n\r\n说明：\r\n- `trade_password_md5` 优先级高于 `trade_password`\r\n- `json/config.json` 含敏感信息，已建议加入 `.gitignore`\r\n- 若 `json/config.json` 不存在，代码会优先回退到 `json/config_example.json`，也兼容旧命名 `json/config.example.json`\r\n\r\n## 示例\r\n```python\r\nfrom preflight_check import run_preflight\r\nfrom account_manager import get_account_info, unlock_trade, lock_trade\r\nfrom trade_service import submit_order\r\n\r\nprint(run_preflight())\r\nprint(get_account_info())  # 默认不落盘\r\n# print(get_account_info(persist=True))  # 仅在用户要求缓存时\r\n\r\nprint(unlock_trade(confirm=True))  # 需用户明确同意；从配置读取密码/MD5\r\n\r\nprint(submit_order(\r\n    code=\"HK.00700\",\r\n    side=\"BUY\",\r\n    qty=200,\r\n    price=150,\r\n    order_type=\"NORMAL\",\r\n    acc_id=6017237,\r\n    trd_env=\"SIMULATE\",\r\n))\r\n# REAL 示例（需用户明确批准参数后）:\r\n# submit_order(..., trd_env=\"REAL\", confirm=True)\r\n\r\nprint(lock_trade(confirm=True))\r\n```\r\n\r\n## 实时行情回调示例\r\n```python\r\nfrom quote_service import start_quote_stream, unsubscribe_all, close_quote_service\r\nfrom strategy_runtime import run_strategy\r\nfrom strategy import StrategyState, TradeGuard, extract_latest_price\r\n\r\nstate = StrategyState()\r\nguard = TradeGuard()\r\n\r\ndef on_quote(payload):\r\n    price = extract_latest_price(payload, code=\"HK.00700\")\r\n    if price is None:\r\n        return\r\n    with guard.locked():\r\n        state.current_price = price\r\n        print(\"latest price:\", price)\r\n\r\nstart_quote_stream([\"HK.00700\"], on_quote)\r\nrun_strategy(\r\n    pid_file=\"/tmp/futu_strategy.pid\",\r\n    cleanup_callbacks=[unsubscribe_all, close_quote_service],\r\n)\r\n```\r\n\r\n## 运行要求\r\n- 本机已安装并运行 Futu OpenD\r\n- OpenD 地址与 `json/config.json` 一致（默认 `127.0.0.1:11111`）\r\n- 真实交易前先确认账户已解锁且参数正确\r\n- 若在 OpenClaw/Codex 等受限环境中运行，建议先执行 `PYTHONPATH=src python -m preflight_check`\r\n- 若预检提示日志目录或 OpenD 访问受限，请改用 `host/elevated` 模式\n\nFile v1.0.9:_meta.json\n\n{\n  \"ownerId\": \"kn79d46ahs4v5syfeh8jjzqf7d81y7rr\",\n  \"slug\": \"futu-trading-bot\",\n  \"version\": \"1.0.9\",\n  \"publishedAt\": 1786009435466\n}\n\nFile v1.0.9:docs/account.md\n\n# Account Manager 文档\r\n\r\n所属项目：**Futu Trade Bot Skills**\r\n\r\n## 模块位置\r\n`src/account_manager.py`\r\n\r\n## 安全提示\r\n- `unlock_trade` / `lock_trade` 会改变真实券商账户的交易锁定状态，**必须** `confirm=True`，且仅在用户明确授权后调用。\r\n- 不要通过 agent stdin 收集交易密码；优先使用配置中的 `trade_password_md5`。\r\n- `get_account_info` 默认**不写盘**。仅当用户要求缓存账户列表时使用 `persist=True`（写入 `json/account_info.json`，含账户 ID / 环境 / 券商等元数据，请限制文件权限且勿提交仓库）。\r\n\r\n## 对外接口\r\n\r\n### `get_account_info(persist=False)`\r\n```python\r\nget_account_info(persist: bool = False) -> Dict[str, Any]\r\n```\r\n\r\n行为：\r\n- 调用富途 `get_acc_list()`。\r\n- 返回账户列表结构：`accounts`。\r\n- 仅当 `persist=True` 时覆盖写 `json/account_info.json`，并在结果中设置 `persisted=True/False`。\r\n\r\n### `unlock_trade(password=None, password_md5=None, confirm=False)`\r\n```python\r\nunlock_trade(\r\n    password: Optional[str] = None,\r\n    password_md5: Optional[str] = None,\r\n    confirm: bool = False,\r\n) -> Dict[str, Any]\r\n```\r\n\r\n- `confirm` 必须为 `True`，否则直接失败。\r\n- 密码优先级：显式 `password_md5` → 显式 `password` → 配置 `trade_password_md5` → 配置 `trade_password`。\r\n\r\n### `lock_trade(password=None, password_md5=None, confirm=False)`\r\n同样需要 `confirm=True`。内部调用富途 `unlock_trade(..., is_unlock=False)`。\r\n\r\n## 使用示例\r\n```python\r\nfrom account_manager import get_account_info, unlock_trade, lock_trade\r\n\r\nprint(get_account_info())\r\nprint(unlock_trade(confirm=True))\r\nprint(lock_trade(confirm=True))\r\n```\r\n\r\n## 注意事项\r\n- 依赖 OpenD 连接可用。\r\n- 明文密码和 MD5 都属于敏感信息。\r\n- 对外函数返回后会关闭账户相关 context。\n\nFile v1.0.9:docs/config.md\n\n# Config Manager 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/config_manager.py`\n\n## 作用\n统一加载并提供项目配置（富途连接参数、交易密码、日志参数）。\n\n## 配置文件读取规则\n1. 优先读取：`json/config.json`\n2. 回退读取：`json/config_example.json`（存在时）\n3. 兼容读取：`json/config.example.json`（旧命名存在时）\n4. 若都不存在，抛出 `FileNotFoundError`\n\n## 配置示例\n```json\n{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"\",\n    \"trade_password_md5\": \"\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}\n```\n\n## 默认值（缺省字段自动补全）\n- `host`: `127.0.0.1`\n- `port`: `11111`\n- `security_firm`: `FUTUSECURITIES`\n- `trade_password`: `\"\"`\n- `trade_password_md5`: `\"\"`\n- `default_env`: `SIMULATE`\n\n## 主要接口\n- `get_futu_config()`\n- `get_host()`\n- `get_port()`\n- `get_security_firm()`\n- `get_trade_password()`\n- `get_trade_password_md5()`\n- `get_default_env()`\n- `get_default_env_str()`\n\n## 与其他模块关系\n- `account_manager` 使用本模块读取主机、端口、券商、交易密码。\n- `trade_service` 使用本模块读取主机、端口、券商。\n\n## 安全建议\n- `json/config.json` 不应入库，需加入 `.gitignore`。\n- 使用最小权限：`chmod 600 json/config.json`。\n- 不在日志中输出真实密码或 MD5 值。\n\nFile v1.0.9:docs/development_plan.md\n\n你说得对，富途的行情接口确实很多。不过别担心，我们不需要一次性封装所有接口。根据你之前开发交易模块的经验，我们可以采用“**先核心，后扩展，按需封装**”的策略。\n\n下面我帮你梳理一个清晰的开发路线图，你可以根据实际需要决定优先实现哪些部分。\n\n### 📈 行情模块封装路线图\n\n#### **第一阶段：核心基础（必须实现）**\n这是所有行情功能的基石，也是你之前交易模块中已经用到的部分。\n1.  **连接管理**：封装 `OpenQuoteContext` 的创建与关闭，沿用交易模块的延迟初始化模式。\n2.  **基础数据获取**：\n    *   **`get_stock_basicinfo`**：获取股票代码、每手股数等基本信息。你的交易模块中已经需要这个接口来校验下单数量。\n    *   **`get_market_state`**：获取市场状态（如是否在交易中），这对判断能否下单很有用。\n\n#### **第二阶段：实时行情订阅（核心功能）**\n这是为了构建实时监控或自动交易策略的基础。\n1.  **订阅管理**：封装 `subscribe`、`unsubscribe`、`unsubscribe_all`、`query_subscription` 四个接口，实现订阅状态的统一管理。\n2.  **推送回调**：\n    *   **报价推送 (`StockQuoteHandlerBase`)**：实时获取价格变动，最常用。\n    *   **摆盘推送 (`OrderBookHandlerBase`)**：如果需要监控深度行情。\n    你可以先实现报价推送，因为这是最基本的需求。\n\n#### **第三阶段：主动数据拉取（常用功能）**\n当需要一次性获取当前数据快照时使用。\n1.  **市场快照 (`get_market_snapshot`)**：最常用的“看一眼”接口，能一次性获取最新价、涨跌幅、成交量等核心数据。\n2.  **K线数据 (`get_cur_kline` 或 `request_history_kline`)**：用于技术分析或展示图表。\n3.  **实时逐笔 (`get_rt_ticker`)**：如果需要监控每一笔成交。\n\n#### **第四阶段：进阶数据（按需扩展）**\n这些接口用于特定的策略或分析，可以根据你的实际需求逐步添加。\n*   **全市场筛选 (`get_stock_filter`)**：用于选股策略。\n*   **板块数据 (`get_plate_stock`, `get_plate_list`)**：分析板块轮动。\n*   **资金流向 (`get_capital_flow`)**：观察主力资金动向。\n*   **自选股管理 (`get_user_security` 等)**：如果你需要管理用户的股票池。\n\n### 💡 给你的具体建议\n\n1.  **先从交易模块中已有的依赖开始**：你的 `trade_service` 已经用到了 `get_market_snapshot` 来获取每手股数，可以优先把它完整封装起来。\n2.  **遵循“先测试，后封装”原则**：就像你之前做的，先用一个简单的测试脚本调通一个接口（比如 `get_market_snapshot`），理解它的输入输出，然后再进行封装。\n3.  **统一设计风格**：延续交易模块的设计模式：一个内部服务类 (`_HKQuoteService`) + 对外暴露的简洁函数。返回格式也保持一致 `{\"success\": bool, \"data\": ..., \"message\": str}`。\n4.  **管理好订阅状态**：在服务类内部维护一个订阅列表，避免重复订阅，也便于取消订阅。\n\n你可以先从第一阶段和第三阶段开始，搭建起行情模块的骨架。当有具体的策略需求时，再有针对性地封装第二阶段或其他进阶接口。这样既不会一开始就被庞大的接口列表吓倒，也能快速用起来。\n\nFile v1.0.9:docs/quote.md\n\n# Quote Service 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/quote_service.py`\n\n## 概述\n行情模块负责：\n- 基础行情拉取\n- K 线与逐笔拉取\n- 行情订阅与回调\n- 统一启动实时报价/摆盘监听\n\n## 拉取型函数\n- `get_stock_basicinfo(...)`\n- `get_market_state(...)`\n- `get_market_snapshot(...)`\n- `get_cur_kline(...)`\n- `request_history_kline(...)`\n- `get_rt_ticker(...)`\n\n说明：\n- 拉取型函数返回后会显式关闭 quote context。\n- `get_cur_kline(...)` 和 `get_rt_ticker(...)` 在遇到“请先订阅”时会自动补订阅后重试。\n\n## 订阅/回调型函数\n- `set_quote_callback(callback)`\n- `set_orderbook_callback(callback)`\n- `subscribe(...)`\n- `unsubscribe(...)`\n- `unsubscribe_all()`\n- `query_subscription()`\n\n说明：\n- 这些函数不会自动关闭 quote context。\n- 用于长连接 / 回调推送场景。\n- 调用方结束时应显式 `close_quote_service()`。\n\n## 统一启动函数\n\n### `start_quote_stream(...)`\n完成两步：\n1. 注册 `QUOTE` 回调\n2. 发起 `QUOTE` 订阅\n\n### `start_orderbook_stream(...)`\n完成两步：\n1. 注册 `ORDER_BOOK` 回调\n2. 发起 `ORDER_BOOK` 订阅\n\n这两个函数适合策略脚本，避免把“设置回调 + 订阅”拆开写。\n\n## 使用示例\n```python\nfrom quote_service import start_quote_stream, unsubscribe_all, close_quote_service\n\ndef on_quote(payload):\n    print(payload)\n\nstart_quote_stream([\"HK.00700\"], on_quote)\n\n# done\nunsubscribe_all()\nclose_quote_service()\n```\n\nFile v1.0.9:docs/strategy.md\n\n# Strategy Helpers 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n- `src/strategy.py`\n- `src/strategy_runtime.py`\n\n## 目标\n为策略脚本提供轻量辅助，而不是复杂框架。\n\n## `strategy.py`\n提供三类能力：\n\n1. 运行状态\n- `StrategyState`\n\n2. 并发保护\n- `TradeGuard`\n\n3. 运行辅助判断\n- `in_trading_window(...)`\n- `trading_window_status(...)`\n- `cooldown_elapsed(...)`\n- `holding_timeout_exceeded(...)`\n\n4. 回调 payload 解析\n- `extract_callback_rows(payload)`\n- `filter_rows_by_code(rows, code)`\n- `extract_latest_price(payload, code=None, field=\"last_price\")`\n\n## `strategy_runtime.py`\n提供：\n- `run_strategy(...)`\n\n职责只包括：\n- PID 文件管理\n- 防重复启动\n- `SIGINT` / `SIGTERM` 清理\n- 保持进程运行\n\n## 推荐使用方式\n1. 先用 `start_quote_stream(...)` 或 `start_orderbook_stream(...)` 建立订阅\n2. 在回调中用 `extract_latest_price(...)` 等辅助解析行情\n3. 用 `StrategyState` 和 `TradeGuard` 管理策略状态\n4. 最后调用 `run_strategy(...)` 保持进程运行并处理退出清理\n\nFile v1.0.9:docs/trade.md\n\n# Trade Service 文档\r\n\r\n所属项目：**Futu Trade Bot Skills**\r\n\r\n## 模块位置\r\n`src/trade_service.py`\r\n\r\n## 概述\r\n交易模块负责下单、改单、撤单与全部撤单，内部包含参数校验和富途 API 调用。\r\n\r\n## 安全门闩\r\n- 推荐默认：`trd_env=\"SIMULATE\"`。\r\n- `submit_order` / `modify_order` / `cancel_order`：当 `trd_env=\"REAL\"` 时必须 `confirm=True`。\r\n- `cancel_all_orders`：**任何环境**都必须 `confirm=True`（高 blast radius）。\r\n- 缺少确认时函数返回 `success=False` 与说明信息，不会调用富途下单接口。\r\n\r\n## 设计原则\r\n- 交易环境不做内部管理，调用方必须显式传入。\r\n- 不提供账户环境切换接口（无 `switch_account_env`）。\r\n- 不做幂等去重校验。\r\n\r\n## 对外接口\r\n\r\n### `submit_order(...)`\r\n```python\r\nsubmit_order(\r\n    code: str,\r\n    side: str,\r\n    qty: int,\r\n    acc_id: int,\r\n    trd_env: str,\r\n    price: Optional[float] = None,\r\n    order_type: str = \"NORMAL\",\r\n    aux_price: Optional[float] = None,\r\n    remark: Optional[str] = None,\r\n    time_in_force: str = \"DAY\",\r\n    confirm: bool = False,\r\n) -> Dict[str, Any]\r\n```\r\n\r\n### `modify_order(...)` / `cancel_order(...)`\r\n`REAL` 需要 `confirm=True`。\r\n\r\n### `cancel_all_orders(...)`\r\n```python\r\ncancel_all_orders(trd_env: str, acc_id: int = 0, trdmarket: Optional[str] = None, confirm: bool = False)\r\n```\r\n必须 `confirm=True`。\r\n\r\n## 使用示例\r\n```python\r\nfrom trade_service import submit_order, cancel_all_orders\r\n\r\nresult = submit_order(\r\n    code=\"HK.00700\",\r\n    side=\"BUY\",\r\n    qty=200,\r\n    acc_id=6017237,\r\n    trd_env=\"SIMULATE\",\r\n    price=150,\r\n    order_type=\"NORMAL\",\r\n)\r\nprint(result)\r\n\r\n# cancel_all_orders(trd_env=\"SIMULATE\", acc_id=6017237, confirm=True)\r\n```\r\n\r\n## 注意事项\r\n- `REAL` 环境会尝试真实交易，请先确认交易权限状态。\r\n- 真实交易密码解锁/锁定由 `account_manager` 处理，不在本模块内自动完成。\n\nFile v1.0.9:skill-card.md\n\n## Description:\n\nUse Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[jeffersonling1217-png](https://clawhub.ai/user/jeffersonling1217-png)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers, traders, and agent builders use this skill to connect an agent to Futu OpenD for HK market quotes, account lookup, simulated trading, confirmed live order workflows, and user-approved trading strategy scripts.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can control real-money trades through a local Futu OpenD session.\n\nMitigation: Keep REAL trading disabled unless the user confirms the exact order parameters; prefer SIMULATE and require explicit confirmation for live orders, trade unlocks, order changes, and cancellations.\n\nRisk: Reusable trading credentials may be stored in json/config.json.\n\nMitigation: Treat json/config.json as a secret, prefer trade_password_md5, use restrictive file permissions, and avoid committing real credentials.\n\nRisk: The skill requires local network access to Futu OpenD and may need broader host access in restricted sandboxes.\n\nMitigation: Avoid host or elevated mode unless necessary; explain the access need to the user before rerunning with broader permissions.\n\nRisk: User-approved background strategies can place repeated orders if configured incorrectly.\n\nMitigation: Review generated strategy scripts before starting them, use fixed parameters, prefer simulated accounts, and record PID and log paths for monitoring and shutdown.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/jeffersonling1217-png/skills/futu-trading-bot)\n- [Publisher profile](https://clawhub.ai/user/jeffersonling1217-png)\n- [README](README.md)\n- [Account Manager docs](docs/account.md)\n- [Config Manager docs](docs/config.md)\n- [Quote Service docs](docs/quote.md)\n- [Strategy Helpers docs](docs/strategy.md)\n- [Trade Service docs](docs/trade.md)\n- [Configuration example](json/config_example.json)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown guidance with Python code examples, shell commands, and JSON configuration references]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May produce or run user-approved strategy scripts and local configuration files when the user explicitly requests them.]\n\n## Skill Version(s):\n\n1.0.9 (source: release evidence, _meta.json, pyproject.toml)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.0.9:json/config_example.json\n\n{\r\n  \"futu_api\": {\r\n    \"host\": \"127.0.0.1\",\r\n    \"port\": 11111,\r\n    \"security_firm\": \"FUTUSECURITIES\",\r\n    \"trade_password\": \"\",\r\n    \"trade_password_md5\": \"\",\r\n    \"default_env\": \"SIMULATE\"\r\n  },\r\n  \"logging\": {\r\n    \"level\": \"INFO\",\r\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\r\n  }\r\n}\n\nFile v1.0.9:pyproject.toml\n\n[build-system]\r\nrequires = [\"setuptools>=68\", \"wheel\"]\r\nbuild-backend = \"setuptools.build_meta\"\r\n\r\n[project]\r\nname = \"futu-trade-bot-skills\"\r\nversion = \"1.0.9\"\r\ndescription = \"Futu Trade Bot Skills modules for account, trade, and quote services.\"\r\nreadme = \"README.md\"\r\nrequires-python = \">=3.10\"\r\ndependencies = [\r\n  \"futu-api==9.6.5608\",\r\n  \"pydantic==2.12.5\",\r\n]\r\n\r\n[tool.setuptools]\r\npy-modules = [\"account_manager\", \"config_manager\", \"trade_service\", \"quote_service\", \"preflight_check\", \"strategy_runtime\", \"strategy\"]\r\n\r\n[tool.setuptools.package-dir]\r\n\"\" = \"src\"\n\nArchive v1.0.8: 20 files, 45014 bytes\n\nFiles: _meta.json (135b), docs/account.md (1889b), docs/config.md (1531b), docs/development_plan.md (3458b), docs/quote.md (1516b), docs/strategy.md (1091b), docs/trade.md (1967b), json/config_example.json (306b), pyproject.toml (572b), README.md (6563b), requirements.txt (40b), skill-card.md (2565b), SKILL.md (17937b), src/account_manager.py (15211b), src/config_manager.py (7404b), src/preflight_check.py (8558b), src/quote_service.py (20690b), src/strategy_runtime.py (2934b), src/strategy.py (3776b), src/trade_service.py (36331b)\n\nFile v1.0.8:SKILL.md\n\n---\r\nname: futu-trading-bot\r\ndescription: Use Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.\r\nlicense: MIT-0\r\nmetadata:\r\n  openclaw:\r\n    emoji: \"📈\"\r\n    requires:\r\n      bins: [\"python3\", \"pip\"]\r\n    permissions:\r\n      - local-network  # Futu OpenD (default 127.0.0.1:11111)\r\n      - filesystem-read  # json/config.json and skill modules\r\n      - filesystem-write  # optional account_info.json / strategy logs / PID files when user opts in\r\n      - process  # optional background strategy only after explicit user confirmation\r\n---\r\n\r\n# Futu Trade Bot Skills 📈\r\n\r\n## ⚠️ Security & Safety (READ FIRST)\r\n\r\nThis skill can control a **live brokerage account** via Futu OpenD. Misuse can cause **irreversible financial loss**.\r\n\r\n**Hard rules for the agent:**\r\n1. **Default to SIMULATE.** Never use `trd_env=\"REAL\"` unless the user explicitly requests live trading and confirms the exact order parameters.\r\n2. **State-changing actions require explicit user approval**, then pass `confirm=True`:\r\n   - `unlock_trade` / `lock_trade`\r\n   - `submit_order` when `trd_env=\"REAL\"`\r\n   - `modify_order` / `cancel_order` when `trd_env=\"REAL\"`\r\n   - `cancel_all_orders` in **any** environment\r\n3. **Read-only actions** (quotes, `get_account_info(persist=False)`) may run without `confirm`.\r\n4. **Do not** collect trading passwords via interactive stdin. Use config (`trade_password_md5` preferred) or an explicit parameter the user already provided out-of-band.\r\n5. **Do not** write `json/account_info.json` unless the user asks to cache accounts (`persist=True`).\r\n6. **Background strategies** (write script / start process / stop process) only after the user clearly asks and confirms symbol, qty, `SIMULATE`/`REAL`, and log/PID paths.\r\n7. If a restricted sandbox blocks OpenD or `~/.com.futunn.FutuOpenD/Log`, **tell the user** before suggesting `host` / `elevated` mode — never silently escalate.\r\n\r\n**中文硬规则：** 默认模拟盘；真金白银/解锁/全部撤单必须先复述参数并得到用户明确同意，再传 `confirm=True`；禁止 stdin 要密码；默认不把账户信息写盘。\r\n\r\n## 🎯 Overview / 概述\r\n\r\n**English Version:**\r\nA trading bot skill based on Futu OpenAPI that enables natural language trading. This skill encapsulates Futu's market quote and order execution APIs, allowing agents to perform real-time trading operations through simple commands or scripts. Perfect for implementing natural language trading strategies and automated workflows.\r\n\r\n**Important**: Always use the encapsulated functions provided in this skill (e.g., `submit_order`, `get_market_snapshot`). **Never call Futu SDK functions directly** (`ctx.place_order`, `ctx.get_market_snapshot`), as this will bypass connection management, parameter validation, and error handling, leading to unpredictable failures and resource leaks.\r\n\r\n**中文版本:**\r\n基于富途牛牛API接口的交易机器人技能，帮助用户用自然语言进行交易。本技能已将富途牛牛的行情报价、下单交易等功能做了完整封装，可供智能助手随时调用。建议通过命令行或脚本来实现自然语言的策略生成和交易执行。\r\n\r\n**重要提示**：请始终使用本技能提供的封装函数（如 `submit_order`、`get_market_snapshot`）。**切勿直接调用富途SDK的原始函数**（例如 `ctx.place_order`），否则会绕过连接管理、参数校验和错误处理，导致不可预料的失败和资源泄漏。\r\n\r\n---\r\n\r\n## When to Use This Skill / 使用场景\r\n\r\n### Read-only (no confirm required)\r\n- **行情查询**：“腾讯现在多少钱？”、“查港股报价”、“看 K 线 / 逐笔”\r\n- **账户列表查询**：“看看我有哪些账户”（`get_account_info()`，默认不落盘）\r\n\r\n### State-changing (require explicit user intent + confirmation)\r\n- **解锁 / 锁定交易**：“解锁交易”、“锁定账户” → 复述风险后 `unlock_trade(confirm=True)` / `lock_trade(confirm=True)`\r\n- **下单 / 改单 / 撤单**：“帮我买 100 股腾讯限价 350” → 复述 code/side/qty/price/`SIMULATE|REAL`，用户确认后再调用；`REAL` 必须 `confirm=True`\r\n- **全部撤单**：“撤销全部订单” → 高风险，**任何环境**都要 `cancel_all_orders(..., confirm=True)`\r\n- **策略启停**：仅当用户明确说启动/停止策略；先确认参数与环境，默认 `SIMULATE`\r\n\r\n**Do not** map vague chat like “看看市场怎么样” to unlock/order/cancel.\r\n\r\n**Note to agent**: Always use this skill's wrappers (`get_account_info`, `get_market_snapshot`, `submit_order`, …). **Never call Futu SDK functions directly**. Never skip `confirm` gates for privileged actions.\r\n\r\n## Quick Start / 快速开始\r\n\r\n**Prerequisites / 前提条件:**\r\n- Ensure Futu OpenD is running and HK quote entitlement is available.\r\n- 确保富途OpenD正在运行且拥有港股行情权限。\r\n- Futu OpenD must be reachable (default `127.0.0.1:11111`). The SDK may also need write access to `~/.com.futunn.FutuOpenD/Log`.\r\n- If a restricted sandbox blocks OpenD/log access, **ask the user** whether to rerun in `host` / `elevated` mode. Do not silently escalate privileges.\r\n- 若沙箱导致 OpenD/日志目录不可用，先告知用户再征得同意后使用 `host` / `elevated`，不要静默提权。\r\n\r\n**Setup Steps / 安装步骤:**\r\n1. Install this skill via ClawHub (if not installed yet):\r\n   ```bash\r\n   clawhub install futu-trading-bot\r\n   ```\r\n\r\n2. Enter the skill folder (default OpenClaw workspace path):\r\n   ```bash\r\n   cd ~/.openclaw/workspace/skills/futu-trading-bot\r\n   ```\r\n   If you installed to a different location, `cd` into that folder instead.\r\n\r\n3. Create virtual environment (recommended):\r\n   ```bash\r\n   python3 -m venv .venv\r\n   source .venv/bin/activate\r\n   ```\r\n\r\n4. Install package:\r\n   ```bash\r\n   pip install -e .\r\n   ```\r\n\r\n5. Configure credentials:\r\n   ```bash\r\n   cp json/config_example.json json/config.json\r\n   # Edit json/config.json with your Futu credentials\r\n   # 编辑json/config.json填写你的富途账户信息\r\n   ```\r\n\r\n## 依赖项\r\n\r\n本技能通过 `pip install -e .` 安装（版本见 `requirements.txt` / `pyproject.toml`）：\r\n- `futu-api==9.6.5608`\r\n- `pydantic>=2.7.0,<3`\r\n\r\n## Module Map\r\n\r\n- **Account**: `account_manager`\r\n  - `get_account_info(persist=False)` — default no disk write\r\n  - `unlock_trade(..., confirm=True)` — privileged\r\n  - `lock_trade(..., confirm=True)` — privileged\r\n- **Quote**: `quote_service` (read-oriented)\r\n  - Stage 1: `get_stock_basicinfo`, `get_market_state`\r\n  - Stage 2: `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, callbacks\r\n  - Stage 3: `get_market_snapshot`, `get_cur_kline`, `request_history_kline`, `get_rt_ticker`\r\n  - Stage 4: `start_quote_stream`, `start_orderbook_stream`\r\n- **Trade**: `trade_service` (privileged)\r\n  - `submit_order(..., confirm=)` — REAL requires confirm\r\n  - `modify_order` / `cancel_order` — REAL requires confirm\r\n  - `cancel_all_orders(..., confirm=True)` — always requires confirm\r\n- **Strategy Runtime**: `strategy_runtime` / `strategy` helpers\r\n\r\n## Standard Workflow\r\n\r\n1. Run `preflight_check` first.\r\n2. `get_account_info()` (no persist) and select `acc_id`.\r\n3. Quote/snapshot for target symbol (e.g. `HK.00700`).\r\n4. For live trading only after user confirmation: `unlock_trade(confirm=True)`.\r\n5. Orders with explicit `acc_id` + `trd_env` (prefer `SIMULATE`; REAL needs `confirm=True`).\r\n6. After live ops, `lock_trade(confirm=True)` if the user wants trading locked again.\r\n\r\n## Connection Lifecycle\r\n\r\n- Pull-style quote functions such as `get_market_snapshot`, `get_stock_basicinfo`, `get_market_state`, `get_cur_kline`, `request_history_kline`, and `get_rt_ticker` now close their quote context automatically after returning.\r\n- Trade functions such as `submit_order`, `modify_order`, and `cancel_all_orders` now close their trade/quote contexts automatically after returning.\r\n- Account functions such as `get_account_info`, `unlock_trade`, and `lock_trade` now close their contexts automatically after returning.\r\n- Subscription/callback flows keep the quote context open on purpose. For `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, `set_quote_callback`, and `set_orderbook_callback`, call `close_quote_service()` explicitly when you are done with the session.\r\n\r\n## Canonical Imports\r\n\r\n```python\r\n# Always use these import paths – do not import from futu directly\r\nfrom preflight_check import run_preflight\r\nfrom strategy import (\r\n    StrategyState, TradeGuard, in_trading_window,\r\n    trading_window_status, cooldown_elapsed, holding_timeout_exceeded\r\n)\r\nfrom strategy_runtime import run_strategy\r\nfrom account_manager import get_account_info, unlock_trade, lock_trade\r\nfrom quote_service import (\r\n    get_stock_basicinfo, get_market_state, get_market_snapshot,\r\n    get_cur_kline, request_history_kline, get_rt_ticker,\r\n    subscribe, unsubscribe, unsubscribe_all, query_subscription,\r\n    set_quote_callback, set_orderbook_callback,\r\n    start_quote_stream, start_orderbook_stream\r\n)\r\nfrom trade_service import submit_order, modify_order, cancel_order, cancel_all_orders\r\n```\r\n\r\n## Account Usage\r\n\r\n### Preflight\r\n```python\r\npreflight = run_preflight()\r\nif not preflight[\"success\"]:\r\n    print(preflight)\r\n    raise SystemExit(\"Preflight failed\")\r\n```\r\n\r\n```python\r\n# Get list of accounts (in-memory only by default)\r\ninfo = get_account_info()  # persist=False\r\nif info['success']:\r\n    accounts = info['accounts']\r\n    print(accounts)\r\n\r\n# Optional: cache accounts locally only if user asked\r\n# info = get_account_info(persist=True)\r\n\r\n# Unlock trade ONLY after explicit user approval\r\nunlock_trade(confirm=True)  # loads trade_password_md5 / trade_password from config\r\n\r\n# Lock trade after user approval\r\nlock_trade(confirm=True)\r\n```\r\n\r\n## Quote Usage\r\n\r\n### Basic Info / Market State\r\n```python\r\nget_stock_basicinfo(market=\"HK\", sec_type=\"STOCK\", code_list=[\"HK.00700\"])\r\nget_market_state([\"HK.00700\"])\r\n```\r\n\r\n### Snapshot (no subscription needed)\r\n```python\r\nsnap = get_market_snapshot([\"HK.00700\"])\r\nif snap['success']:\r\n    price = snap['data'][0]['last_price']\r\n```\r\n\r\n### K-Line\r\n```python\r\n# Current K-line (requires subscription, will auto-subscribe if needed)\r\nkline = get_cur_kline(code=\"HK.00700\", num=5, ktype=\"K_DAY\", autype=\"QFQ\")\r\n\r\n# Historical K-line\r\nhist = request_history_kline(\r\n    code=\"HK.00700\",\r\n    start=\"2026-02-20\",\r\n    end=\"2026-03-06\",\r\n    ktype=\"K_DAY\"\r\n)\r\n```\r\n\r\n### Ticker\r\n```python\r\ntickers = get_rt_ticker(code=\"HK.00700\", num=10)\r\n```\r\n\r\n### Subscription & Callbacks\r\n```python\r\ndef on_quote(payload):\r\n    print(payload)\r\n\r\nset_quote_callback(on_quote)\r\nsubscribe([\"HK.00700\"], [\"QUOTE\"], is_first_push=True, subscribe_push=True)\r\nquery_subscription()\r\nunsubscribe([\"HK.00700\"], [\"QUOTE\"])\r\nunsubscribe_all()\r\nclose_quote_service()\r\n```\r\n\r\n### Unified Stream Startup\r\n```python\r\ndef on_quote(payload):\r\n    print(payload)\r\n\r\nstart_quote_stream([\"HK.00700\"], on_quote)\r\n```\r\n\r\n### Strategy Helpers\r\n```python\r\nstate = StrategyState()\r\nguard = TradeGuard()\r\n\r\nif in_trading_window(start_time=\"09:30\", end_time=\"16:00\"):\r\n    with guard.locked():\r\n        pass\r\n```\r\n\r\n## Trade Usage\r\n\r\n```python\r\n# Preferred: SIMULATE (no confirm required by the gate)\r\nresult = submit_order(\r\n    code=\"HK.00700\",\r\n    side=\"BUY\",\r\n    qty=200,\r\n    acc_id=6017237,\r\n    trd_env=\"SIMULATE\",\r\n    price=150,\r\n    order_type=\"NORMAL\",\r\n)\r\n\r\n# REAL only after user explicitly approves the exact parameters\r\n# result = submit_order(..., trd_env=\"REAL\", confirm=True)\r\n\r\nmodify_order(\r\n    op=\"NORMAL\",\r\n    order_id=\"123456789\",\r\n    trd_env=\"SIMULATE\",\r\n    price=151,\r\n    qty=200,\r\n    acc_id=6017237,\r\n)\r\n\r\ncancel_order(order_id=\"123456789\", trd_env=\"SIMULATE\", acc_id=6017237)\r\n\r\n# Bulk cancel ALWAYS requires confirm=True\r\ncancel_all_orders(trd_env=\"SIMULATE\", acc_id=6017237, confirm=True)\r\n```\r\n\r\n## Running a Background Trading Strategy (Optional, User-Confirmed Only)\r\n\r\nThis skill does **not** auto-start long-running processes. Only if the user **explicitly** asks to start/stop a strategy:\r\n\r\n1. Run preflight.\r\n2. Restate parameters: symbol, account, qty, buy/sell rules, **SIMULATE (default) or REAL**, log path.\r\n3. Wait for user confirmation.\r\n4. Write a **fixed-parameter** strategy script from the template below (no arbitrary remote code).\r\n5. Start it with the platform process tools the user already authorized; record PID + log path.\r\n6. Stop only when the user asks; then terminate that PID and clean the PID file.\r\n\r\nDo **not** launch background strategies for vague requests. Do **not** use elevated/host mode without telling the user why.\r\n\r\n### Natural Language Triggers\r\n\r\n| User Request | Agent Action |\r\n|--------------|--------------|\r\n| “Start a strategy…” (explicit) | Confirm params → write template script → start after approval → return PID/log |\r\n| “How is my strategy doing?” | Read the agreed log file / check PID → summarize |\r\n| “Stop my strategy” | Confirm → stop the recorded PID → clean up |\r\n\r\n### 4.3 Script Template (for Agent Reference)\r\n\r\nWhen generating a strategy script, use the following template. It handles signals, logging, and state persistence correctly.\r\n\r\n```python\r\n#!/usr/bin/env python3\r\nimport sys\r\nimport time\r\nimport json\r\nimport os\r\nimport signal\r\nimport logging\r\nfrom pathlib import Path\r\n\r\n# If you installed the skill with `pip install -e .`, you can import modules directly.\r\n# Only use sys.path/PYTHONPATH hacks when you didn't install the package.\r\n\r\nfrom trade_service import submit_order\r\nfrom quote_service import get_market_snapshot\r\n\r\n# ===== Strategy parameters – fill by agent =====\r\n# Replace these placeholders with your own strategy settings.\r\nSYMBOL = \"HK.00700\"\r\nACC_ID = 0                 # fill from get_account_info()\r\nTRD_ENV = \"SIMULATE\"       # default to SIMULATE; use REAL only with explicit confirmation\r\nQTY = 0                    # position sizing / order quantity\r\nLOG_FILE = Path(\"strategy.log\")\r\nPID_FILE = Path(\"strategy.pid\")\r\n# ===============================================\r\n\r\nlogging.basicConfig(\r\n    filename=LOG_FILE,\r\n    level=logging.INFO,\r\n    format='%(asctime)s - %(levelname)s - %(message)s'\r\n)\r\n\r\n# Handle termination signals\r\ndef handle_exit(signum, frame):\r\n    logging.info(\"Received signal, stopping strategy\")\r\n    sys.exit(0)\r\n\r\nsignal.signal(signal.SIGTERM, handle_exit)\r\nsignal.signal(signal.SIGINT, handle_exit)\r\n\r\n# Write PID file\r\nwith open(PID_FILE, \"w\") as f:\r\n    f.write(str(os.getpid()))\r\n\r\nlogging.info(f\"Strategy started: {SYMBOL}\")\r\n\r\ntry:\r\n    while True:\r\n        snap = get_market_snapshot([SYMBOL])\r\n        if not snap[\"success\"]:\r\n            logging.error(f\"Quote failed: {snap['message']}\")\r\n            time.sleep(60)\r\n            continue\r\n        price = snap[\"data\"][0][\"last_price\"]\r\n        logging.info(f\"Current price: {price}\")\r\n\r\n        # --- Insert your strategy logic here ---\r\n        # Decide whether to trade based on your own signals/logic, then call submit_order(...).\r\n\r\n        time.sleep(60)   # check every minute\r\nexcept Exception as e:\r\n    logging.exception(\"Strategy crashed\")\r\nfinally:\r\n    if PID_FILE.exists():\r\n        PID_FILE.unlink()\r\n```\r\n\r\n### 4.4 Agent Execution Steps\r\n\r\n**User**: “Start a range strategy for Tencent, buy below 540, sell above 550.”\r\n\r\n**Agent**:\r\n1. Restate strategy params; default `TRD_ENV=SIMULATE`. Ask for confirmation.\r\n2. After approval, `get_account_info()` for `acc_id`.\r\n3. Write the template script with fixed parameters (e.g. `range_00700.py`).\r\n4. Start only the approved script; capture PID and log path.\r\n5. Reply with PID/log and remind the user how to stop it.\r\n\r\n### 4.5 Check Status\r\n\r\n**User**: “How is my strategy doing?”\r\n\r\n**Agent**:\r\n- Read last lines of log: `tail -n 20 strategy_00700.log`.\r\n- Check if process still running: `ps -p 12345`.\r\n- Summarize: “Strategy is running, last price was 542.5 at 10:30.”\r\n\r\n### 4.6 Stop Strategy\r\n\r\n**User**: “Stop my strategy.”\r\n\r\n**Agent**:\r\n- Confirm the user wants to stop the recorded PID.\r\n- Terminate that process, clean the PID file, reply with status.\r\n\r\n---\r\n\r\n## Error Handling\r\n\r\n- All functions return a dictionary with at least `success` (bool) and `message` (str).\r\n- On success, additional fields like `data` or `order_id` may be present.\r\n- Always check `success` first before using other fields.\r\n\r\nExample:\r\n```python\r\nresult = submit_order(...)\r\nif result[\"success\"]:\r\n    print(f\"Order ID: {result['order_id']}\")\r\nelse:\r\n    print(f\"Error: {result['message']}\")\r\n```\r\n\r\nIf OpenD connection fails, recheck:\r\n- OpenD is running (check port 11111 with `lsof -i :11111`)\r\n- Host/port in `config.json` matches OpenD\r\n- Account has necessary permissions\r\n\r\nIf the skill fails before quote/trade functions are even called, recheck:\r\n- Whether the current agent/tool is running in a restricted sandbox\r\n- Whether you should rerun in `host` / `elevated` mode\r\n- Whether the runtime can access the local Futu OpenD log directory under `~/.com.futunn.FutuOpenD/Log`\r\n- Run `PYTHONPATH=src python -m preflight_check` first and follow its suggestions\r\n\r\n## Configuration\r\n\r\n- **Config file**: `json/config.json`\r\n- **Required fields**:\r\n  - `futu_api.host` (default: 127.0.0.1)\r\n  - `futu_api.port` (default: 11111)\r\n  - `futu_api.security_firm` (e.g., `FUTUSECURITIES`)\r\n- **Password handling**:\r\n  - Prefer `trade_password_md5` (32-char lowercase MD5)\r\n  - Optional empty `trade_password` fallback (MD5 at runtime)\r\n  - Never commit real credentials; keep `json/config.json` private\r\n- **Account cache**: `json/account_info.json` only when `get_account_info(persist=True)`\r\n\r\n## 📜 License\r\n\r\nThis skill is licensed under **MIT-0** (MIT No Attribution).\r\n\r\n---\r\n\r\n**Copyright © 2026 jeffersonling1217-png**\r\n```\n\nFile v1.0.8:README.md\n\n# Futu Trading Bot Skills\r\n\r\n> **⚠️ Safety first**\r\n>\r\n> This skill can unlock a Futu brokerage account and place, modify, or cancel **real-money** orders via local OpenD.\r\n> - Prefer **`SIMULATE`** until you fully trust the setup.\r\n> - `REAL` orders, unlock/lock, and **`cancel_all_orders`** require explicit human approval and API `confirm=True`.\r\n> - Do not store plaintext passwords in git; prefer `trade_password_md5`.\r\n> - `get_account_info()` does **not** write disk by default (`persist=False`).\r\n\r\n这是一个为 AI Agent 打造的自然语言交易执行工具。它将富途 OpenAPI 的底层逻辑封装为语义能力，支持通过自然语言驱动账户解锁、下单及风控管理。系统支持（模拟/实盘）环境隔离，能够将“帮我买 200 股腾讯”或“清仓一半持仓”这类模糊意图，转化为符合金融规范的执行动作。\r\n\r\nA robust trade execution tool designed for AI Agents. It abstracts Futu OpenAPI logic into high-level semantic capabilities, enabling natural language control over account unlocking, order placement, and risk management. With native support for MD5 credential handling and environment isolation (Simulated/Real), it accurately translates vague intents—such as \"buy 200 shares of Tencent\" or \"close half of my positions\"—into execution actions that comply with financial standards.\r\n\r\n适用对象：配合 OpenClaw 使用，或任何能通过命令行调用工具并能编写 Python 脚本的 Agent/LLM。\r\n\r\n核心代码在 `src/`，配置与运行数据在 `json/`。\r\n\r\n## 功能\r\n- 账户查询：`get_account_info()`\r\n- 交易解锁：`unlock_trade(password=None, password_md5=None)`\r\n- 交易锁定：`lock_trade(password=None, password_md5=None)`\r\n- 预检：`run_preflight()`\r\n- 行情拉取：`get_stock_basicinfo()`、`get_market_state()`、`get_market_snapshot()`、`get_cur_kline()`、`request_history_kline()`、`get_rt_ticker()`\r\n- 行情统一启动：`start_quote_stream()`、`start_orderbook_stream()`\r\n- 下单：`submit_order(...)`\r\n- 改单/撤单：`modify_order(...)`、`cancel_order(...)`、`cancel_all_orders(...)`\r\n- 策略运行：`run_strategy(...)`\r\n- 策略辅助：状态、交易锁、交易时段判断、回调 payload 解析\r\n\r\n## 当前行为说明\r\n- `submit_order` 必须显式传入 `acc_id` 和 `trd_env`（`REAL` / `SIMULATE`）。`REAL` 还需要 `confirm=True`。\r\n- `cancel_all_orders` 在任何环境下都需要 `confirm=True`。\r\n- `get_account_info(persist=False)` 默认只返回内存结果；仅当 `persist=True` 时写入 `json/account_info.json`。\r\n- `unlock_trade` / `lock_trade` 需要 `confirm=True`，支持 MD5 密码：\r\n  - 优先使用 `password_md5` / 配置 `trade_password_md5`\r\n  - 若仅提供明文 `password`，会在运行时自动转 MD5 后调用富途接口\r\n  - **不提供** stdin 交互式输密码接口\r\n- 拉取型 quote 函数会在返回后自动关闭 quote context。\r\n- trade/account 对外函数会在返回后自动关闭各自 context。\r\n- 订阅/回调模式不会自动关闭 quote context，调用方结束时应显式 `close_quote_service()`。\r\n- `modify_order` / `cancel_order` / `cancel_all_orders` 会自行重新初始化交易 context，不依赖上一次调用留下的连接。\r\n\r\n## 安装\r\n### 方式 A：作为 ClawHub Skill 安装（推荐给 Agent 用户）\r\n不需要手动下载整个仓库，直接安装 skill 文件夹即可：\r\n```bash\r\nclawhub install futu-trading-bot\r\n```\r\n\r\n安装完成后，在该 skill 目录中创建虚拟环境并安装依赖（否则无法 `import` / 调用）：\r\n```bash\r\npython3 -m venv .venv\r\nsource .venv/bin/activate\r\npip install -r requirements.txt\r\npip install -e .\r\n```\r\n\r\n### 方式 B：从 GitHub 源码安装（推荐给开发者）\r\n如果你是要开发/改代码，直接 clone 本仓库后：\r\n```bash\r\npip install -r requirements.txt\r\n```\r\n\r\n推荐（开发环境）：\r\n```bash\r\npip install -e .\r\n```\r\n安装后可直接 `import quote_service/trade_service/account_manager/config_manager`，\r\n无需再手动设置 `PYTHONPATH` 或在脚本里写 `sys.path`。\r\n\r\n额外可直接导入：\r\n- `preflight_check`\r\n- `strategy_runtime`\r\n- `strategy`\r\n\r\n## 配置\r\n配置文件路径：`json/config.json`\r\n\r\n最小模板：\r\n```json\r\n{\r\n  \"futu_api\": {\r\n    \"host\": \"127.0.0.1\",\r\n    \"port\": 11111,\r\n    \"security_firm\": \"FUTUSECURITIES\",\r\n    \"trade_password\": \"\",\r\n    \"trade_password_md5\": \"\",\r\n    \"default_env\": \"SIMULATE\"\r\n  }\r\n}\r\n```\r\n\r\n说明：\r\n- `trade_password_md5` 优先级高于 `trade_password`\r\n- `json/config.json` 含敏感信息，已建议加入 `.gitignore`\r\n- 若 `json/config.json` 不存在，代码会优先回退到 `json/config_example.json`，也兼容旧命名 `json/config.example.json`\r\n\r\n## 示例\r\n```python\r\nfrom preflight_check import run_preflight\r\nfrom account_manager import get_account_info, unlock_trade, lock_trade\r\nfrom trade_service import submit_order\r\n\r\nprint(run_preflight())\r\nprint(get_account_info())  # 默认不落盘\r\n# print(get_account_info(persist=True))  # 仅在用户要求缓存时\r\n\r\nprint(unlock_trade(confirm=True))  # 需用户明确同意；从配置读取密码/MD5\r\n\r\nprint(submit_order(\r\n    code=\"HK.00700\",\r\n    side=\"BUY\",\r\n    qty=200,\r\n    price=150,\r\n    order_type=\"NORMAL\",\r\n    acc_id=6017237,\r\n    trd_env=\"SIMULATE\",\r\n))\r\n# REAL 示例（需用户明确批准参数后）:\r\n# submit_order(..., trd_env=\"REAL\", confirm=True)\r\n\r\nprint(lock_trade(confirm=True))\r\n```\r\n\r\n## 实时行情回调示例\r\n```python\r\nfrom quote_service import start_quote_stream, unsubscribe_all, close_quote_service\r\nfrom strategy_runtime import run_strategy\r\nfrom strategy import StrategyState, TradeGuard, extract_latest_price\r\n\r\nstate = StrategyState()\r\nguard = TradeGuard()\r\n\r\ndef on_quote(payload):\r\n    price = extract_latest_price(payload, code=\"HK.00700\")\r\n    if price is None:\r\n        return\r\n    with guard.locked():\r\n        state.current_price = price\r\n        print(\"latest price:\", price)\r\n\r\nstart_quote_stream([\"HK.00700\"], on_quote)\r\nrun_strategy(\r\n    pid_file=\"/tmp/futu_strategy.pid\",\r\n    cleanup_callbacks=[unsubscribe_all, close_quote_service],\r\n)\r\n```\r\n\r\n## 运行要求\r\n- 本机已安装并运行 Futu OpenD\r\n- OpenD 地址与 `json/config.json` 一致（默认 `127.0.0.1:11111`）\r\n- 真实交易前先确认账户已解锁且参数正确\r\n- 若在 OpenClaw/Codex 等受限环境中运行，建议先执行 `PYTHONPATH=src python -m preflight_check`\r\n- 若预检提示日志目录或 OpenD 访问受限，请改用 `host/elevated` 模式\n\nFile v1.0.8:_meta.json\n\n{\n  \"ownerId\": \"kn79d46ahs4v5syfeh8jjzqf7d81y7rr\",\n  \"slug\": \"futu-trading-bot\",\n  \"version\": \"1.0.8\",\n  \"publishedAt\": 1786008493368\n}\n\nFile v1.0.8:docs/account.md\n\n# Account Manager 文档\r\n\r\n所属项目：**Futu Trade Bot Skills**\r\n\r\n## 模块位置\r\n`src/account_manager.py`\r\n\r\n## 安全提示\r\n- `unlock_trade` / `lock_trade` 会改变真实券商账户的交易锁定状态，**必须** `confirm=True`，且仅在用户明确授权后调用。\r\n- 不要通过 agent stdin 收集交易密码；优先使用配置中的 `trade_password_md5`。\r\n- `get_account_info` 默认**不写盘**。仅当用户要求缓存账户列表时使用 `persist=True`（写入 `json/account_info.json`，含账户 ID / 环境 / 券商等元数据，请限制文件权限且勿提交仓库）。\r\n\r\n## 对外接口\r\n\r\n### `get_account_info(persist=False)`\r\n```python\r\nget_account_info(persist: bool = False) -> Dict[str, Any]\r\n```\r\n\r\n行为：\r\n- 调用富途 `get_acc_list()`。\r\n- 返回账户列表结构：`accounts`。\r\n- 仅当 `persist=True` 时覆盖写 `json/account_info.json`，并在结果中设置 `persisted=True/False`。\r\n\r\n### `unlock_trade(password=None, password_md5=None, confirm=False)`\r\n```python\r\nunlock_trade(\r\n    password: Optional[str] = None,\r\n    password_md5: Optional[str] = None,\r\n    confirm: bool = False,\r\n) -> Dict[str, Any]\r\n```\r\n\r\n- `confirm` 必须为 `True`，否则直接失败。\r\n- 密码优先级：显式 `password_md5` → 显式 `password` → 配置 `trade_password_md5` → 配置 `trade_password`。\r\n\r\n### `lock_trade(password=None, password_md5=None, confirm=False)`\r\n同样需要 `confirm=True`。内部调用富途 `unlock_trade(..., is_unlock=False)`。\r\n\r\n## 使用示例\r\n```python\r\nfrom account_manager import get_account_info, unlock_trade, lock_trade\r\n\r\nprint(get_account_info())\r\nprint(unlock_trade(confirm=True))\r\nprint(lock_trade(confirm=True))\r\n```\r\n\r\n## 注意事项\r\n- 依赖 OpenD 连接可用。\r\n- 明文密码和 MD5 都属于敏感信息。\r\n- 对外函数返回后会关闭账户相关 context。\n\nFile v1.0.8:docs/config.md\n\n# Config Manager 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/config_manager.py`\n\n## 作用\n统一加载并提供项目配置（富途连接参数、交易密码、日志参数）。\n\n## 配置文件读取规则\n1. 优先读取：`json/config.json`\n2. 回退读取：`json/config_example.json`（存在时）\n3. 兼容读取：`json/config.example.json`（旧命名存在时）\n4. 若都不存在，抛出 `FileNotFoundError`\n\n## 配置示例\n```json\n{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"\",\n    \"trade_password_md5\": \"\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}\n```\n\n## 默认值（缺省字段自动补全）\n- `host`: `127.0.0.1`\n- `port`: `11111`\n- `security_firm`: `FUTUSECURITIES`\n- `trade_password`: `\"\"`\n- `trade_password_md5`: `\"\"`\n- `default_env`: `SIMULATE`\n\n## 主要接口\n- `get_futu_config()`\n- `get_host()`\n- `get_port()`\n- `get_security_firm()`\n- `get_trade_password()`\n- `get_trade_password_md5()`\n- `get_default_env()`\n- `get_default_env_str()`\n\n## 与其他模块关系\n- `account_manager` 使用本模块读取主机、端口、券商、交易密码。\n- `trade_service` 使用本模块读取主机、端口、券商。\n\n## 安全建议\n- `json/config.json` 不应入库，需加入 `.gitignore`。\n- 使用最小权限：`chmod 600 json/config.json`。\n- 不在日志中输出真实密码或 MD5 值。\n\nFile v1.0.8:docs/development_plan.md\n\n你说得对，富途的行情接口确实很多。不过别担心，我们不需要一次性封装所有接口。根据你之前开发交易模块的经验，我们可以采用“**先核心，后扩展，按需封装**”的策略。\n\n下面我帮你梳理一个清晰的开发路线图，你可以根据实际需要决定优先实现哪些部分。\n\n### 📈 行情模块封装路线图\n\n#### **第一阶段：核心基础（必须实现）**\n这是所有行情功能的基石，也是你之前交易模块中已经用到的部分。\n1.  **连接管理**：封装 `OpenQuoteContext` 的创建与关闭，沿用交易模块的延迟初始化模式。\n2.  **基础数据获取**：\n    *   **`get_stock_basicinfo`**：获取股票代码、每手股数等基本信息。你的交易模块中已经需要这个接口来校验下单数量。\n    *   **`get_market_state`**：获取市场状态（如是否在交易中），这对判断能否下单很有用。\n\n#### **第二阶段：实时行情订阅（核心功能）**\n这是为了构建实时监控或自动交易策略的基础。\n1.  **订阅管理**：封装 `subscribe`、`unsubscribe`、`unsubscribe_all`、`query_subscription` 四个接口，实现订阅状态的统一管理。\n2.  **推送回调**：\n    *   **报价推送 (`StockQuoteHandlerBase`)**：实时获取价格变动，最常用。\n    *   **摆盘推送 (`OrderBookHandlerBase`)**：如果需要监控深度行情。\n    你可以先实现报价推送，因为这是最基本的需求。\n\n#### **第三阶段：主动数据拉取（常用功能）**\n当需要一次性获取当前数据快照时使用。\n1.  **市场快照 (`get_market_snapshot`)**：最常用的“看一眼”接口，能一次性获取最新价、涨跌幅、成交量等核心数据。\n2.  **K线数据 (`get_cur_kline` 或 `request_history_kline`)**：用于技术分析或展示图表。\n3.  **实时逐笔 (`get_rt_ticker`)**：如果需要监控每一笔成交。\n\n#### **第四阶段：进阶数据（按需扩展）**\n这些接口用于特定的策略或分析，可以根据你的实际需求逐步添加。\n*   **全市场筛选 (`get_stock_filter`)**：用于选股策略。\n*   **板块数据 (`get_plate_stock`, `get_plate_list`)**：分析板块轮动。\n*   **资金流向 (`get_capital_flow`)**：观察主力资金动向。\n*   **自选股管理 (`get_user_security` 等)**：如果你需要管理用户的股票池。\n\n### 💡 给你的具体建议\n\n1.  **先从交易模块中已有的依赖开始**：你的 `trade_service` 已经用到了 `get_market_snapshot` 来获取每手股数，可以优先把它完整封装起来。\n2.  **遵循“先测试，后封装”原则**：就像你之前做的，先用一个简单的测试脚本调通一个接口（比如 `get_market_snapshot`），理解它的输入输出，然后再进行封装。\n3.  **统一设计风格**：延续交易模块的设计模式：一个内部服务类 (`_HKQuoteService`) + 对外暴露的简洁函数。返回格式也保持一致 `{\"success\": bool, \"data\": ..., \"message\": str}`。\n4.  **管理好订阅状态**：在服务类内部维护一个订阅列表，避免重复订阅，也便于取消订阅。\n\n你可以先从第一阶段和第三阶段开始，搭建起行情模块的骨架。当有具体的策略需求时，再有针对性地封装第二阶段或其他进阶接口。这样既不会一开始就被庞大的接口列表吓倒，也能快速用起来。\n\nFile v1.0.8:docs/quote.md\n\n# Quote Service 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/quote_service.py`\n\n## 概述\n行情模块负责：\n- 基础行情拉取\n- K 线与逐笔拉取\n- 行情订阅与回调\n- 统一启动实时报价/摆盘监听\n\n## 拉取型函数\n- `get_stock_basicinfo(...)`\n- `get_market_state(...)`\n- `get_market_snapshot(...)`\n- `get_cur_kline(...)`\n- `request_history_kline(...)`\n- `get_rt_ticker(...)`\n\n说明：\n- 拉取型函数返回后会显式关闭 quote context。\n- `get_cur_kline(...)` 和 `get_rt_ticker(...)` 在遇到“请先订阅”时会自动补订阅后重试。\n\n## 订阅/回调型函数\n- `set_quote_callback(callback)`\n- `set_orderbook_callback(callback)`\n- `subscribe(...)`\n- `unsubscribe(...)`\n- `unsubscribe_all()`\n- `query_subscription()`\n\n说明：\n- 这些函数不会自动关闭 quote context。\n- 用于长连接 / 回调推送场景。\n- 调用方结束时应显式 `close_quote_service()`。\n\n## 统一启动函数\n\n### `start_quote_stream(...)`\n完成两步：\n1. 注册 `QUOTE` 回调\n2. 发起 `QUOTE` 订阅\n\n### `start_orderbook_stream(...)`\n完成两步：\n1. 注册 `ORDER_BOOK` 回调\n2. 发起 `ORDER_BOOK` 订阅\n\n这两个函数适合策略脚本，避免把“设置回调 + 订阅”拆开写。\n\n## 使用示例\n```python\nfrom quote_service import start_quote_stream, unsubscribe_all, close_quote_service\n\ndef on_quote(payload):\n    print(payload)\n\nstart_quote_stream([\"HK.00700\"], on_quote)\n\n# done\nunsubscribe_all()\nclose_quote_service()\n```\n\nFile v1.0.8:docs/strategy.md\n\n# Strategy Helpers 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n- `src/strategy.py`\n- `src/strategy_runtime.py`\n\n## 目标\n为策略脚本提供轻量辅助，而不是复杂框架。\n\n## `strategy.py`\n提供三类能力：\n\n1. 运行状态\n- `StrategyState`\n\n2. 并发保护\n- `TradeGuard`\n\n3. 运行辅助判断\n- `in_trading_window(...)`\n- `trading_window_status(...)`\n- `cooldown_elapsed(...)`\n- `holding_timeout_exceeded(...)`\n\n4. 回调 payload 解析\n- `extract_callback_rows(payload)`\n- `filter_rows_by_code(rows, code)`\n- `extract_latest_price(payload, code=None, field=\"last_price\")`\n\n## `strategy_runtime.py`\n提供：\n- `run_strategy(...)`\n\n职责只包括：\n- PID 文件管理\n- 防重复启动\n- `SIGINT` / `SIGTERM` 清理\n- 保持进程运行\n\n## 推荐使用方式\n1. 先用 `start_quote_stream(...)` 或 `start_orderbook_stream(...)` 建立订阅\n2. 在回调中用 `extract_latest_price(...)` 等辅助解析行情\n3. 用 `StrategyState` 和 `TradeGuard` 管理策略状态\n4. 最后调用 `run_strategy(...)` 保持进程运行并处理退出清理\n\nFile v1.0.8:docs/trade.md\n\n# Trade Service 文档\r\n\r\n所属项目：**Futu Trade Bot Skills**\r\n\r\n## 模块位置\r\n`src/trade_service.py`\r\n\r\n## 概述\r\n交易模块负责下单、改单、撤单与全部撤单，内部包含参数校验和富途 API 调用。\r\n\r\n## 安全门闩\r\n- 推荐默认：`trd_env=\"SIMULATE\"`。\r\n- `submit_order` / `modify_order` / `cancel_order`：当 `trd_env=\"REAL\"` 时必须 `confirm=True`。\r\n- `cancel_all_orders`：**任何环境**都必须 `confirm=True`（高 blast radius）。\r\n- 缺少确认时函数返回 `success=False` 与说明信息，不会调用富途下单接口。\r\n\r\n## 设计原则\r\n- 交易环境不做内部管理，调用方必须显式传入。\r\n- 不提供账户环境切换接口（无 `switch_account_env`）。\r\n- 不做幂等去重校验。\r\n\r\n## 对外接口\r\n\r\n### `submit_order(...)`\r\n```python\r\nsubmit_order(\r\n    code: str,\r\n    side: str,\r\n    qty: int,\r\n    acc_id: int,\r\n    trd_env: str,\r\n    price: Optional[float] = None,\r\n    order_type: str = \"NORMAL\",\r\n    aux_price: Optional[float] = None,\r\n    remark: Optional[str] = None,\r\n    time_in_force: str = \"DAY\",\r\n    confirm: bool = False,\r\n) -> Dict[str, Any]\r\n```\r\n\r\n### `modify_order(...)` / `cancel_order(...)`\r\n`REAL` 需要 `confirm=True`。\r\n\r\n### `cancel_all_orders(...)`\r\n```python\r\ncancel_all_orders(trd_env: str, acc_id: int = 0, trdmarket: Optional[str] = None, confirm: bool = False)\r\n```\r\n必须 `confirm=True`。\r\n\r\n## 使用示例\r\n```python\r\nfrom trade_service import submit_order, cancel_all_orders\r\n\r\nresult = submit_order(\r\n    code=\"HK.00700\",\r\n    side=\"BUY\",\r\n    qty=200,\r\n    acc_id=6017237,\r\n    trd_env=\"SIMULATE\",\r\n    price=150,\r\n    order_type=\"NORMAL\",\r\n)\r\nprint(result)\r\n\r\n# cancel_all_orders(trd_env=\"SIMULATE\", acc_id=6017237, confirm=True)\r\n```\r\n\r\n## 注意事项\r\n- `REAL` 环境会尝试真实交易，请先确认交易权限状态。\r\n- 真实交易密码解锁/锁定由 `account_manager` 处理，不在本模块内自动完成。\n\nFile v1.0.8:skill-card.md\n\n## Description:\n\nUse Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[jeffersonling1217-png](https://clawhub.ai/user/jeffersonling1217-png)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and agent developers use this skill to query Futu account and HK market data, manage simulated trading workflows, and execute confirmed live Futu OpenD trading actions through guarded Python wrappers.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can interact with a live brokerage account through Futu OpenD, including live orders, account unlocks, and order cancellation.\n\nMitigation: Keep SIMULATE as the default and require explicit user confirmation for live orders, unlock or lock actions, and cancel-all operations.\n\nRisk: Trading credentials and account metadata may be present in local configuration or optional account cache files.\n\nMitigation: Protect json/config.json, prefer trade_password_md5 over plaintext passwords, and write account_info.json only when the user explicitly opts in.\n\nRisk: Background strategies can place repeated actions or continue running after the initiating conversation.\n\nMitigation: Start background strategies only after the user confirms fixed parameters, SIMULATE or REAL mode, and monitorable PID and log paths.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/jeffersonling1217-png/skills/futu-trading-bot)\n- [Account Manager Documentation](docs/account.md)\n- [Trade Service Documentation](docs/trade.md)\n- [Quote Service Documentation](docs/quote.md)\n- [Configuration Documentation](docs/config.md)\n- [Strategy Helpers Documentation](docs/strategy.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown guidance with Python snippets, shell commands, JSON configuration, and dictionary-shaped function results]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Live trading, account unlock, and cancel-all workflows require explicit user confirmation; SIMULATE is the documented default.]\n\n## Skill Version(s):\n\n1.0.8 (source: server release metadata and pyproject.toml)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.0.8:json/config_example.json\n\n{\r\n  \"futu_api\": {\r\n    \"host\": \"127.0.0.1\",\r\n    \"port\": 11111,\r\n    \"security_firm\": \"FUTUSECURITIES\",\r\n    \"trade_password\": \"\",\r\n    \"trade_password_md5\": \"\",\r\n    \"default_env\": \"SIMULATE\"\r\n  },\r\n  \"logging\": {\r\n    \"level\": \"INFO\",\r\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\r\n  }\r\n}\n\nFile v1.0.8:pyproject.toml\n\n[build-system]\r\nrequires = [\"setuptools>=68\", \"wheel\"]\r\nbuild-backend = \"setuptools.build_meta\"\r\n\r\n[project]\r\nname = \"futu-trade-bot-skills\"\r\nversion = \"1.0.8\"\r\ndescription = \"Futu Trade Bot Skills modules for account, trade, and quote services.\"\r\nreadme = \"README.md\"\r\nrequires-python = \">=3.10\"\r\ndependencies = [\r\n  \"futu-api==9.6.5608\",\r\n  \"pydantic>=2.7.0,<3\",\r\n]\r\n\r\n[tool.setuptools]\r\npy-modules = [\"account_manager\", \"config_manager\", \"trade_service\", \"quote_service\", \"preflight_check\", \"strategy_runtime\", \"strategy\"]\r\n\r\n[tool.setuptools.package-dir]\r\n\"\" = \"src\"\n\nArchive v1.0.7: 20 files, 43755 bytes\n\nFiles: docs/account.md (2201b), docs/config.md (1531b), docs/development_plan.md (3458b), docs/quote.md (1516b), docs/strategy.md (1091b), docs/trade.md (2976b), json/config_example.json (274b), pyproject.toml (538b), README.md (5475b), requirements.txt (24b), skill-card.md (2779b), SKILL.md (16223b), src/account_manager.py (13925b), src/config_manager.py (7404b), src/preflight_check.py (8558b), src/quote_service.py (20690b), src/strategy_runtime.py (2934b), src/strategy.py (3776b), src/trade_service.py (33929b), _meta.json (135b)\n\nFile v1.0.7:SKILL.md\n\n---\nname: futu-trading-bot\ndescription: Use Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.\nlicense: MIT-0\nmetadata:\n  openclaw:\n    emoji: \"📈\"\n    requires:\n      bins: [\"python3\", \"pip\"]\n---\n\n# Futu Trade Bot Skills 📈\n\n## 🎯 Overview / 概述\n\n**English Version:**\nA trading bot skill based on Futu OpenAPI that enables natural language trading. This skill encapsulates Futu's market quote and order execution APIs, allowing agents to perform real-time trading operations through simple commands or scripts. Perfect for implementing natural language trading strategies and automated workflows.\n\n**Important**: Always use the encapsulated functions provided in this skill (e.g., `submit_order`, `get_market_snapshot`). **Never call Futu SDK functions directly** (`ctx.place_order`, `ctx.get_market_snapshot`), as this will bypass connection management, parameter validation, and error handling, leading to unpredictable failures and resource leaks.\n\n**中文版本:**\n基于富途牛牛API接口的交易机器人技能，帮助用户用自然语言进行交易。本技能已将富途牛牛的行情报价、下单交易等功能做了完整封装，可供智能助手随时调用。建议通过命令行或脚本来实现自然语言的策略生成和交易执行。\n\n**重要提示**：请始终使用本技能提供的封装函数（如 `submit_order`、`get_market_snapshot`）。**切勿直接调用富途SDK的原始函数**（例如 `ctx.place_order`），否则会绕过连接管理、参数校验和错误处理，导致不可预料的失败和资源泄漏。\n\n---\n\n## When to Use This Skill / 使用场景\n\nUse this skill when the user asks in natural language, for example:\n\n- **账户相关**：“查一下我的账户余额”、“解锁交易”、“锁定账户”、“看看我有哪些账户”\n- **行情查询**：“腾讯现在多少钱？”、“查一下港交所的实时报价”、“帮我看看美团今天的K线图”\n- **数据拉取**：“获取腾讯的历史K线数据”、“拉取最近10笔成交”\n- **订阅与回调**：“实时监控腾讯的报价”、“给我推送腾讯的逐笔成交”\n- **下单交易**：“帮我买100股腾讯，限价350”、“卖出200股阿里”、“撤单”、“把订单价格改到355”\n- **策略运行**：\n  - “帮我写一个区间策略，监控腾讯，低于540买入，高于550卖出”\n  - “启动这个策略”\n  - “我的策略跑得怎么样了？”\n  - “停止我的策略”\n\n**Note to agent**: When the user expresses any of these intents, you should use the encapsulated functions provided in this skill (e.g., `get_account_info`, `get_market_snapshot`, `submit_order`, etc.). **Never call Futu SDK functions directly** – always go through the skill's API.\n\n## Quick Start / 快速开始\n\n**Prerequisites / 前提条件:**\n- Ensure Futu OpenD is running and HK quote entitlement is available.\n- 确保富途OpenD正在运行且拥有港股行情权限。\n- When running inside a restricted agent sandbox (for example OpenClaw/Codex exec), prefer `host` / `elevated` mode.\n- The Futu Python SDK may access local OpenD resources during import, including the user log directory under `~/.com.futunn.FutuOpenD/Log`, so restricted sandboxes may fail before business functions are called.\n- 如果在受限的 agent 沙箱中运行（例如 OpenClaw/Codex exec），优先使用 `host` / `elevated` 模式。\n- 富途 Python SDK 在导入阶段就可能访问本机 OpenD 相关资源，包括 `~/.com.futunn.FutuOpenD/Log` 下的日志目录；因此受限沙箱可能会在业务函数执行前就失败。\n\n**Setup Steps / 安装步骤:**\n1. Install this skill via ClawHub (if not installed yet):\n   ```bash\n   clawhub install futu-trading-bot\n   ```\n\n2. Enter the skill folder (default OpenClaw workspace path):\n   ```bash\n   cd ~/.openclaw/workspace/skills/futu-trading-bot\n   ```\n   If you installed to a different location, `cd` into that folder instead.\n\n3. Create virtual environment (recommended):\n   ```bash\n   python3 -m venv .venv\n   source .venv/bin/activate\n   ```\n\n4. Install package:\n   ```bash\n   pip install -e .\n   ```\n\n5. Configure credentials:\n   ```bash\n   cp json/config_example.json json/config.json\n   # Edit json/config.json with your Futu credentials\n   # 编辑json/config.json填写你的富途账户信息\n   ```\n\n## 依赖项\n\n本技能通过 `pip install -e .` 自动安装以下核心 Python 包：\n- `futu-api`（富途 SDK）\n- `pydantic`（数据校验）\n\n更多依赖请以 `pyproject.toml` / `requirements.txt` 为准。\n\n## Module Map\n\n- **Account**: `account_manager`\n  - `get_account_info()`\n  - `unlock_trade(password=None, password_md5=None)`\n  - `lock_trade()`\n- **Quote**: `quote_service`\n  - Stage 1: `get_stock_basicinfo`, `get_market_state`\n  - Stage 2: `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, callbacks\n  - Stage 3: `get_market_snapshot`, `get_cur_kline`, `request_history_kline`, `get_rt_ticker`\n  - Stage 4: `start_quote_stream`, `start_orderbook_stream`\n- **Trade**: `trade_service`\n  - `submit_order`, `modify_order`, `cancel_order`, `cancel_all_orders`\n- **Strategy Runtime**: `strategy_runtime`\n  - `run_strategy`\n- **Strategy Helpers**: `strategy`\n  - in-memory state\n  - trade guard / lock\n  - trading window and cooldown helpers\n\n## Standard Workflow\n\n1. Run `preflight_check` first to verify config, OpenD connectivity, and sandbox/runtime readiness.\n2. Call `get_account_info()` and select target account (get `acc_id`).\n3. Pull quote/snapshot for the target symbol (default HK use case: `HK.00700`).\n4. For real trading, call `unlock_trade(...)` (password from config or input).\n5. Submit or manage orders with explicit `acc_id` and `trd_env`.\n6. After real operation, call `lock_trade()` if needed.\n\n## Connection Lifecycle\n\n- Pull-style quote functions such as `get_market_snapshot`, `get_stock_basicinfo`, `get_market_state`, `get_cur_kline`, `request_history_kline`, and `get_rt_ticker` now close their quote context automatically after returning.\n- Trade functions such as `submit_order`, `modify_order`, and `cancel_all_orders` now close their trade/quote contexts automatically after returning.\n- Account functions such as `get_account_info`, `unlock_trade`, and `lock_trade` now close their contexts automatically after returning.\n- Subscription/callback flows keep the quote context open on purpose. For `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, `set_quote_callback`, and `set_orderbook_callback`, call `close_quote_service()` explicitly when you are done with the session.\n\n## Canonical Imports\n\n```python\n# Always use these import paths – do not import from futu directly\nfrom preflight_check import run_preflight\nfrom strategy import (\n    StrategyState, TradeGuard, in_trading_window,\n    trading_window_status, cooldown_elapsed, holding_timeout_exceeded\n)\nfrom strategy_runtime import run_strategy\nfrom account_manager import get_account_info, unlock_trade, lock_trade\nfrom quote_service import (\n    get_stock_basicinfo, get_market_state, get_market_snapshot,\n    get_cur_kline, request_history_kline, get_rt_ticker,\n    subscribe, unsubscribe, unsubscribe_all, query_subscription,\n    set_quote_callback, set_orderbook_callback,\n    start_quote_stream, start_orderbook_stream\n)\nfrom trade_service import submit_order, modify_order, cancel_order, cancel_all_orders\n```\n\n## Account Usage\n\n### Preflight\n```python\npreflight = run_preflight()\nif not preflight[\"success\"]:\n    print(preflight)\n    raise SystemExit(\"Preflight failed\")\n```\n\n```python\n# Get list of accounts\ninfo = get_account_info()\nif info['success']:\n    accounts = info['accounts']\n    print(accounts)\n\n# Unlock trade (uses password from config or provided)\nunlock_trade()  # will prompt for password if not configured\n# Or with explicit password:\n# unlock_trade(password=\"your_password\")\n\n# Lock trade\nlock_trade()\n```\n\n## Quote Usage\n\n### Basic Info / Market State\n```python\nget_stock_basicinfo(market=\"HK\", sec_type=\"STOCK\", code_list=[\"HK.00700\"])\nget_market_state([\"HK.00700\"])\n```\n\n### Snapshot (no subscription needed)\n```python\nsnap = get_market_snapshot([\"HK.00700\"])\nif snap['success']:\n    price = snap['data'][0]['last_price']\n```\n\n### K-Line\n```python\n# Current K-line (requires subscription, will auto-subscribe if needed)\nkline = get_cur_kline(code=\"HK.00700\", num=5, ktype=\"K_DAY\", autype=\"QFQ\")\n\n# Historical K-line\nhist = request_history_kline(\n    code=\"HK.00700\",\n    start=\"2026-02-20\",\n    end=\"2026-03-06\",\n    ktype=\"K_DAY\"\n)\n```\n\n### Ticker\n```python\ntickers = get_rt_ticker(code=\"HK.00700\", num=10)\n```\n\n### Subscription & Callbacks\n```python\ndef on_quote(payload):\n    print(payload)\n\nset_quote_callback(on_quote)\nsubscribe([\"HK.00700\"], [\"QUOTE\"], is_first_push=True, subscribe_push=True)\nquery_subscription()\nunsubscribe([\"HK.00700\"], [\"QUOTE\"])\nunsubscribe_all()\nclose_quote_service()\n```\n\n### Unified Stream Startup\n```python\ndef on_quote(payload):\n    print(payload)\n\nstart_quote_stream([\"HK.00700\"], on_quote)\n```\n\n### Strategy Helpers\n```python\nstate = StrategyState()\nguard = TradeGuard()\n\nif in_trading_window(start_time=\"09:30\", end_time=\"16:00\"):\n    with guard.locked():\n        pass\n```\n\n## Trade Usage\n\n```python\n# Submit an order\nresult = submit_order(\n    code=\"HK.00700\",\n    side=\"BUY\",\n    qty=200,\n    acc_id=6017237,               # from get_account_info\n    trd_env=\"SIMULATE\",            # or \"REAL\"\n    price=150,                     # required for LIMIT order\n    order_type=\"NORMAL\",\n)\n\n# Modify order (change price/quantity)\nmodify_order(\n    op=\"NORMAL\",\n    order_id=\"123456789\",\n    trd_env=\"SIMULATE\",\n    price=151,\n    qty=200,\n    acc_id=6017237\n)\n\n# Cancel a single order\ncancel_order(order_id=\"123456789\", trd_env=\"SIMULATE\", acc_id=6017237)\n\n# Cancel all orders\ncancel_all_orders(trd_env=\"SIMULATE\", acc_id=6017237)\n```\n\n## Running a Background Trading Strategy (Using System Tools)\n\nThis skill does not manage long-running processes internally. Instead, you (the agent) should use system tools (e.g., `exec`, `write`, `kill`) to run strategy scripts in the background. This keeps the skill simple and leverages the platform's process management.\n\n### 4.1 Workflow for Background Strategies\n\n1. **Run preflight first** with `PYTHONPATH=src python -m preflight_check`.\n2. If preflight reports sandbox/log-directory restrictions, rerun in `host` / `elevated` mode before using quote/trade functions.\n3. **Generate a Python script** based on user's natural language request, using the encapsulated functions from this skill (e.g., `start_quote_stream`, `submit_order`, `run_strategy`).\n4. **Save the script** to a temporary file (using the `write` tool or similar).\n5. **Launch the script as a background process** using the `exec` tool, redirecting output to a log file.\n6. **Record the process ID (PID)** and log file path for future monitoring.\n7. **Monitor/stop** using system tools (`ps`, `kill`, `cat`).\n\n### 4.2 Natural Language Triggers\n\n| User Request | Agent Action |\n|--------------|--------------|\n| “Start a strategy to monitor Tencent, buy below 540, sell above 550” | Generate script → save → launch with `exec` → return PID and log path |\n| “How is my strategy doing?” | Read log file (e.g., `tail -n 20 logfile`) → summarize |\n| “Stop my strategy” | Kill process using PID via `kill` tool |\n\n### 4.3 Script Template (for Agent Reference)\n\nWhen generating a strategy script, use the following template. It handles signals, logging, and state persistence correctly.\n\n```python\n#!/usr/bin/env python3\nimport sys\nimport time\nimport json\nimport os\nimport signal\nimport logging\nfrom pathlib import Path\n\n# If you installed the skill with `pip install -e .`, you can import modules directly.\n# Only use sys.path/PYTHONPATH hacks when you didn't install the package.\n\nfrom trade_service import submit_order\nfrom quote_service import get_market_snapshot\n\n# ===== Strategy parameters – fill by agent =====\n# Replace these placeholders with your own strategy settings.\nSYMBOL = \"HK.00700\"\nACC_ID = 0                 # fill from get_account_info()\nTRD_ENV = \"SIMULATE\"       # default to SIMULATE; use REAL only with explicit confirmation\nQTY = 0                    # position sizing / order quantity\nLOG_FILE = Path(\"strategy.log\")\nPID_FILE = Path(\"strategy.pid\")\n# ===============================================\n\nlogging.basicConfig(\n    filename=LOG_FILE,\n    level=logging.INFO,\n    format='%(asctime)s - %(levelname)s - %(message)s'\n)\n\n# Handle termination signals\ndef handle_exit(signum, frame):\n    logging.info(\"Received signal, stopping strategy\")\n    sys.exit(0)\n\nsignal.signal(signal.SIGTERM, handle_exit)\nsignal.signal(signal.SIGINT, handle_exit)\n\n# Write PID file\nwith open(PID_FILE, \"w\") as f:\n    f.write(str(os.getpid()))\n\nlogging.info(f\"Strategy started: {SYMBOL}\")\n\ntry:\n    while True:\n        snap = get_market_snapshot([SYMBOL])\n        if not snap[\"success\"]:\n            logging.error(f\"Quote failed: {snap['message']}\")\n            time.sleep(60)\n            continue\n        price = snap[\"data\"][0][\"last_price\"]\n        logging.info(f\"Current price: {price}\")\n\n        # --- Insert your strategy logic here ---\n        # Decide whether to trade based on your own signals/logic, then call submit_order(...).\n\n        time.sleep(60)   # check every minute\nexcept Exception as e:\n    logging.exception(\"Strategy crashed\")\nfinally:\n    if PID_FILE.exists():\n        PID_FILE.unlink()\n```\n\n### 4.4 Agent Execution Steps\n\n**User**: “Start a range strategy for Tencent, buy below 540, sell above 550.”\n\n**Agent**:\n1. **Get account ID** via `get_account_info()`.\n2. **Generate script** using the template above, filling in parameters.\n3. **Save script** to a file, e.g., `range_00700.py`, using `write` tool.\n4. **Launch background process** using `exec`:\n   ```bash\n   cd /path/to/workspace\n   nohup .venv/bin/python range_00700.py > strategy.out 2>&1 &\n   ```\n   (Capture the PID from output.)\n5. **Record** PID and log path.\n6. **Reply**: “Strategy started. PID: 12345, log file: strategy_00700.log. You can check status or stop it anytime.”\n\n### 4.5 Check Status\n\n**User**: “How is my strategy doing?”\n\n**Agent**:\n- Read last lines of log: `tail -n 20 strategy_00700.log`.\n- Check if process still running: `ps -p 12345`.\n- Summarize: “Strategy is running, last price was 542.5 at 10:30.”\n\n### 4.6 Stop Strategy\n\n**User**: “Stop my strategy.”\n\n**Agent**:\n- Send SIGTERM: `kill 12345`.\n- Verify process ended, clean up PID file if needed.\n- Reply: “Strategy stopped.”\n\n---\n\n## Error Handling\n\n- All functions return a dictionary with at least `success` (bool) and `message` (str).\n- On success, additional fields like `data` or `order_id` may be present.\n- Always check `success` first before using other fields.\n\nExample:\n```python\nresult = submit_order(...)\nif result[\"success\"]:\n    print(f\"Order ID: {result['order_id']}\")\nelse:\n    print(f\"Error: {result['message']}\")\n```\n\nIf OpenD connection fails, recheck:\n- OpenD is running (check port 11111 with `lsof -i :11111`)\n- Host/port in `config.json` matches OpenD\n- Account has necessary permissions\n\nIf the skill fails before quote/trade functions are even called, recheck:\n- Whether the current agent/tool is running in a restricted sandbox\n- Whether you should rerun in `host` / `elevated` mode\n- Whether the runtime can access the local Futu OpenD log directory under `~/.com.futunn.FutuOpenD/Log`\n- Run `PYTHONPATH=src python -m preflight_check` first and follow its suggestions\n\n## Configuration\n\n- **Config file**: `json/config.json`\n- **Required fields**:\n  - `futu_api.host` (default: 127.0.0.1)\n  - `futu_api.port` (default: 11111)\n  - `futu_api.security_firm` (e.g., `FUTUSECURITIES`)\n- **Password handling**:\n  - Prefer `trade_password_md5` (32‑char lowercase MD5)\n  - Fallback to `trade_password` (will be MD5‑ed at runtime)\n- **Account cache**: `json/account_info.json` (auto‑generated after `get_account_info`)\n\n## 📜 License\n\nThis skill is licensed under **MIT-0** (MIT No Attribution).\n\n---\n\n**Copyright © 2026 jeffersonling1217-png**\n```\n\nFile v1.0.7:README.md\n\n# Futu Trading Bot Skills\n\n这是一个为 AI Agent 打造的自然语言交易执行工具。它将富途 OpenAPI 的底层逻辑封装为语义能力，支持通过自然语言驱动账户解锁、下单及风控管理。系统支持（模拟/实盘）环境隔离，能够将“帮我买 200 股腾讯”或“清仓一半持仓”这类模糊意图，转化为符合金融规范的执行动作。\n\nA robust trade execution tool designed for AI Agents. It abstracts Futu OpenAPI logic into high-level semantic capabilities, enabling natural language control over account unlocking, order placement, and risk management. With native support for MD5 credential handling and environment isolation (Simulated/Real), it accurately translates vague intents—such as \"buy 200 shares of Tencent\" or \"close half of my positions\"—into execution actions that comply with financial standards.\n\n适用对象：配合 OpenClaw 使用，或任何能通过命令行调用工具并能编写 Python 脚本的 Agent/LLM。\n\n核心代码在 `src/`，配置与运行数据在 `json/`。\n\n## 功能\n- 账户查询：`get_account_info()`\n- 交易解锁：`unlock_trade(password=None, password_md5=None)`\n- 交易锁定：`lock_trade(password=None, password_md5=None)`\n- 预检：`run_preflight()`\n- 行情拉取：`get_stock_basicinfo()`、`get_market_state()`、`get_market_snapshot()`、`get_cur_kline()`、`request_history_kline()`、`get_rt_ticker()`\n- 行情统一启动：`start_quote_stream()`、`start_orderbook_stream()`\n- 下单：`submit_order(...)`\n- 改单/撤单：`modify_order(...)`、`cancel_order(...)`、`cancel_all_orders(...)`\n- 策略运行：`run_strategy(...)`\n- 策略辅助：状态、交易锁、交易时段判断、回调 payload 解析\n\n## 当前行为说明\n- `submit_order` 必须显式传入 `acc_id` 和 `trd_env`（`REAL` / `SIMULATE`）。\n- `get_account_info` 每次调用都会覆盖写入 `json/account_info.json`。\n- `unlock_trade` / `lock_trade` 支持 MD5 密码：\n  - 优先使用 `password_md5`\n  - 若仅提供明文 `password`，会在运行时自动转 MD5 后调用富途接口\n- 拉取型 quote 函数会在返回后自动关闭 quote context。\n- trade/account 对外函数会在返回后自动关闭各自 context。\n- 订阅/回调模式不会自动关闭 quote context，调用方结束时应显式 `close_quote_service()`。\n- `modify_order` / `cancel_order` / `cancel_all_orders` 会自行重新初始化交易 context，不依赖上一次调用留下的连接。\n\n## 安装\n### 方式 A：作为 ClawHub Skill 安装（推荐给 Agent 用户）\n不需要手动下载整个仓库，直接安装 skill 文件夹即可：\n```bash\nclawhub install futu-trading-bot\n```\n\n安装完成后，在该 skill 目录中创建虚拟环境并安装依赖（否则无法 `import` / 调用）：\n```bash\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\npip install -e .\n```\n\n### 方式 B：从 GitHub 源码安装（推荐给开发者）\n如果你是要开发/改代码，直接 clone 本仓库后：\n```bash\npip install -r requirements.txt\n```\n\n推荐（开发环境）：\n```bash\npip install -e .\n```\n安装后可直接 `import quote_service/trade_service/account_manager/config_manager`，\n无需再手动设置 `PYTHONPATH` 或在脚本里写 `sys.path`。\n\n额外可直接导入：\n- `preflight_check`\n- `strategy_runtime`\n- `strategy`\n\n## 配置\n配置文件路径：`json/config.json`\n\n最小模板：\n```json\n{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"\",\n    \"trade_password_md5\": \"\",\n    \"default_env\": \"SIMULATE\"\n  }\n}\n```\n\n说明：\n- `trade_password_md5` 优先级高于 `trade_password`\n- `json/config.json` 含敏感信息，已建议加入 `.gitignore`\n- 若 `json/config.json` 不存在，代码会优先回退到 `json/config_example.json`，也兼容旧命名 `json/config.example.json`\n\n## 示例\n```python\nfrom preflight_check import run_preflight\nfrom account_manager import get_account_info, unlock_trade, lock_trade\nfrom trade_service import submit_order\n\nprint(run_preflight())\nprint(get_account_info())\nprint(unlock_trade())  # 使用配置密码（支持MD5）\n\nprint(submit_order(\n    code=\"HK.00700\",\n    side=\"BUY\",\n    qty=200,\n    price=150,\n    order_type=\"NORMAL\",\n    acc_id=6017237,\n    trd_env=\"SIMULATE\"\n))\n\nprint(lock_trade())  # 用完建议锁回去\n```\n\n## 实时行情回调示例\n```python\nfrom quote_service import start_quote_stream, unsubscribe_all, close_quote_service\nfrom strategy_runtime import run_strategy\nfrom strategy import StrategyState, TradeGuard, extract_latest_price\n\nstate = StrategyState()\nguard = TradeGuard()\n\ndef on_quote(payload):\n    price = extract_latest_price(payload, code=\"HK.00700\")\n    if price is None:\n        return\n    with guard.locked():\n        state.current_price = price\n        print(\"latest price:\", price)\n\nstart_quote_stream([\"HK.00700\"], on_quote)\nrun_strategy(\n    pid_file=\"/tmp/futu_strategy.pid\",\n    cleanup_callbacks=[unsubscribe_all, close_quote_service],\n)\n```\n\n## 运行要求\n- 本机已安装并运行 Futu OpenD\n- OpenD 地址与 `json/config.json` 一致（默认 `127.0.0.1:11111`）\n- 真实交易前先确认账户已解锁且参数正确\n- 若在 OpenClaw/Codex 等受限环境中运行，建议先执行 `PYTHONPATH=src python -m preflight_check`\n- 若预检提示日志目录或 OpenD 访问受限，请改用 `host/elevated` 模式\n\nFile v1.0.7:_meta.json\n\n{\n  \"ownerId\": \"kn79d46ahs4v5syfeh8jjzqf7d81y7rr\",\n  \"slug\": \"futu-trading-bot\",\n  \"version\": \"1.0.7\",\n  \"publishedAt\": 1774319399800\n}\n\nFile v1.0.7:docs/account.md\n\n# Account Manager 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/account_manager.py`\n\n## 概述\n账户模块用于：\n- 查询账户列表\n- 解锁交易权限\n- 锁定交易权限\n\n并提供便捷函数供脚本/LLM 直接调用。\n\n## 对外接口\n\n### `get_account_info()`\n```python\nget_account_info() -> Dict[str, Any]\n```\n\n行为：\n- 调用富途 `get_acc_list()`。\n- 返回账户列表结构：`accounts`。\n- 每次调用都会覆盖写本地文件：`json/account_info.json`。\n\n成功返回示例：\n```python\n{\n  \"success\": True,\n  \"accounts\": [\n    {\n      \"account_id\": \"2817...\",\n      \"account_type\": \"REAL\",\n      \"market\": \"['HK', 'US']\",\n      \"acc_type\": \"MARGIN\",\n      \"security_firm\": \"FUTUSECURITIES\",\n      \"sim_acc_type\": \"N/A\",\n      \"acc_status\": \"ACTIVE\"\n    }\n  ],\n  \"error_msg\": None\n}\n```\n\n### `unlock_trade(password=None, password_md5=None)`\n```python\nunlock_trade(\n    password: Optional[str] = None,\n    password_md5: Optional[str] = None\n) -> Dict[str, Any]\n```\n\n密码优先级：\n1. 显式参数 `password_md5`\n2. 显式参数 `password`（运行时自动转 MD5）\n3. 配置 `trade_password_md5`\n4. 配置 `trade_password`（运行时自动转 MD5）\n\n### `lock_trade(password=None, password_md5=None)`\n```python\nlock_trade(\n    password: Optional[str] = None,\n    password_md5: Optional[str] = None\n) -> Dict[str, Any]\n```\n\n实现调用：\n- 富途 `unlock_trade(..., is_unlock=False)`\n\n## 统一返回格式\n```python\n{\n  \"success\": bool,\n  \"error_msg\": Optional[str]\n}\n```\n\n## 本地文件输出\n`get_account_info()` 会写入：\n- 文件：`json/account_info.json`\n- 策略：每次覆盖\n- 结构：\n```json\n{\n  \"updated_at\": \"2026-03-06T14:44:51\",\n  \"data\": { \"...\": \"...\" }\n}\n```\n\n## 使用示例\n```python\nfrom account_manager import get_account_info, unlock_trade, lock_trade\n\nprint(get_account_info())\nprint(unlock_trade())  # 使用配置中的密码或MD5\nprint(lock_trade())    # 用完建议锁回\n```\n\n## 注意事项\n- 依赖 OpenD 连接可用。\n- 明文密码和 MD5 密码都属于敏感信息，均应避免泄露。\n- 对外函数返回后会显式关闭账户相关 context，避免 SDK 线程阻止进程退出。\n\nFile v1.0.7:docs/config.md\n\n# Config Manager 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/config_manager.py`\n\n## 作用\n统一加载并提供项目配置（富途连接参数、交易密码、日志参数）。\n\n## 配置文件读取规则\n1. 优先读取：`json/config.json`\n2. 回退读取：`json/config_example.json`（存在时）\n3. 兼容读取：`json/config.example.json`（旧命名存在时）\n4. 若都不存在，抛出 `FileNotFoundError`\n\n## 配置示例\n```json\n{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"\",\n    \"trade_password_md5\": \"\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}\n```\n\n## 默认值（缺省字段自动补全）\n- `host`: `127.0.0.1`\n- `port`: `11111`\n- `security_firm`: `FUTUSECURITIES`\n- `trade_password`: `\"\"`\n- `trade_password_md5`: `\"\"`\n- `default_env`: `SIMULATE`\n\n## 主要接口\n- `get_futu_config()`\n- `get_host()`\n- `get_port()`\n- `get_security_firm()`\n- `get_trade_password()`\n- `get_trade_password_md5()`\n- `get_default_env()`\n- `get_default_env_str()`\n\n## 与其他模块关系\n- `account_manager` 使用本模块读取主机、端口、券商、交易密码。\n- `trade_service` 使用本模块读取主机、端口、券商。\n\n## 安全建议\n- `json/config.json` 不应入库，需加入 `.gitignore`。\n- 使用最小权限：`chmod 600 json/config.json`。\n- 不在日志中输出真实密码或 MD5 值。\n\nFile v1.0.7:docs/development_plan.md\n\n你说得对，富途的行情接口确实很多。不过别担心，我们不需要一次性封装所有接口。根据你之前开发交易模块的经验，我们可以采用“**先核心，后扩展，按需封装**”的策略。\n\n下面我帮你梳理一个清晰的开发路线图，你可以根据实际需要决定优先实现哪些部分。\n\n### 📈 行情模块封装路线图\n\n#### **第一阶段：核心基础（必须实现）**\n这是所有行情功能的基石，也是你之前交易模块中已经用到的部分。\n1.  **连接管理**：封装 `OpenQuoteContext` 的创建与关闭，沿用交易模块的延迟初始化模式。\n2.  **基础数据获取**：\n    *   **`get_stock_basicinfo`**：获取股票代码、每手股数等基本信息。你的交易模块中已经需要这个接口来校验下单数量。\n    *   **`get_market_state`**：获取市场状态（如是否在交易中），这对判断能否下单很有用。\n\n#### **第二阶段：实时行情订阅（核心功能）**\n这是为了构建实时监控或自动交易策略的基础。\n1.  **订阅管理**：封装 `subscribe`、`unsubscribe`、`unsubscribe_all`、`query_subscription` 四个接口，实现订阅状态的统一管理。\n2.  **推送回调**：\n    *   **报价推送 (`StockQuoteHandlerBase`)**：实时获取价格变动，最常用。\n    *   **摆盘推送 (`OrderBookHandlerBase`)**：如果需要监控深度行情。\n    你可以先实现报价推送，因为这是最基本的需求。\n\n#### **第三阶段：主动数据拉取（常用功能）**\n当需要一次性获取当前数据快照时使用。\n1.  **市场快照 (`get_market_snapshot`)**：最常用的“看一眼”接口，能一次性获取最新价、涨跌幅、成交量等核心数据。\n2.  **K线数据 (`get_cur_kline` 或 `request_history_kline`)**：用于技术分析或展示图表。\n3.  **实时逐笔 (`get_rt_ticker`)**：如果需要监控每一笔成交。\n\n#### **第四阶段：进阶数据（按需扩展）**\n这些接口用于特定的策略或分析，可以根据你的实际需求逐步添加。\n*   **全市场筛选 (`get_stock_filter`)**：用于选股策略。\n*   **板块数据 (`get_plate_stock`, `get_plate_list`)**：分析板块轮动。\n*   **资金流向 (`get_capital_flow`)**：观察主力资金动向。\n*   **自选股管理 (`get_user_security` 等)**：如果你需要管理用户的股票池。\n\n### 💡 给你的具体建议\n\n1.  **先从交易模块中已有的依赖开始**：你的 `trade_service` 已经用到了 `get_market_snapshot` 来获取每手股数，可以优先把它完整封装起来。\n2.  **遵循“先测试，后封装”原则**：就像你之前做的，先用一个简单的测试脚本调通一个接口（比如 `get_market_snapshot`），理解它的输入输出，然后再进行封装。\n3.  **统一设计风格**：延续交易模块的设计模式：一个内部服务类 (`_HKQuoteService`) + 对外暴露的简洁函数。返回格式也保持一致 `{\"success\": bool, \"data\": ..., \"message\": str}`。\n4.  **管理好订阅状态**：在服务类内部维护一个订阅列表，避免重复订阅，也便于取消订阅。\n\n你可以先从第一阶段和第三阶段开始，搭建起行情模块的骨架。当有具体的策略需求时，再有针对性地封装第二阶段或其他进阶接口。这样既不会一开始就被庞大的接口列表吓倒，也能快速用起来。\n\nFile v1.0.7:docs/quote.md\n\n# Quote Service 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/quote_service.py`\n\n## 概述\n行情模块负责：\n- 基础行情拉取\n- K 线与逐笔拉取\n- 行情订阅与回调\n- 统一启动实时报价/摆盘监听\n\n## 拉取型函数\n- `get_stock_basicinfo(...)`\n- `get_market_state(...)`\n- `get_market_snapshot(...)`\n- `get_cur_kline(...)`\n- `request_history_kline(...)`\n- `get_rt_ticker(...)`\n\n说明：\n- 拉取型函数返回后会显式关闭 quote context。\n- `get_cur_kline(...)` 和 `get_rt_ticker(...)` 在遇到“请先订阅”时会自动补订阅后重试。\n\n## 订阅/回调型函数\n- `set_quote_callback(callback)`\n- `set_orderbook_callback(callback)`\n- `subscribe(...)`\n- `unsubscribe(...)`\n- `unsubscribe_all()`\n- `query_subscription()`\n\n说明：\n- 这些函数不会自动关闭 quote context。\n- 用于长连接 / 回调推送场景。\n- 调用方结束时应显式 `close_quote_service()`。\n\n## 统一启动函数\n\n### `start_quote_stream(...)`\n完成两步：\n1. 注册 `QUOTE` 回调\n2. 发起 `QUOTE` 订阅\n\n### `start_orderbook_stream(...)`\n完成两步：\n1. 注册 `ORDER_BOOK` 回调\n2. 发起 `ORDER_BOOK` 订阅\n\n这两个函数适合策略脚本，避免把“设置回调 + 订阅”拆开写。\n\n## 使用示例\n```python\nfrom quote_service import start_quote_stream, unsubscribe_all, close_quote_service\n\ndef on_quote(payload):\n    print(payload)\n\nstart_quote_stream([\"HK.00700\"], on_quote)\n\n# done\nunsubscribe_all()\nclose_quote_service()\n```\n\nFile v1.0.7:docs/strategy.md\n\n# Strategy Helpers 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n- `src/strategy.py`\n- `src/strategy_runtime.py`\n\n## 目标\n为策略脚本提供轻量辅助，而不是复杂框架。\n\n## `strategy.py`\n提供三类能力：\n\n1. 运行状态\n- `StrategyState`\n\n2. 并发保护\n- `TradeGuard`\n\n3. 运行辅助判断\n- `in_trading_window(...)`\n- `trading_window_status(...)`\n- `cooldown_elapsed(...)`\n- `holding_timeout_exceeded(...)`\n\n4. 回调 payload 解析\n- `extract_callback_rows(payload)`\n- `filter_rows_by_code(rows, code)`\n- `extract_latest_price(payload, code=None, field=\"last_price\")`\n\n## `strategy_runtime.py`\n提供：\n- `run_strategy(...)`\n\n职责只包括：\n- PID 文件管理\n- 防重复启动\n- `SIGINT` / `SIGTERM` 清理\n- 保持进程运行\n\n## 推荐使用方式\n1. 先用 `start_quote_stream(...)` 或 `start_orderbook_stream(...)` 建立订阅\n2. 在回调中用 `extract_latest_price(...)` 等辅助解析行情\n3. 用 `StrategyState` 和 `TradeGuard` 管理策略状态\n4. 最后调用 `run_strategy(...)` 保持进程运行并处理退出清理\n\nFile v1.0.7:docs/trade.md\n\n# Trade Service 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/trade_service.py`\n\n## 概述\n交易模块负责下单、改单、撤单与全部撤单，内部包含参数校验和富途 API 调用。\n\n## 设计原则\n- 交易环境不做内部管理，调用方必须显式传入。\n- 不提供账户环境切换接口（无 `switch_account_env`）。\n- 不做幂等去重校验。\n\n## 对外接口\n\n### `submit_order(...)`\n```python\nsubmit_order(\n    code: str,\n    side: str,\n    qty: int,\n    acc_id: int,\n    trd_env: str,\n    price: Optional[float] = None,\n    order_type: str = \"NORMAL\",\n    aux_price: Optional[float] = None,\n    remark: Optional[str] = None,\n    time_in_force: str = \"DAY\",\n) -> Dict[str, Any]\n```\n\n说明：\n- `acc_id` 必传。\n- `trd_env` 必传，仅支持 `REAL`、`SIMULATE`。\n- `code` 目前按港股校验：必须以 `HK.` 开头。\n- 会校验下单数量是否为 `lot_size` 整数倍。\n\n### `modify_order(...)`\n```python\nmodify_order(\n    op: str,\n    order_id: str,\n    trd_env: str,\n    qty: Optional[float] = None,\n    price: Optional[float] = None,\n    acc_id: int = 0,\n    **kwargs,\n) -> Dict[str, Any]\n```\n\n`op` 支持：\n- `NORMAL`\n- `CANCEL`\n- `DISABLE`\n- `ENABLE`\n- `DELETE`\n\n### `cancel_order(...)`\n```python\ncancel_order(order_id: str, trd_env: str, acc_id: int = 0) -> Dict[str, Any]\n```\n\n### `cancel_all_orders(...)`\n```python\ncancel_all_orders(trd_env: str, acc_id: int = 0, trdmarket: Optional[str] = None) -> Dict[str, Any]\n```\n\n### `close_trade_service()`\n```python\nclose_trade_service() -> None\n```\n用于显式关闭内部交易/行情 context。一般情况下，对外交易函数已经会在返回后自动关闭。\n\n## 下单校验流程（`submit_order`）\n1. 订单模型参数校验（Pydantic）。\n2. 股票代码格式校验。\n3. 获取并校验 `lot_size`。\n4. 价格、数量、触发价等基础校验。\n5. 通过市场快照验证股票可用。\n6. 调用富途 `place_order`。\n\n## 连接生命周期\n- `submit_order`、`modify_order`、`cancel_order`、`cancel_all_orders` 返回后都会显式关闭内部 context。\n- `modify_order` 和 `cancel_all_orders` 会在调用前自行确保 context 已初始化，因此不依赖此前的 `submit_order` 调用状态。\n- 这种设计适合一次性脚本与 agent 调用，避免 Futu SDK 内部线程阻止进程退出。\n\n## 返回格式\n统一返回字典，至少包含：\n- `success`: 是否成功\n- `message`: 结果描述\n\n成功下单通常包含：\n- `order_id`\n- `lot_size`\n- `trd_env`\n\n## 使用示例\n```python\nfrom trade_service import submit_order\n\nresult = submit_order(\n    code=\"HK.00700\",\n    side=\"BUY\",\n    qty=200,\n    acc_id=6017237,\n    trd_env=\"SIMULATE\",\n    price=150,\n    order_type=\"NORMAL\",\n)\nprint(result)\n```\n\n## 注意事项\n- `REAL` 环境会尝试真实交易，请先确认交易权限状态。\n- 真实交易密码解锁/锁定由 `account_manager` 处理，不在本模块内自动完成。\n\nFile v1.0.7:skill-card.md\n\n## Description: <br>\nUse Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[jeffersonling1217-png](https://clawhub.ai/user/jeffersonling1217-png) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal agent users and developers use this skill to configure Futu OpenD access, inspect accounts and HK market quotes, place or manage Futu orders, and run simple trading strategy scripts from natural-language requests. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill can unlock Futu accounts and place, modify, or cancel real-money orders. <br>\nMitigation: Keep SIMULATE as the default trading environment and require explicit human approval before unlocking REAL trading or submitting, modifying, or canceling orders. <br>\nRisk: The skill can cancel all orders and run background strategy processes. <br>\nMitigation: Confirm account, environment, symbol, quantity, and order scope before calling cancel_all_orders or launching long-running strategy scripts; record PID and log paths for monitoring and stop actions. <br>\nRisk: Configuration and generated account cache files may contain sensitive trading credentials or account data. <br>\nMitigation: Avoid plaintext trade passwords, prefer protected credential handling, keep config and account_info.json out of shared storage, and restrict file permissions for local configuration. <br>\n\n\n## Reference(s): <br>\n- [ClawHub release page](https://clawhub.ai/jeffersonling1217-png/futu-trading-bot) <br>\n- [README](README.md) <br>\n- [Account Manager documentation](docs/account.md) <br>\n- [Config Manager documentation](docs/config.md) <br>\n- [Quote Service documentation](docs/quote.md) <br>\n- [Trade Service documentation](docs/trade.md) <br>\n- [Strategy Helpers documentation](docs/strategy.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown guidance with Python snippets, shell commands, JSON configuration, and function call patterns] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May produce Python strategy scripts, process commands, account or quote summaries, order-management guidance, and local configuration instructions.] <br>\n\n## Skill Version(s): <br>\n1.0.7 (source: ClawHub release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v1.0.7:json/config_example.json\n\n{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"YOUR PASSWORD\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}\n\nFile v1.0.7:pyproject.toml\n\n[build-system]\nrequires = [\"setuptools>=68\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"futu-trade-bot-skills\"\nversion = \"0.1.0\"\ndescription = \"Futu Trade Bot Skills modules for account, trade, and quote services.\"\nreadme = \"README.md\"\nrequires-python = \">=3.10\"\ndependencies = [\n  \"futu-api\",\n  \"pydantic>=2,<3\",\n]\n\n[tool.setuptools]\npy-modules = [\"account_manager\", \"config_manager\", \"trade_service\", \"quote_service\", \"preflight_check\", \"strategy_runtime\", \"strategy\"]\n\n[tool.setuptools.package-dir]\n\"\" = \"src\"\n\nArchive v1.0.6: 13 files, 32067 bytes\n\nFiles: docs/account.md (2101b), docs/config.md (1462b), docs/trade.md (2389b), json/config_example.json (274b), pyproject.toml (506b), requirements.txt (24b), SKILL.md (15425b), src/account_manager.py (13925b), src/config_manager.py (7404b), src/preflight_check.py (8558b), src/quote_service.py (18390b), src/trade_service.py (33929b), _meta.json (135b)\n\nFile v1.0.6:SKILL.md\n\n---\nname: futu-trading-bot\ndescription: Use Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.\nlicense: MIT-0\nmetadata:\n  openclaw:\n    emoji: \"📈\"\n    requires:\n      bins: [\"python3\", \"pip\"]\n---\n\n# Futu Trade Bot Skills 📈\n\n## 🎯 Overview / 概述\n\n**English Version:**\nA trading bot skill based on Futu OpenAPI that enables natural language trading. This skill encapsulates Futu's market quote and order execution APIs, allowing agents to perform real-time trading operations through simple commands or scripts. Perfect for implementing natural language trading strategies and automated workflows.\n\n**Important**: Always use the encapsulated functions provided in this skill (e.g., `submit_order`, `get_market_snapshot`). **Never call Futu SDK functions directly** (`ctx.place_order`, `ctx.get_market_snapshot`), as this will bypass connection management, parameter validation, and error handling, leading to unpredictable failures and resource leaks.\n\n**中文版本:**\n基于富途牛牛API接口的交易机器人技能，帮助用户用自然语言进行交易。本技能已将富途牛牛的行情报价、下单交易等功能做了完整封装，可供智能助手随时调用。建议通过命令行或脚本来实现自然语言的策略生成和交易执行。\n\n**重要提示**：请始终使用本技能提供的封装函数（如 `submit_order`、`get_market_snapshot`）。**切勿直接调用富途SDK的原始函数**（例如 `ctx.place_order`），否则会绕过连接管理、参数校验和错误处理，导致不可预料的失败和资源泄漏。\n\n---\n\n## When to Use This Skill / 使用场景\n\nUse this skill when the user asks in natural language, for example:\n\n- **账户相关**：“查一下我的账户余额”、“解锁交易”、“锁定账户”、“看看我有哪些账户”\n- **行情查询**：“腾讯现在多少钱？”、“查一下港交所的实时报价”、“帮我看看美团今天的K线图”\n- **数据拉取**：“获取腾讯的历史K线数据”、“拉取最近10笔成交”\n- **订阅与回调**：“实时监控腾讯的报价”、“给我推送腾讯的逐笔成交”\n- **下单交易**：“帮我买100股腾讯，限价350”、“卖出200股阿里”、“撤单”、“把订单价格改到355”\n- **策略运行**：\n  - “帮我写一个区间策略，监控腾讯，低于540买入，高于550卖出”\n  - “启动这个策略”\n  - “我的策略跑得怎么样了？”\n  - “停止我的策略”\n\n**Note to agent**: When the user expresses any of these intents, you should use the encapsulated functions provided in this skill (e.g., `get_account_info`, `get_market_snapshot`, `submit_order`, etc.). **Never call Futu SDK functions directly** – always go through the skill's API.\n\n## Quick Start / 快速开始\n\n**Prerequisites / 前提条件:**\n- Ensure Futu OpenD is running and HK quote entitlement is available.\n- 确保富途OpenD正在运行且拥有港股行情权限。\n- When running inside a restricted agent sandbox (for example OpenClaw/Codex exec), prefer `host` / `elevated` mode.\n- The Futu Python SDK may access local OpenD resources during import, including the user log directory under `~/.com.futunn.FutuOpenD/Log`, so restricted sandboxes may fail before business functions are called.\n- 如果在受限的 agent 沙箱中运行（例如 OpenClaw/Codex exec），优先使用 `host` / `elevated` 模式。\n- 富途 Python SDK 在导入阶段就可能访问本机 OpenD 相关资源，包括 `~/.com.futunn.FutuOpenD/Log` 下的日志目录；因此受限沙箱可能会在业务函数执行前就失败。\n\n**Setup Steps / 安装步骤:**\n1. Install this skill via ClawHub (if not installed yet):\n   ```bash\n   clawhub install futu-trading-bot\n   ```\n\n2. Enter the skill folder (default OpenClaw workspace path):\n   ```bash\n   cd ~/.openclaw/workspace/skills/futu-trading-bot\n   ```\n   If you installed to a different location, `cd` into that folder instead.\n\n3. Create virtual environment (recommended):\n   ```bash\n   python3 -m venv .venv\n   source .venv/bin/activate\n   ```\n\n4. Install package:\n   ```bash\n   pip install -e .\n   ```\n\n5. Configure credentials:\n   ```bash\n   cp json/config_example.json json/config.json\n   # Edit json/config.json with your Futu credentials\n   # 编辑json/config.json填写你的富途账户信息\n   ```\n\n## 依赖项\n\n本技能通过 `pip install -e .` 自动安装以下核心 Python 包：\n- `futu-api`（富途 SDK）\n- `pydantic`（数据校验）\n\n更多依赖请以 `pyproject.toml` / `requirements.txt` 为准。\n\n## Module Map\n\n- **Account**: `account_manager`\n  - `get_account_info()`\n  - `unlock_trade(password=None, password_md5=None)`\n  - `lock_trade()`\n- **Quote**: `quote_service`\n  - Stage 1: `get_stock_basicinfo`, `get_market_state`\n  - Stage 2: `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, callbacks\n  - Stage 3: `get_market_snapshot`, `get_cur_kline`, `request_history_kline`, `get_rt_ticker`\n- **Trade**: `trade_service`\n  - `submit_order`, `modify_order`, `cancel_order`, `cancel_all_orders`\n\n## Standard Workflow\n\n1. Run `preflight_check` first to verify config, OpenD connectivity, and sandbox/runtime readiness.\n2. Call `get_account_info()` and select target account (get `acc_id`).\n3. Pull quote/snapshot for the target symbol (default HK use case: `HK.00700`).\n4. For real trading, call `unlock_trade(...)` (password from config or input).\n5. Submit or manage orders with explicit `acc_id` and `trd_env`.\n6. After real operation, call `lock_trade()` if needed.\n\n## Connection Lifecycle\n\n- Pull-style quote functions such as `get_market_snapshot`, `get_stock_basicinfo`, `get_market_state`, `get_cur_kline`, `request_history_kline`, and `get_rt_ticker` now close their quote context automatically after returning.\n- Trade functions such as `submit_order`, `modify_order`, and `cancel_all_orders` now close their trade/quote contexts automatically after returning.\n- Account functions such as `get_account_info`, `unlock_trade`, and `lock_trade` now close their contexts automatically after returning.\n- Subscription/callback flows keep the quote context open on purpose. For `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, `set_quote_callback`, and `set_orderbook_callback`, call `close_quote_service()` explicitly when you are done with the session.\n\n## Canonical Imports\n\n```python\n# Always use these import paths – do not import from futu directly\nfrom preflight_check import run_preflight\nfrom account_manager import get_account_info, unlock_trade, lock_trade\nfrom quote_service import (\n    get_stock_basicinfo, get_market_state, get_market_snapshot,\n    get_cur_kline, request_history_kline, get_rt_ticker,\n    subscribe, unsubscribe, unsubscribe_all, query_subscription,\n    set_quote_callback, set_orderbook_callback\n)\nfrom trade_service import submit_order, modify_order, cancel_order, cancel_all_orders\n```\n\n## Account Usage\n\n### Preflight\n```python\npreflight = run_preflight()\nif not preflight[\"success\"]:\n    print(preflight)\n    raise SystemExit(\"Preflight failed\")\n```\n\n```python\n# Get list of accounts\ninfo = get_account_info()\nif info['success']:\n    accounts = info['accounts']\n    print(accounts)\n\n# Unlock trade (uses password from config or provided)\nunlock_trade()  # will prompt for password if not configured\n# Or with explicit password:\n# unlock_trade(password=\"your_password\")\n\n# Lock trade\nlock_trade()\n```\n\n## Quote Usage\n\n### Basic Info / Market State\n```python\nget_stock_basicinfo(market=\"HK\", sec_type=\"STOCK\", code_list=[\"HK.00700\"])\nget_market_state([\"HK.00700\"])\n```\n\n### Snapshot (no subscription needed)\n```python\nsnap = get_market_snapshot([\"HK.00700\"])\nif snap['success']:\n    price = snap['data'][0]['last_price']\n```\n\n### K-Line\n```python\n# Current K-line (requires subscription, will auto-subscribe if needed)\nkline = get_cur_kline(code=\"HK.00700\", num=5, ktype=\"K_DAY\", autype=\"QFQ\")\n\n# Historical K-line\nhist = request_history_kline(\n    code=\"HK.00700\",\n    start=\"2026-02-20\",\n    end=\"2026-03-06\",\n    ktype=\"K_DAY\"\n)\n```\n\n### Ticker\n```python\ntickers = get_rt_ticker(code=\"HK.00700\", num=10)\n```\n\n### Subscription & Callbacks\n```python\ndef on_quote(payload):\n    print(payload)\n\nset_quote_callback(on_quote)\nsubscribe([\"HK.00700\"], [\"QUOTE\"], is_first_push=True, subscribe_push=True)\nquery_subscription()\nunsubscribe([\"HK.00700\"], [\"QUOTE\"])\nunsubscribe_all()\nclose_quote_service()\n```\n\n## Trade Usage\n\n```python\n# Submit an order\nresult = submit_order(\n    code=\"HK.00700\",\n    side=\"BUY\",\n    qty=200,\n    acc_id=6017237,               # from get_account_info\n    trd_env=\"SIMULATE\",            # or \"REAL\"\n    price=150,                     # required for LIMIT order\n    order_type=\"NORMAL\",\n)\n\n# Modify order (change price/quantity)\nmodify_order(\n    op=\"NORMAL\",\n    order_id=\"123456789\",\n    trd_env=\"SIMULATE\",\n    price=151,\n    qty=200,\n    acc_id=6017237\n)\n\n# Cancel a single order\ncancel_order(order_id=\"123456789\", trd_env=\"SIMULATE\", acc_id=6017237)\n\n# Cancel all orders\ncancel_all_orders(trd_env=\"SIMULATE\", acc_id=6017237)\n```\n\n## Running a Background Trading Strategy (Using System Tools)\n\nThis skill does not manage long-running processes internally. Instead, you (the agent) should use system tools (e.g., `exec`, `write`, `kill`) to run strategy scripts in the background. This keeps the skill simple and leverages the platform's process management.\n\n### 4.1 Workflow for Background Strategies\n\n1. **Run preflight first** with `PYTHONPATH=src python -m preflight_check`.\n2. If preflight reports sandbox/log-directory restrictions, rerun in `host` / `elevated` mode before using quote/trade functions.\n3. **Generate a Python script** based on user's natural language request, using the encapsulated functions from this skill (e.g., `get_market_snapshot`, `submit_order`).\n4. **Save the script** to a temporary file (using the `write` tool or similar).\n5. **Launch the script as a background process** using the `exec` tool, redirecting output to a log file.\n6. **Record the process ID (PID)** and log file path for future monitoring.\n7. **Monitor/stop** using system tools (`ps`, `kill`, `cat`).\n\n### 4.2 Natural Language Triggers\n\n| User Request | Agent Action |\n|--------------|--------------|\n| “Start a strategy to monitor Tencent, buy below 540, sell above 550” | Generate script → save → launch with `exec` → return PID and log path |\n| “How is my strategy doing?” | Read log file (e.g., `tail -n 20 logfile`) → summarize |\n| “Stop my strategy” | Kill process using PID via `kill` tool |\n\n### 4.3 Script Template (for Agent Reference)\n\nWhen generating a strategy script, use the following template. It handles signals, logging, and state persistence correctly.\n\n```python\n#!/usr/bin/env python3\nimport sys\nimport time\nimport json\nimport os\nimport signal\nimport logging\nfrom pathlib import Path\n\n# If you installed the skill with `pip install -e .`, you can import modules directly.\n# Only use sys.path/PYTHONPATH hacks when you didn't install the package.\n\nfrom trade_service import submit_order\nfrom quote_service import get_market_snapshot\n\n# ===== Strategy parameters – fill by agent =====\n# Replace these placeholders with your own strategy settings.\nSYMBOL = \"HK.00700\"\nACC_ID = 0                 # fill from get_account_info()\nTRD_ENV = \"SIMULATE\"       # default to SIMULATE; use REAL only with explicit confirmation\nQTY = 0                    # position sizing / order quantity\nLOG_FILE = Path(\"strategy.log\")\nPID_FILE = Path(\"strategy.pid\")\n# ===============================================\n\nlogging.basicConfig(\n    filename=LOG_FILE,\n    level=logging.INFO,\n    format='%(asctime)s - %(levelname)s - %(message)s'\n)\n\n# Handle termination signals\ndef handle_exit(signum, frame):\n    logging.info(\"Received signal, stopping strategy\")\n    sys.exit(0)\n\nsignal.signal(signal.SIGTERM, handle_exit)\nsignal.signal(signal.SIGINT, handle_exit)\n\n# Write PID file\nwith open(PID_FILE, \"w\") as f:\n    f.write(str(os.getpid()))\n\nlogging.info(f\"Strategy started: {SYMBOL}\")\n\ntry:\n    while True:\n        snap = get_market_snapshot([SYMBOL])\n        if not snap[\"success\"]:\n            logging.error(f\"Quote failed: {snap['message']}\")\n            time.sleep(60)\n            continue\n        price = snap[\"data\"][0][\"last_price\"]\n        logging.info(f\"Current price: {price}\")\n\n        # --- Insert your strategy logic here ---\n        # Decide whether to trade based on your own signals/logic, then call submit_order(...).\n\n        time.sleep(60)   # check every minute\nexcept Exception as e:\n    logging.exception(\"Strategy crashed\")\nfinally:\n    if PID_FILE.exists():\n        PID_FILE.unlink()\n```\n\n### 4.4 Agent Execution Steps\n\n**User**: “Start a range strategy for Tencent, buy below 540, sell above 550.”\n\n**Agent**:\n1. **Get account ID** via `get_account_info()`.\n2. **Generate script** using the template above, filling in parameters.\n3. **Save script** to a file, e.g., `range_00700.py`, using `write` tool.\n4. **Launch background process** using `exec`:\n   ```bash\n   cd /path/to/workspace\n   nohup .venv/bin/python range_00700.py > strategy.out 2>&1 &\n   ```\n   (Capture the PID from output.)\n5. **Record** PID and log path.\n6. **Reply**: “Strategy started. PID: 12345, log file: strategy_00700.log. You can check status or stop it anytime.”\n\n### 4.5 Check Status\n\n**User**: “How is my strategy doing?”\n\n**Agent**:\n- Read last lines of log: `tail -n 20 strategy_00700.log`.\n- Check if process still running: `ps -p 12345`.\n- Summarize: “Strategy is running, last price was 542.5 at 10:30.”\n\n### 4.6 Stop Strategy\n\n**User**: “Stop my strategy.”\n\n**Agent**:\n- Send SIGTERM: `kill 12345`.\n- Verify process ended, clean up PID file if needed.\n- Reply: “Strategy stopped.”\n\n---\n\n## Error Handling\n\n- All functions return a dictionary with at least `success` (bool) and `message` (str).\n- On success, additional fields like `data` or `order_id` may be present.\n- Always check `success` first before using other fields.\n\nExample:\n```python\nresult = submit_order(...)\nif result[\"success\"]:\n    print(f\"Order ID: {result['order_id']}\")\nelse:\n    print(f\"Error: {result['message']}\")\n```\n\nIf OpenD connection fails, recheck:\n- OpenD is running (check port 11111 with `lsof -i :11111`)\n- Host/port in `config.json` matches OpenD\n- Account has necessary permissions\n\nIf the skill fails before quote/trade functions are even called, recheck:\n- Whether the current agent/tool is running in a restricted sandbox\n- Whether you should rerun in `host` / `elevated` mode\n- Whether the runtime can access the local Futu OpenD log directory under `~/.com.futunn.FutuOpenD/Log`\n- Run `PYTHONPATH=src python -m preflight_check` first and follow its suggestions\n\n## Configuration\n\n- **Config file**: `json/config.json`\n- **Required fields**:\n  - `futu_api.host` (default: 127.0.0.1)\n  - `futu_api.port` (default: 11111)\n  - `futu_api.security_firm` (e.g., `FUTUSECURITIES`)\n- **Password handling**:\n  - Prefer `trade_password_md5` (32‑char lowercase MD5)\n  - Fallback to `trade_password` (will be MD5‑ed at runtime)\n- **Account cache**: `json/account_info.json` (auto‑generated after `get_account_info`)\n\n## 📜 License\n\nThis skill is licensed under **MIT-0** (MIT No Attribution).\n\n---\n\n**Copyright © 2026 jeffersonling1217-png**\n```\n\nFile v1.0.6:_meta.json\n\n{\n  \"ownerId\": \"kn79d46ahs4v5syfeh8jjzqf7d81y7rr\",\n  \"slug\": \"futu-trading-bot\",\n  \"version\": \"1.0.6\",\n  \"publishedAt\": 1774245824887\n}\n\nFile v1.0.6:docs/account.md\n\n# Account Manager 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/account_manager.py`\n\n## 概述\n账户模块用于：\n- 查询账户列表\n- 解锁交易权限\n- 锁定交易权限\n\n并提供便捷函数供脚本/LLM 直接调用。\n\n## 对外接口\n\n### `get_account_info()`\n```python\nget_account_info() -> Dict[str, Any]\n```\n\n行为：\n- 调用富途 `get_acc_list()`。\n- 返回账户列表结构：`accounts`。\n- 每次调用都会覆盖写本地文件：`json/account_info.json`。\n\n成功返回示例：\n```python\n{\n  \"success\": True,\n  \"accounts\": [\n    {\n      \"account_id\": \"2817...\",\n      \"account_type\": \"REAL\",\n      \"market\": \"['HK', 'US']\",\n      \"acc_type\": \"MARGIN\",\n      \"security_firm\": \"FUTUSECURITIES\",\n      \"sim_acc_type\": \"N/A\",\n      \"acc_status\": \"ACTIVE\"\n    }\n  ],\n  \"error_msg\": None\n}\n```\n\n### `unlock_trade(password=None, password_md5=None)`\n```python\nunlock_trade(\n    password: Optional[str] = None,\n    password_md5: Optional[str] = None\n) -> Dict[str, Any]\n```\n\n密码优先级：\n1. 显式参数 `password_md5`\n2. 显式参数 `password`（运行时自动转 MD5）\n3. 配置 `trade_password_md5`\n4. 配置 `trade_password`（运行时自动转 MD5）\n\n### `lock_trade(password=None, password_md5=None)`\n```python\nlock_trade(\n    password: Optional[str] = None,\n    password_md5: Optional[str] = None\n) -> Dict[str, Any]\n```\n\n实现调用：\n- 富途 `unlock_trade(..., is_unlock=False)`\n\n## 统一返回格式\n```python\n{\n  \"success\": bool,\n  \"error_msg\": Optional[str]\n}\n```\n\n## 本地文件输出\n`get_account_info()` 会写入：\n- 文件：`json/account_info.json`\n- 策略：每次覆盖\n- 结构：\n```json\n{\n  \"updated_at\": \"2026-03-06T14:44:51\",\n  \"data\": { \"...\": \"...\" }\n}\n```\n\n## 使用示例\n```python\nfrom account_manager import get_account_info, unlock_trade, lock_trade\n\nprint(get_account_info())\nprint(unlock_trade())  # 使用配置中的密码或MD5\nprint(lock_trade())    # 用完建议锁回\n```\n\n## 注意事项\n- 依赖 OpenD 连接可用。\n- 明文密码和 MD5 密码都属于敏感信息，均应避免泄露。\n\nFile v1.0.6:docs/config.md\n\n# Config Manager 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/config_manager.py`\n\n## 作用\n统一加载并提供项目配置（富途连接参数、交易密码、日志参数）。\n\n## 配置文件读取规则\n1. 优先读取：`json/config.json`\n2. 回退读取：`json/config.example.json`（存在时）\n3. 若都不存在，抛出 `FileNotFoundError`\n\n## 配置示例\n```json\n{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"\",\n    \"trade_password_md5\": \"\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}\n```\n\n## 默认值（缺省字段自动补全）\n- `host`: `127.0.0.1`\n- `port`: `11111`\n- `security_firm`: `FUTUSECURITIES`\n- `trade_password`: `\"\"`\n- `trade_password_md5`: `\"\"`\n- `default_env`: `SIMULATE`\n\n## 主要接口\n- `get_futu_config()`\n- `get_host()`\n- `get_port()`\n- `get_security_firm()`\n- `get_trade_password()`\n- `get_trade_password_md5()`\n- `get_default_env()`\n- `get_default_env_str()`\n\n## 与其他模块关系\n- `account_manager` 使用本模块读取主机、端口、券商、交易密码。\n- `trade_service` 使用本模块读取主机、端口、券商。\n\n## 安全建议\n- `json/config.json` 不应入库，需加入 `.gitignore`。\n- 使用最小权限：`chmod 600 json/config.json`。\n- 不在日志中输出真实密码或 MD5 值。\n\nFile v1.0.6:docs/trade.md\n\n# Trade Service 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/trade_service.py`\n\n## 概述\n交易模块负责下单、改单、撤单与全部撤单，内部包含参数校验和富途 API 调用。\n\n## 设计原则\n- 交易环境不做内部管理，调用方必须显式传入。\n- 不提供账户环境切换接口（无 `switch_account_env`）。\n- 不做幂等去重校验。\n\n## 对外接口\n\n### `submit_order(...)`\n```python\nsubmit_order(\n    code: str,\n    side: str,\n    qty: int,\n    acc_id: int,\n    trd_env: str,\n    price: Optional[float] = None,\n    order_type: str = \"NORMAL\",\n    aux_price: Optional[float] = None,\n    remark: Optional[str] = None,\n    time_in_force: str = \"DAY\",\n) -> Dict[str, Any]\n```\n\n说明：\n- `acc_id` 必传。\n- `trd_env` 必传，仅支持 `REAL`、`SIMULATE`。\n- `code` 目前按港股校验：必须以 `HK.` 开头。\n- 会校验下单数量是否为 `lot_size` 整数倍。\n\n### `modify_order(...)`\n```python\nmodify_order(\n    op: str,\n    order_id: str,\n    trd_env: str,\n    qty: Optional[float] = None,\n    price: Optional[float] = None,\n    acc_id: int = 0,\n    **kwargs,\n) -> Dict[str, Any]\n```\n\n`op` 支持：\n- `NORMAL`\n- `CANCEL`\n- `DISABLE`\n- `ENABLE`\n- `DELETE`\n\n### `cancel_order(...)`\n```python\ncancel_order(order_id: str, trd_env: str, acc_id: int = 0) -> Dict[str, Any]\n```\n\n### `cancel_all_orders(...)`\n```python\ncancel_all_orders(trd_env: str, acc_id: int = 0, trdmarket: Optional[str] = None) -> Dict[str, Any]\n```\n\n## 下单校验流程（`submit_order`）\n1. 订单模型参数校验（Pydantic）。\n2. 股票代码格式校验。\n3. 获取并校验 `lot_size`。\n4. 价格、数量、触发价等基础校验。\n5. 通过市场快照验证股票可用。\n6. 调用富途 `place_order`。\n\n## 返回格式\n统一返回字典，至少包含：\n- `success`: 是否成功\n- `message`: 结果描述\n\n成功下单通常包含：\n- `order_id`\n- `lot_size`\n- `trd_env`\n\n## 使用示例\n```python\nfrom trade_service import submit_order\n\nresult = submit_order(\n    code=\"HK.00700\",\n    side=\"BUY\",\n    qty=200,\n    acc_id=6017237,\n    trd_env=\"SIMULATE\",\n    price=150,\n    order_type=\"NORMAL\",\n)\nprint(result)\n```\n\n## 注意事项\n- `REAL` 环境会尝试真实交易，请先确认交易权限状态。\n- 真实交易密码解锁/锁定由 `account_manager` 处理，不在本模块内自动完成。\n\nFile v1.0.6:json/config_example.json\n\n{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"YOUR PASSWORD\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}\n\nFile v1.0.6:pyproject.toml\n\n[build-system]\nrequires = [\"setuptools>=68\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"futu-trade-bot-skills\"\nversion = \"0.1.0\"\ndescription = \"Futu Trade Bot Skills modules for account, trade, and quote services.\"\nreadme = \"README.md\"\nrequires-python = \">=3.10\"\ndependencies = [\n  \"futu-api\",\n  \"pydantic>=2,<3\",\n]\n\n[tool.setuptools]\npy-modules = [\"account_manager\", \"config_manager\", \"trade_service\", \"quote_service\", \"preflight_check\"]\n\n[tool.setuptools.package-dir]\n\"\" = \"src\"\n\nFile v1.0.6:requirements.txt\n\nfutu-api\npydantic>=2,<3\n\nArchive v1.0.5: 13 files, 32069 bytes\n\nFiles: docs/account.md (2101b), docs/config.md (1462b), docs/trade.md (2389b), json/config_example.json (274b), pyproject.toml (506b), requirements.txt (24b), SKILL.md (15425b), src/account_manager.py (13925b), src/config_manager.py (7404b), src/preflight_check.py (8558b), src/quote_service.py (18390b), src/trade_service.py (33842b), _meta.json (135b)\n\nFile v1.0.5:SKILL.md\n\n---\nname: futu-trading-bot\ndescription: Use Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.\nlicense: MIT-0\nmetadata:\n  openclaw:\n    emoji: \"📈\"\n    requires:\n      bins: [\"python3\", \"pip\"]\n---\n\n# Futu Trade Bot Skills 📈\n\n## 🎯 Overview / 概述\n\n**English Version:**\nA trading bot skill based on Futu OpenAPI that enables natural language trading. This skill encapsulates Futu's market quote and order execution APIs, allowing agents to perform real-time trading operations through simple commands or scripts. Perfect for implementing natural language trading strategies and automated workflows.\n\n**Important**: Always use the encapsulated functions provided in this skill (e.g., `submit_order`, `get_market_snapshot`). **Never call Futu SDK functions directly** (`ctx.place_order`, `ctx.get_market_snapshot`), as this will bypass connection management, parameter validation, and error handling, leading to unpredictable failures and resource leaks.\n\n**中文版本:**\n基于富途牛牛API接口的交易机器人技能，帮助用户用自然语言进行交易。本技能已将富途牛牛的行情报价、下单交易等功能做了完整封装，可供智能助手随时调用。建议通过命令行或脚本来实现自然语言的策略生成和交易执行。\n\n**重要提示**：请始终使用本技能提供的封装函数（如 `submit_order`、`get_market_snapshot`）。**切勿直接调用富途SDK的原始函数**（例如 `ctx.place_order`），否则会绕过连接管理、参数校验和错误处理，导致不可预料的失败和资源泄漏。\n\n---\n\n## When to Use This Skill / 使用场景\n\nUse this skill when the user asks in natural language, for example:\n\n- **账户相关**：“查一下我的账户余额”、“解锁交易”、“锁定账户”、“看看我有哪些账户”\n- **行情查询**：“腾讯现在多少钱？”、“查一下港交所的实时报价”、“帮我看看美团今天的K线图”\n- **数据拉取**：“获取腾讯的历史K线数据”、“拉取最近10笔成交”\n- **订阅与回调**：“实时监控腾讯的报价”、“给我推送腾讯的逐笔成交”\n- **下单交易**：“帮我买100股腾讯，限价350”、“卖出200股阿里”、“撤单”、“把订单价格改到355”\n- **策略运行**：\n  - “帮我写一个区间策略，监控腾讯，低于540买入，高于550卖出”\n  - “启动这个策略”\n  - “我的策略跑得怎么样了？”\n  - “停止我的策略”\n\n**Note to agent**: When the user expresses any of these intents, you should use the encapsulated functions provided in this skill (e.g., `get_account_info`, `get_market_snapshot`, `submit_order`, etc.). **Never call Futu SDK functions directly** – always go through the skill's API.\n\n## Quick Start / 快速开始\n\n**Prerequisites / 前提条件:**\n- Ensure Futu OpenD is running and HK quote entitlement is available.\n- 确保富途OpenD正在运行且拥有港股行情权限。\n- When running inside a restricted agent sandbox (for example OpenClaw/Codex exec), prefer `host` / `elevated` mode.\n- The Futu Python SDK may access local OpenD resources during import, including the user log directory under `~/.com.futunn.FutuOpenD/Log`, so restricted sandboxes may fail before business functions are called.\n- 如果在受限的 agent 沙箱中运行（例如 OpenClaw/Codex exec），优先使用 `host` / `elevated` 模式。\n- 富途 Python SDK 在导入阶段就可能访问本机 OpenD 相关资源，包括 `~/.com.futunn.FutuOpenD/Log` 下的日志目录；因此受限沙箱可能会在业务函数执行前就失败。\n\n**Setup Steps / 安装步骤:**\n1. Install this skill via ClawHub (if not installed yet):\n   ```bash\n   clawhub install futu-trading-bot\n   ```\n\n2. Enter the skill folder (default OpenClaw workspace path):\n   ```bash\n   cd ~/.openclaw/workspace/skills/futu-trading-bot\n   ```\n   If you installed to a different location, `cd` into that folder instead.\n\n3. Create virtual environment (recommended):\n   ```bash\n   python3 -m venv .venv\n   source .venv/bin/activate\n   ```\n\n4. Install package:\n   ```bash\n   pip install -e .\n   ```\n\n5. Configure credentials:\n   ```bash\n   cp json/config_example.json json/config.json\n   # Edit json/config.json with your Futu credentials\n   # 编辑json/config.json填写你的富途账户信息\n   ```\n\n## 依赖项\n\n本技能通过 `pip install -e .` 自动安装以下核心 Python 包：\n- `futu-api`（富途 SDK）\n- `pydantic`（数据校验）\n\n更多依赖请以 `pyproject.toml` / `requirements.txt` 为准。\n\n## Module Map\n\n- **Account**: `account_manager`\n  - `get_account_info()`\n  - `unlock_trade(password=None, password_md5=None)`\n  - `lock_trade()`\n- **Quote**: `quote_service`\n  - Stage 1: `get_stock_basicinfo`, `get_market_state`\n  - Stage 2: `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, callbacks\n  - Stage 3: `get_market_snapshot`, `get_cur_kline`, `request_history_kline`, `get_rt_ticker`\n- **Trade**: `trade_service`\n  - `submit_order`, `modify_order`, `cancel_order`, `cancel_all_orders`\n\n## Standard Workflow\n\n1. Run `preflight_check` first to verify config, OpenD connectivity, and sandbox/runtime readiness.\n2. Call `get_account_info()` and select target account (get `acc_id`).\n3. Pull quote/snapshot for the target symbol (default HK use case: `HK.00700`).\n4. For real trading, call `unlock_trade(...)` (password from config or input).\n5. Submit or manage orders with explicit `acc_id` and `trd_env`.\n6. After real operation, call `lock_trade()` if needed.\n\n## Connection Lifecycle\n\n- Pull-style quote functions such as `get_market_snapshot`, `get_stock_basicinfo`, `get_market_state`, `get_cur_kline`, `request_history_kline`, and `get_rt_ticker` now close their quote context automatically after returning.\n- Trade functions such as `submit_order`, `modify_order`, and `cancel_all_orders` now close their trade/quote contexts automatically after returning.\n- Account functions such as `get_account_info`, `unlock_trade`, and `lock_trade` now close their contexts automatically after returning.\n- Subscription/callback flows keep the quote context open on purpose. For `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, `set_quote_callback`, and `set_orderbook_callback`, call `close_quote_service()` explicitly when you are done with the session.\n\n## Canonical Imports\n\n```python\n# Always use these import paths – do not import from futu directly\nfrom preflight_check import run_preflight\nfrom account_manager import get_account_info, unlock_trade, lock_trade\nfrom quote_service import (\n    get_stock_basicinfo, get_market_state, get_market_snapshot,\n    get_cur_kline, request_history_kline, get_rt_ticker,\n    subscribe, unsubscribe, unsubscribe_all, query_subscription,\n    set_quote_callback, set_orderbook_callback\n)\nfrom trade_service import submit_order, modify_order, cancel_order, cancel_all_orders\n```\n\n## Account Usage\n\n### Preflight\n```python\npreflight = run_preflight()\nif not preflight[\"success\"]:\n    print(preflight)\n    raise SystemExit(\"Preflight failed\")\n```\n\n```python\n# Get list of accounts\ninfo = get_account_info()\nif info['success']:\n    accounts = info['accounts']\n    print(accounts)\n\n# Unlock trade (uses password from config or provided)\nunlock_trade()  # will prompt for password if not configured\n# Or with explicit password:\n# unlock_trade(password=\"your_password\")\n\n# Lock trade\nlock_trade()\n```\n\n## Quote Usage\n\n### Basic Info / Market State\n```python\nget_stock_basicinfo(market=\"HK\", sec_type=\"STOCK\", code_list=[\"HK.00700\"])\nget_market_state([\"HK.00700\"])\n```\n\n### Snapshot (no subscription needed)\n```python\nsnap = get_market_snapshot([\"HK.00700\"])\nif snap['success']:\n    price = snap['data'][0]['last_price']\n```\n\n### K-Line\n```python\n# Current K-line (requires subscription, will auto-subscribe if needed)\nkline = get_cur_kline(code=\"HK.00700\", num=5, ktype=\"K_DAY\", autype=\"QFQ\")\n\n# Historical K-line\nhist = request_history_kline(\n    code=\"HK.00700\",\n    start=\"2026-02-20\",\n    end=\"2026-03-06\",\n    ktype=\"K_DAY\"\n)\n```\n\n### Ticker\n```python\ntickers = get_rt_ticker(code=\"HK.00700\", num=10)\n```\n\n### Subscription & Callbacks\n```python\ndef on_quote(payload):\n    print(payload)\n\nset_quote_callback(on_quote)\nsubscribe([\"HK.00700\"], [\"QUOTE\"], is_first_push=True, subscribe_push=True)\nquery_subscription()\nunsubscribe([\"HK.00700\"], [\"QUOTE\"])\nunsubscribe_all()\nclose_quote_service()\n```\n\n## Trade Usage\n\n```python\n# Submit an order\nresult = submit_order(\n    code=\"HK.00700\",\n    side=\"BUY\",\n    qty=200,\n    acc_id=6017237,               # from get_account_info\n    trd_env=\"SIMULATE\",            # or \"REAL\"\n    price=150,                     # required for LIMIT order\n    order_type=\"NORMAL\",\n)\n\n# Modify order (change price/quantity)\nmodify_order(\n    op=\"NORMAL\",\n    order_id=\"123456789\",\n    trd_env=\"SIMULATE\",\n    price=151,\n    qty=200,\n    acc_id=6017237\n)\n\n# Cancel a single order\ncancel_order(order_id=\"123456789\", trd_env=\"SIMULATE\", acc_id=6017237)\n\n# Cancel all orders\ncancel_all_orders(trd_env=\"SIMULATE\", acc_id=6017237)\n```\n\n## Running a Background Trading Strategy (Using System Tools)\n\nThis skill does not manage long-running processes internally. Instead, you (the agent) should use system tools (e.g., `exec`, `write`, `kill`) to run strategy scripts in the background. This keeps the skill simple and leverages the platform's process management.\n\n### 4.1 Workflow for Background Strategies\n\n1. **Run preflight first** with `PYTHONPATH=src python -m preflight_check`.\n2. If preflight reports sandbox/log-directory restrictions, rerun in `host` / `elevated` mode before using quote/trade functions.\n3. **Generate a Python script** based on user's natural language request, using the encapsulated functions from this skill (e.g., `get_market_snapshot`, `submit_order`).\n4. **Save the script** to a temporary file (using the `write` tool or similar).\n5. **Launch the script as a background process** using the `exec` tool, redirecting output to a log file.\n6. **Record the process ID (PID)** and log file path for future monitoring.\n7. **Monitor/stop** using system tools (`ps`, `kill`, `cat`).\n\n### 4.2 Natural Language Triggers\n\n| User Request | Agent Action |\n|--------------|--------------|\n| “Start a strategy to monitor Tencent, buy below 540, sell above 550” | Generate script → save → launch with `exec` → return PID and log path |\n| “How is my strategy doing?” | Read log file (e.g., `tail -n 20 logfile`) → summarize |\n| “Stop my strategy” | Kill process using PID via `kill` tool |\n\n### 4.3 Script Template (for Agent Reference)\n\nWhen generating a strategy script, use the following template. It handles signals, logging, and state persistence correctly.\n\n```python\n#!/usr/bin/env python3\nimport sys\nimport time\nimport json\nimport os\nimport signal\nimport logging\nfrom pathlib import Path\n\n# If you installed the skill with `pip install -e .`, you can import modules directly.\n# Only use sys.path/PYTHONPATH hacks when you didn't install the package.\n\nfrom trade_service import submit_order\nfrom quote_service import get_market_snapshot\n\n# ===== Strategy parameters – fill by agent =====\n# Replace these placeholders with your own strategy settings.\nSYMBOL = \"HK.00700\"\nACC_ID = 0                 # fill from get_account_info()\nTRD_ENV = \"SIMULATE\"       # default to SIMULATE; use REAL only with explicit confirmation\nQTY = 0                    # position sizing / order quantity\nLOG_FILE = Path(\"strategy.log\")\nPID_FILE = Path(\"strategy.pid\")\n# ===============================================\n\nlogging.basicConfig(\n    filename=LOG_FILE,\n    level=logging.INFO,\n    format='%(asctime)s - %(levelname)s - %(message)s'\n)\n\n# Handle termination signals\ndef handle_exit(signum, frame):\n    logging.info(\"Received signal, stopping strategy\")\n    sys.exit(0)\n\nsignal.signal(signal.SIGTERM, handle_exit)\nsignal.signal(signal.SIGINT, handle_exit)\n\n# Write PID file\nwith open(PID_FILE, \"w\") as f:\n    f.write(str(os.getpid()))\n\nlogging.info(f\"Strategy started: {SYMBOL}\")\n\ntry:\n    while True:\n        snap = get_market_snapshot([SYMBOL])\n        if not snap[\"success\"]:\n            logging.error(f\"Quote failed: {snap['message']}\")\n            time.sleep(60)\n            continue\n        price = snap[\"data\"][0][\"last_price\"]\n        logging.info(f\"Current price: {price}\")\n\n        # --- Insert your strategy logic here ---\n        # Decide whether to trade based on your own signals/logic, then call submit_order(...).\n\n        time.sleep(60)   # check every minute\nexcept Exception as e:\n    logging.exception(\"Strategy crashed\")\nfinally:\n    if PID_FILE.exists():\n        PID_FILE.unlink()\n```\n\n### 4.4 Agent Execution Steps\n\n**User**: “Start a range strategy for Tencent, buy below 540, sell above 550.”\n\n**Agent**:\n1. **Get account ID** via `get_account_info()`.\n2. **Generate script** using the template above, filling in parameters.\n3. **Save script** to a file, e.g., `range_00700.py`, using `write` tool.\n4. **Launch background process** using `exec`:\n   ```bash\n   cd /path/to/workspace\n   nohup .venv/bin/python range_00700.py > strategy.out 2>&1 &\n   ```\n   (Capture the PID from output.)\n5. **Record** PID and log path.\n6. **Reply**: “Strategy started. PID: 12345, log file: strategy_00700.log. You can check status or stop it anytime.”\n\n### 4.5 Check Status\n\n**User**: “How is my strategy doing?”\n\n**Agent**:\n- Read last lines of log: `tail -n 20 strategy_00700.log`.\n- Check if process still running: `ps -p 12345`.\n- Summarize: “Strategy is running, last price was 542.5 at 10:30.”\n\n### 4.6 Stop Strategy\n\n**User**: “Stop my strategy.”\n\n**Agent**:\n- Send SIGTERM: `kill 12345`.\n- Verify process ended, clean up PID file if needed.\n- Reply: “Strategy stopped.”\n\n---\n\n## Error Handling\n\n- All functions return a dictionary with at least `success` (bool) and `message` (str).\n- On success, additional fields like `data` or `order_id` may be present.\n- Always check `success` first before using other fields.\n\nExample:\n```python\nresult = submit_order(...)\nif result[\"success\"]:\n    print(f\"Order ID: {result['order_id']}\")\nelse:\n    print(f\"Error: {result['message']}\")\n```\n\nIf OpenD connection fails, recheck:\n- OpenD is running (check port 11111 with `lsof -i :11111`)\n- Host/port in `config.json` matches OpenD\n- Account has necessary permissions\n\nIf the skill fails before quote/trade functions are even called, recheck:\n- Whether the current agent/tool is running in a restricted sandbox\n- Whether you should rerun in `host` / `elevated` mode\n- Whether the runtime can access the local Futu OpenD log directory under `~/.com.futunn.FutuOpenD/Log`\n- Run `PYTHONPATH=src python -m preflight_check` first and follow its suggestions\n\n## Configuration\n\n- **Config file**: `json/config.json`\n- **Required fields**:\n  - `futu_api.host` (default: 127.0.0.1)\n  - `futu_api.port` (default: 11111)\n  - `futu_api.security_firm` (e.g., `FUTUSECURITIES`)\n- **Password handling**:\n  - Prefer `trade_password_md5` (32‑char lowercase MD5)\n  - Fallback to `trade_password` (will be MD5‑ed at runtime)\n- **Account cache**: `json/account_info.json` (auto‑generated after `get_account_info`)\n\n## 📜 License\n\nThis skill is licensed under **MIT-0** (MIT No Attribution).\n\n---\n\n**Copyright © 2026 jeffersonling1217-png**\n```\n\nFile v1.0.5:_meta.json\n\n{\n  \"ownerId\": \"kn79d46ahs4v5syfeh8jjzqf7d81y7rr\",\n  \"slug\": \"futu-trading-bot\",\n  \"version\": \"1.0.5\",\n  \"publishedAt\": 1773905021501\n}\n\nFile v1.0.5:docs/account.md\n\n# Account Manager 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/account_manager.py`\n\n## 概述\n账户模块用于：\n- 查询账户列表\n- 解锁交易权限\n- 锁定交易权限\n\n并提供便捷函数供脚本/LLM 直接调用。\n\n## 对外接口\n\n### `get_account_info()`\n```python\nget_account_info() -> Dict[str, Any]\n```\n\n行为：\n- 调用富途 `get_acc_list()`。\n- 返回账户列表结构：`accounts`。\n- 每次调用都会覆盖写本地文件：`json/account_info.json`。\n\n成功返回示例：\n```python\n{\n  \"success\": True,\n  \"accounts\": [\n    {\n      \"account_id\": \"2817...\",\n      \"account_type\": \"REAL\",\n      \"market\": \"['HK', 'US']\",\n      \"acc_type\": \"MARGIN\",\n      \"security_firm\": \"FUTUSECURITIES\",\n      \"sim_acc_type\": \"N/A\",\n      \"acc_status\": \"ACTIVE\"\n    }\n  ],\n  \"error_msg\": None\n}\n```\n\n### `unlock_trade(password=None, password_md5=None)`\n```python\nunlock_trade(\n    password: Optional[str] = None,\n    password_md5: Optional[str] = None\n) -> Dict[str, Any]\n```\n\n密码优先级：\n1. 显式参数 `password_md5`\n2. 显式参数 `password`（运行时自动转 MD5）\n3. 配置 `trade_password_md5`\n4. 配置 `trade_password`（运行时自动转 MD5）\n\n### `lock_trade(password=None, password_md5=None)`\n```python\nlock_trade(\n    password: Optional[str] = None,\n    password_md5: Optional[str] = None\n) -> Dict[str, Any]\n```\n\n实现调用：\n- 富途 `unlock_trade(..., is_unlock=False)`\n\n## 统一返回格式\n```python\n{\n  \"success\": bool,\n  \"error_msg\": Optional[str]\n}\n```\n\n## 本地文件输出\n`get_account_info()` 会写入：\n- 文件：`json/account_info.json`\n- 策略：每次覆盖\n- 结构：\n```json\n{\n  \"updated_at\": \"2026-03-06T14:44:51\",\n  \"data\": { \"...\": \"...\" }\n}\n```\n\n## 使用示例\n```python\nfrom account_manager import get_account_info, unlock_trade, lock_trade\n\nprint(get_account_info())\nprint(unlock_trade())  # 使用配置中的密码或MD5\nprint(lock_trade())    # 用完建议锁回\n```\n\n## 注意事项\n- 依赖 OpenD 连接可用。\n- 明文密码和 MD5 密码都属于敏感信息，均应避免泄露。\n\nFile v1.0.5:docs/config.md\n\n# Config Manager 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/config_manager.py`\n\n## 作用\n统一加载并提供项目配置（富途连接参数、交易密码、日志参数）。\n\n## 配置文件读取规则\n1. 优先读取：`json/config.json`\n2. 回退读取：`json/config.example.json`（存在时）\n3. 若都不存在，抛出 `FileNotFoundError`\n\n## 配置示例\n```json\n{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"\",\n    \"trade_password_md5\": \"\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}\n```\n\n## 默认值（缺省字段自动补全）\n- `host`: `127.0.0.1`\n- `port`: `11111`\n- `security_firm`: `FUTUSECURITIES`\n- `trade_password`: `\"\"`\n- `trade_password_md5`: `\"\"`\n- `default_env`: `SIMULATE`\n\n## 主要接口\n- `get_futu_config()`\n- `get_host()`\n- `get_port()`\n- `get_security_firm()`\n- `get_trade_password()`\n- `get_trade_password_md5()`\n- `get_default_env()`\n- `get_default_env_str()`\n\n## 与其他模块关系\n- `account_manager` 使用本模块读取主机、端口、券商、交易密码。\n- `trade_service` 使用本模块读取主机、端口、券商。\n\n## 安全建议\n- `json/config.json` 不应入库，需加入 `.gitignore`。\n- 使用最小权限：`chmod 600 json/config.json`。\n- 不在日志中输出真实密码或 MD5 值。\n\nFile v1.0.5:docs/trade.md\n\n# Trade Service 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/trade_service.py`\n\n## 概述\n交易模块负责下单、改单、撤单与全部撤单，内部包含参数校验和富途 API 调用。\n\n## 设计原则\n- 交易环境不做内部管理，调用方必须显式传入。\n- 不提供账户环境切换接口（无 `switch_account_env`）。\n- 不做幂等去重校验。\n\n## 对外接口\n\n### `submit_order(...)`\n```python\nsubmit_order(\n    code: str,\n    side: str,\n    qty: int,\n    acc_id: int,\n    trd_env: str,\n    price: Optional[float] = None,\n    order_type: str = \"NORMAL\",\n    aux_price: Optional[float] = None,\n    remark: Optional[str] = None,\n    time_in_force: str = \"DAY\",\n) -> Dict[str, Any]\n```\n\n说明：\n- `acc_id` 必传。\n- `trd_env` 必传，仅支持 `REAL`、`SIMULATE`。\n- `code` 目前按港股校验：必须以 `HK.` 开头。\n- 会校验下单数量是否为 `lot_size` 整数倍。\n\n### `modify_order(...)`\n```python\nmodify_order(\n    op: str,\n    order_id: str,\n    trd_env: str,\n    qty: Optional[float] = None,\n    price: Optional[float] = None,\n    acc_id: int = 0,\n    **kwargs,\n) -> Dict[str, Any]\n```\n\n`op` 支持：\n- `NORMAL`\n- `CANCEL`\n- `DISABLE`\n- `ENABLE`\n- `DELETE`\n\n### `cancel_order(...)`\n```python\ncancel_order(order_id: str, trd_env: str, acc_id: int = 0) -> Dict[str, Any]\n```\n\n### `cancel_all_orders(...)`\n```python\ncancel_all_orders(trd_env: str, acc_id: int = 0, trdmarket: Optional[str] = None) -> Dict[str, Any]\n```\n\n## 下单校验流程（`submit_order`）\n1. 订单模型参数校验（Pydantic）。\n2. 股票代码格式校验。\n3. 获取并校验 `lot_size`。\n4. 价格、数量、触发价等基础校验。\n5. 通过市场快照验证股票可用。\n6. 调用富途 `place_order`。\n\n## 返回格式\n统一返回字典，至少包含：\n- `success`: 是否成功\n- `message`: 结果描述\n\n成功下单通常包含：\n- `order_id`\n- `lot_size`\n- `trd_env`\n\n## 使用示例\n```python\nfrom trade_service import submit_order\n\nresult = submit_order(\n    code=\"HK.00700\",\n    side=\"BUY\",\n    qty=200,\n    acc_id=6017237,\n    trd_env=\"SIMULATE\",\n    price=150,\n    order_type=\"NORMAL\",\n)\nprint(result)\n```\n\n## 注意事项\n- `REAL` 环境会尝试真实交易，请先确认交易权限状态。\n- 真实交易密码解锁/锁定由 `account_manager` 处理，不在本模块内自动完成。\n\nFile v1.0.5:json/config_example.json\n\n{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"YOUR PASSWORD\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}\n\nFile v1.0.5:pyproject.toml\n\n[build-system]\nrequires = [\"setuptools>=68\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"futu-trade-bot-skills\"\nversion = \"0.1.0\"\ndescription = \"Futu Trade Bot Skills modules for account, trade, and quote services.\"\nreadme = \"README.md\"\nrequires-python = \">=3.10\"\ndependencies = [\n  \"futu-api\",\n  \"pydantic>=2,<3\",\n]\n\n[tool.setuptools]\npy-modules = [\"account_manager\", \"config_manager\", \"trade_service\", \"quote_service\", \"preflight_check\"]\n\n[tool.setuptools.package-dir]\n\"\" = \"src\"\n\nFile v1.0.5:requirements.txt\n\nfutu-api\npydantic>=2,<3\n\nArchive v1.0.4: 66 files, 84127 bytes\n\nFiles: docs/account.md (2101b), docs/config.md (1462b), docs/trade.md (2389b), json/account_info.json (899b), json/config_example.json (274b), json/config.json (274b), pyproject.toml (520b), README.md (3533b), requirements.txt (24b), SKILL.md (5272b), src/account_manager.py (13279b), src/config_manager.py (6835b), src/futu_trade_bot_skills.egg-info/dependency_links.txt (1b), src/futu_trade_bot_skills.egg-info/requires.txt (24b), src/futu_trade_bot_skills.egg-info/SOURCES.txt (457b), src/futu_trade_bot_skills.egg-info/top_level.txt (59b), src/quote_service.py (17791b), src/trade_service.py (32146b), test/script.py (865b), test/tencent_trade.py (1622b), test/test_account_and_order.py (979b), test/test_quote_service_real.py (1981b), test/test_quote_service_stage3_real.py (1049b), trading_project/_meta.json (135b), trading_project/analysis_strategy.py (3335b), trading_project/better_monitor.py (1674b), trading_project/check_account.py (2521b), trading_project/check_strategy_status.py (2356b), trading_project/debug_connection.py (1715b), trading_project/execute_sell.py (1865b), trading_project/fixed_cleanup.py (4126b), trading_project/force_close_positions.py (5031b), trading_project/instant_trade.py (2553b), trading_project/intraday_trader.py (3627b), trading_project/mini_monitor.py (1385b), trading_project/mini_report.py (671b), trading_project/periodic_report.py (3766b), trading_project/quick_cleanup.py (1025b), trading_project/quick_status.py (3299b), trading_project/realtime_monitor.py (8009b), trading_project/schedule_tomorrow.sh (488b), trading_project/simple_cleanup.py (1350b), trading_project/simple_report.py (2719b), trading_project/simple_trader.py (5331b), trading_project/smart_cleanup.py (1777b), trading_project/stable_trader.py (2676b), trading_project/start_tomorrow.sh (818b), trading_project/strategy_summary.md (2801b), trading_project/strategy.json (127b), trading_project/technical_analysis.py (7111b), trading_project/telegram_reporter.py (5488b), trading_project/telegram_simple_report.py (3067b), trading_project/test_basic_order.py (2600b), trading_project/test_callback.py (4161b), trading_project/test_connection.py (1016b), trading_project/test_tencent_quote.py (3730b), trading_project/test_trade_setup.py (2192b), trading_project/test_wrapper.py (1238b), trading_project/trading_strategy.py (19717b), trading_reports/report_001.json (2706b), trading_reports/report_002.json (2706b), trading_reports/report_003.json (2706b), trading_reports/report_004.json (2706b), trading_reports/report_005.json (2706b), trading_reports/report_006.json (2706b), _meta.json (135b)\n\nFile v1.0.4:SKILL.md\n\n---\nname: futu-trading-bot\ndescription: Use Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.\nlicense: MIT\nmetadata: {\"openclaw\":{\"emoji\":\"📈\",\"requires\":{\"bins\":[\"python3\"]}}}\n---\n\n# Futu Trade Bot Skills 📈\n\n## 🎯 Overview / 概述\n\n**English Version:**\nA trading bot skill based on Futu OpenAPI that enables natural language trading. This skill encapsulates Futu's market quote and order execution APIs, allowing agents to perform real-time trading operations through simple commands or scripts. Perfect for implementing natural language trading strategies and automated workflows.\n\n**中文版本:**\n基于富途牛牛API接口的交易机器人技能，帮助用户用自然语言进行交易。本技能已将富途牛牛的行情报价、下单交易等功能做了完整封装，可供智能助手随时调用。建议通过命令行或脚本来实现自然语言的策略生成和交易执行。\n\n---\n\n## When to Use This Skill / 使用场景\n\nUse this skill when the user asks for any of the following:\n- account query / unlock / lock\n- HK quote pull or quote subscription callback\n- order submission / modification / cancellation\n\n## Quick Start / 快速开始\n\n**Prerequisites / 前提条件:**\n- Ensure Futu OpenD is running and HK quote entitlement is available.\n- 确保富途OpenD正在运行且拥有港股行情权限。\n\n**Setup Steps / 安装步骤:**\n1. Create virtual environment (recommended):\n   ```bash\n   python3 -m venv .venv\n   source .venv/bin/activate\n   ```\n\n2. Install package:\n   ```bash\n   pip install -e .\n   ```\n\n3. Configure credentials:\n   ```bash\n   cp json/config_example.json json/config.json\n   # Edit json/config.json with your Futu credentials\n   # 编辑json/config.json填写你的富途账户信息\n   ```\n\n## Module Map\n\n- Account: `account_manager`\n  - `get_account_info()`\n  - `unlock_trade(password=None, password_md5=None)`\n  - `lock_trade(password=None, password_md5=None)`\n- Quote: `quote_service`\n  - Stage 1: `get_stock_basicinfo`, `get_market_state`\n  - Stage 2: `subscribe`, `unsubscribe`, `unsubscribe_all`, `query_subscription`, callbacks\n  - Stage 3: `get_market_snapshot`, `get_cur_kline`, `request_history_kline`, `get_rt_ticker`\n- Trade: `trade_service`\n  - `submit_order`, `modify_order`, `cancel_order`, `cancel_all_orders`\n\n## Standard Workflow\n\n1. Call `get_account_info()` and select target account.\n2. Pull quote/snapshot for the target symbol (default HK use case: `HK.00700`).\n3. For real trading, call `unlock_trade(...)`.\n4. Submit or manage orders with explicit `acc_id` and `trd_env`.\n5. After real operation, call `lock_trade(...)`.\n\n## Canonical Imports\n\n```python\nfrom account_manager import get_account_info, unlock_trade, lock_trade\nfrom quote_s\n\nArchive v1.0.3: 12 files, 27157 bytes\n\nFiles: docs/account.md (2101b), docs/config.md (1462b), docs/trade.md (2389b), json/config_example.json (274b), pyproject.toml (487b), requirements.txt (24b), SKILL.md (13065b), src/account_manager.py (13279b), src/config_manager.py (6835b), src/quote_service.py (17791b), src/trade_service.py (32146b), _meta.json (135b)\n\nArchive v1.0.2: 12 files, 27090 bytes\n\nFiles: docs/account.md (2101b), docs/config.md (1462b), docs/trade.md (2389b), json/config_example.json (274b), pyproject.toml (487b), requirements.txt (24b), SKILL.md (12909b), src/account_manager.py (13279b), src/config_manager.py (6835b), src/quote_service.py (17791b), src/trade_service.py (32146b), _meta.json (135b)\n\nArchive v1.0.1: 18 files, 29538 bytes\n\nFiles: docs/account.md (2101b), docs/config.md (1462b), docs/trade.md (2389b), json/config_example.json (274b), pyproject.toml (520b), README.md (3533b), requirements.txt (24b), SKILL.md (5272b), src/account_manager.py (13279b), src/config_manager.py (6835b), src/quote_service.py (17791b), src/trade_service.py (32146b), test/script.py (865b), test/tencent_trade.py (1622b), test/test_account_and_order.py (979b), test/test_quote_service_real.py (1981b), test/test_quote_service_stage3_real.py (1049b), _meta.json (135b)\n\nArchive v0.1.9: 19 files, 31525 bytes\n\nFiles: docs/account.md (2101b), docs/config.md (1462b), docs/development_plan.md (3458b), docs/trade.md (2389b), json/config_example.json (274b), pyproject.toml (520b), README.md (3533b), requirements.txt (24b), SKILL.md (5272b), src/account_manager.py (13279b), src/config_manager.py (6835b), src/quote_service.py (17791b), src/trade_service.py (32146b), test/script.py (865b), test/tencent_trade.py (1622b), test/test_account_and_order.py (979b), test/test_quote_service_real.py (1981b), test/test_quote_service_stage3_real.py (1049b), _meta.json (135b)","readmeExcerpt":"Skill: futu-trading-bot Owner: jeffersonling1217-png Summary: Use Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data. Tags: latest:1.0.9 Version history: v1.0.9 | 2026-08-06T09:43:55.466Z | user Pin pydantic==2.12.5 to satisfy supply-chain scanner (SC4); keep 1.0.8 security confirm gates v1.0.8 | 2026-08-06T09:28:13.368Z | user Security: confirm gates for REAL trades/unlock/canc","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"File v1.0.9:README.md\n\n# Futu Trading Bot Skills\r\n\r\n> **⚠️ Safety first**\r\n>\r\n> This skill can unlock a Futu brokerage account and place, modify, or cancel **real-money** orders via local OpenD.\r\n> - Prefer **`SIMULATE`** until you fully trust the setup.\r\n> - `REAL` orders, unlock/lock, and **`cancel_all_orders`** require explicit human approval and API `confirm=True`.\r\n> - Do not store plaintext passwords in git; prefer `trade_password_md5`.\r\n> - `get_account_info()` does **not** write disk by default (`persist=False`).\r\n\r\n这是一个为 AI Agent 打造的自然语言交易执行工具。它将富途 OpenAPI 的底层逻辑封装为语义能力，支持通过自然语言驱动账户解锁、下单及风控管理。系统支持（模拟/实盘）环境隔离，能够将“帮我买 200 股腾讯”或“清仓一半持仓”这类模糊意图，转化为符合金融规范的执行动作。\r\n\r\nA robust trade execution tool designed for AI Agents. It abstracts Futu OpenAPI logic into high-level semantic capabilities, enabling natural language control over account unlocking, order placement, and risk management. With native support for MD5 credential handling and environment isolation (Simulated/Real), it accurately translates vague intents—such as \"buy 200 shares of Tencent\" or \"close half of my positions\"—into execution actions that comply with financial standards.\r\n\r\n适用对象：配合 OpenClaw 使用，或任何能通过命令行调用工具并能编写 Python 脚本的 Agent/LLM。\r\n\r\n核心代码在 `src/`，配置与运行数据在 `json/`。\r\n\r\n## 功能\r\n- 账户查询：`get_account_info()`\r\n- 交易解锁：`unlock_trade(password=None, password_md5=None)`\r\n- 交易锁定：`lock_trade(password=None, password_md5=None)`\r\n- 预检：`run_preflight()`\r\n- 行情拉取：`get_stock_basicinfo()`、`get_market_state()`、`get_market_snapshot()`、`get_cur_kline()`、`request_history_kline()`、`get_rt_ticker()`\r\n- 行情统一启动：`start_quote_stream()`、`start_orderbook_stream()`\r\n- 下单：`submit_order(...)`\r\n- 改单/撤单：`modify_order(...)`、`cancel_order(...)`、`cancel_all_orders(...)`\r\n- 策略运行：`run_strategy(...)`\r\n- 策略辅助：状态、交易锁、交易时段判断、回调 payload 解析\r\n\r\n## 当前行为说明\r\n- `submit_order` 必须显式传入 `acc_id` 和 `trd_env`（`REAL` / `SIMULATE`）。`REAL` 还需要 `confirm=True`。\r\n- `cancel_all_orders` 在任何环境下都需要 `confirm=True`。\r\n- `get_account_info(persist=False)` 默认只返回内存结果；仅当 `per"},{"language":"json","snippet":"{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"\",\n    \"trade_password_md5\": \"\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}"},{"language":"python","snippet":"from quote_service import start_quote_stream, unsubscribe_all, close_quote_service\n\ndef on_quote(payload):\n    print(payload)\n\nstart_quote_stream([\"HK.00700\"], on_quote)\n\n# done\nunsubscribe_all()\nclose_quote_service()"},{"language":"text","snippet":"File v1.0.8:README.md\n\n# Futu Trading Bot Skills\r\n\r\n> **⚠️ Safety first**\r\n>\r\n> This skill can unlock a Futu brokerage account and place, modify, or cancel **real-money** orders via local OpenD.\r\n> - Prefer **`SIMULATE`** until you fully trust the setup.\r\n> - `REAL` orders, unlock/lock, and **`cancel_all_orders`** require explicit human approval and API `confirm=True`.\r\n> - Do not store plaintext passwords in git; prefer `trade_password_md5`.\r\n> - `get_account_info()` does **not** write disk by default (`persist=False`).\r\n\r\n这是一个为 AI Agent 打造的自然语言交易执行工具。它将富途 OpenAPI 的底层逻辑封装为语义能力，支持通过自然语言驱动账户解锁、下单及风控管理。系统支持（模拟/实盘）环境隔离，能够将“帮我买 200 股腾讯”或“清仓一半持仓”这类模糊意图，转化为符合金融规范的执行动作。\r\n\r\nA robust trade execution tool designed for AI Agents. It abstracts Futu OpenAPI logic into high-level semantic capabilities, enabling natural language control over account unlocking, order placement, and risk management. With native support for MD5 credential handling and environment isolation (Simulated/Real), it accurately translates vague intents—such as \"buy 200 shares of Tencent\" or \"close half of my positions\"—into execution actions that comply with financial standards.\r\n\r\n适用对象：配合 OpenClaw 使用，或任何能通过命令行调用工具并能编写 Python 脚本的 Agent/LLM。\r\n\r\n核心代码在 `src/`，配置与运行数据在 `json/`。\r\n\r\n## 功能\r\n- 账户查询：`get_account_info()`\r\n- 交易解锁：`unlock_trade(password=None, password_md5=None)`\r\n- 交易锁定：`lock_trade(password=None, password_md5=None)`\r\n- 预检：`run_preflight()`\r\n- 行情拉取：`get_stock_basicinfo()`、`get_market_state()`、`get_market_snapshot()`、`get_cur_kline()`、`request_history_kline()`、`get_rt_ticker()`\r\n- 行情统一启动：`start_quote_stream()`、`start_orderbook_stream()`\r\n- 下单：`submit_order(...)`\r\n- 改单/撤单：`modify_order(...)`、`cancel_order(...)`、`cancel_all_orders(...)`\r\n- 策略运行：`run_strategy(...)`\r\n- 策略辅助：状态、交易锁、交易时段判断、回调 payload 解析\r\n\r\n## 当前行为说明\r\n- `submit_order` 必须显式传入 `acc_id` 和 `trd_env`（`REAL` / `SIMULATE`）。`REAL` 还需要 `confirm=True`。\r\n- `cancel_all_orders` 在任何环境下都需要 `confirm=True`。\r\n- `get_account_info(persist=False)` 默认只返回内存结果；仅当 `per"},{"language":"json","snippet":"{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"\",\n    \"trade_password_md5\": \"\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}"},{"language":"python","snippet":"from quote_service import start_quote_stream, unsubscribe_all, close_quote_service\n\ndef on_quote(payload):\n    print(payload)\n\nstart_quote_stream([\"HK.00700\"], on_quote)\n\n# done\nunsubscribe_all()\nclose_quote_service()"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\r\nname: futu-trading-bot\r\ndescription: Use Futu Trade Bot Skills to run account, quote, and trade workflows with real HK market data.\r\nlicense: MIT-0\r\nmetadata:\r\n  openclaw:\r\n    emoji: \"📈\"\r\n    requires:\r\n      bins: [\"python3\", \"pip\"]\r\n    permissions:\r\n      - local-network  # Futu OpenD (default 127.0.0.1:11111)\r\n      - filesystem-read  # json/config.json and skill modules\r\n      - filesystem-write  # optional account_info.json / strategy logs / PID files when user opts in\r\n      - process  # optional background strategy only after explicit user confirmation\r\n---\r\n\r\n# Futu Trade Bot Skills 📈\r\n\r\n## ⚠️ Security & Safety (READ FIRST)\r\n\r\nThis skill can control a **live brokerage account** via Futu OpenD. Misuse can cause **irreversible financial loss**.\r\n\r\n**Hard rules for the agent:**\r\n1. **Default to SIMULATE.** Never use `trd_env=\"REAL\"` unless the user explicitly requests live trading and confirms the exact order parameters.\r\n2. **State-changing actions require explicit user approval**, then pass `confirm=True`:\r\n   - `unlock_trade` / `lock_trade`\r\n   - `submit_order` when `trd_env=\"REAL\"`\r\n   - `modify_order` / `cancel_order` when `trd_env=\"REAL\"`\r\n   - `cancel_all_orders` in **any** environment\r\n3. **Read-only actions** (quotes, `get_account_info(persist=False)`) may run without `confirm`.\r\n4. **Do not** collect trading passwords via interactive stdin. Use config (`trade_password_md5` preferred) or an explicit parameter the user already provided out-of-band.\r\n5. **Do not** write `json/account_info.json` unless the user asks to cache accounts (`persist=True`).\r\n6. **Background strategies** (write script / start process / stop process) only after the user clearly asks and confirms symbol, qty, `SIMULATE`/`REAL`, and log/PID paths.\r\n7. If a restricted sandbox blocks OpenD or `~/.com.futunn.FutuOpenD/Log`, **tell the user** before suggesting `host` / `elevated` mode — never silently escalate.\r\n\r\n**中文硬规则：** 默认模拟盘；真金白银/解锁/全部撤单必须先复述参数并得到用户明确同意，再传 `confirm=True`；禁止 stdin 要密码；默认不把账户信息写盘。\r\n\r\n## 🎯 Overview / 概述\r\n\r\n**English Version:**\r\nA trading bot skill based on Futu OpenAPI that enables natural language trading. This skill encapsulates Futu's market quote and order execution APIs, allowing agents to perform real-time trading operations through simple commands or scripts. Perfect for implementing natural language trading strategies and automated workflows.\r\n\r\n**Important**: Always use the encapsulated functions provided in this skill (e.g., `submit_order`, `get_market_snapshot`). **Never call Futu SDK functions directly** (`ctx.place_order`, `ctx.get_market_snapshot`), as this will bypass connection management, parameter validation, and error handling, leading to unpredictable failures and resource leaks.\r\n\r\n**中文版本:**\r\n基于富途牛牛API接口的交易机器人技能，帮助用户用自然语言进行交易。本技能已将富途牛牛的行情报价、下单交易等功能做了完整封装，可供智能助手随时调用。建议通过命令行或脚本来实现自然语言的策略生成和交易执行。\r\n\r\n**重要提示**：请始终使用本技能提供的封装函数（如 `submit_order`、`get_market_snapshot`）。**切勿直接调用富途SDK的原始函数**（例如 `ctx.place_order`），否则会绕过连接管理、参数校"},{"path":"README.md","content":"# Futu Trading Bot Skills\r\n\r\n> **⚠️ Safety first**\r\n>\r\n> This skill can unlock a Futu brokerage account and place, modify, or cancel **real-money** orders via local OpenD.\r\n> - Prefer **`SIMULATE`** until you fully trust the setup.\r\n> - `REAL` orders, unlock/lock, and **`cancel_all_orders`** require explicit human approval and API `confirm=True`.\r\n> - Do not store plaintext passwords in git; prefer `trade_password_md5`.\r\n> - `get_account_info()` does **not** write disk by default (`persist=False`).\r\n\r\n这是一个为 AI Agent 打造的自然语言交易执行工具。它将富途 OpenAPI 的底层逻辑封装为语义能力，支持通过自然语言驱动账户解锁、下单及风控管理。系统支持（模拟/实盘）环境隔离，能够将“帮我买 200 股腾讯”或“清仓一半持仓”这类模糊意图，转化为符合金融规范的执行动作。\r\n\r\nA robust trade execution tool designed for AI Agents. It abstracts Futu OpenAPI logic into high-level semantic capabilities, enabling natural language control over account unlocking, order placement, and risk management. With native support for MD5 credential handling and environment isolation (Simulated/Real), it accurately translates vague intents—such as \"buy 200 shares of Tencent\" or \"close half of my positions\"—into execution actions that comply with financial standards.\r\n\r\n适用对象：配合 OpenClaw 使用，或任何能通过命令行调用工具并能编写 Python 脚本的 Agent/LLM。\r\n\r\n核心代码在 `src/`，配置与运行数据在 `json/`。\r\n\r\n## 功能\r\n- 账户查询：`get_account_info()`\r\n- 交易解锁：`unlock_trade(password=None, password_md5=None)`\r\n- 交易锁定：`lock_trade(password=None, password_md5=None)`\r\n- 预检：`run_preflight()`\r\n- 行情拉取：`get_stock_basicinfo()`、`get_market_state()`、`get_market_snapshot()`、`get_cur_kline()`、`request_history_kline()`、`get_rt_ticker()`\r\n- 行情统一启动：`start_quote_stream()`、`start_orderbook_stream()`\r\n- 下单：`submit_order(...)`\r\n- 改单/撤单：`modify_order(...)`、`cancel_order(...)`、`cancel_all_orders(...)`\r\n- 策略运行：`run_strategy(...)`\r\n- 策略辅助：状态、交易锁、交易时段判断、回调 payload 解析\r\n\r\n## 当前行为说明\r\n- `submit_order` 必须显式传入 `acc_id` 和 `trd_env`（`REAL` / `SIMULATE`）。`REAL` 还需要 `confirm=True`。\r\n- `cancel_all_orders` 在任何环境下都需要 `confirm=True`。\r\n- `get_account_info(persist=False)` 默认只返回内存结果；仅当 `persist=True` 时写入 `json/account_info.json`。\r\n- `unlock_trade` / `lock_trade` 需要 `confirm=True`，支持 MD5 密码：\r\n  - 优先使用 `password_md5` / 配置 `trade_password_md5`\r\n  - 若仅提供明文 `password`，会在运行时自动转 MD5 后调用富途接口\r\n  - **不提供** stdin 交互式输密码接口\r\n- 拉取型 quote 函数会在返回后自动关闭 quote context。\r\n- trade/account 对外函数会在返回后自动关闭各自 context。\r\n- 订阅/回调模式不会自动关闭 quote context，调用方结束时应显式 `close_quote_service()`。\r\n- `modify_order` / `cancel_order` / `cancel_all_orders` 会自行重新初始化交易 context，不依赖上一次调用留下的连接。\r\n\r\n## 安装\r\n### 方式 A：作为 ClawHub Skill 安装（推荐给 Agent 用户）\r\n不需要手动下载整个仓库，直接安装 skill 文件夹即可：\r\n```bash\r\nclawhub install futu-trading-bot\r\n```\r\n\r\n安装完成后，在该 skill 目录中创建虚拟环境并安装依赖（否则无法 `import` / 调用）：\r\n```bash\r\npython3 -m venv .venv\r\nsource .venv/bin/activate\r\npip install -r requirements.txt\r\npip install -e .\r\n```\r\n\r\n### 方式 B：从 GitHub 源码安装（推荐给开发者）\r\n如果你是要开发/改代码，直接 clone 本仓库后：\r\n```bash\r\npip install -r requirements.txt\r\n```\r\n\r\n推荐（开发环境）：\r\n```bash\r\npip install -e .\r\n```\r\n安装后可直接 `import quote_service/trade_service/account_manager/config_manager`，\r\n无需再手动设置 `PYTHONPATH` 或在脚本"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn79d46ahs4v5syfeh8jjzqf7d81y7rr\",\n  \"slug\": \"futu-trading-bot\",\n  \"version\": \"1.0.9\",\n  \"publishedAt\": 1786009435466\n}"},{"path":"docs/account.md","content":"# Account Manager 文档\r\n\r\n所属项目：**Futu Trade Bot Skills**\r\n\r\n## 模块位置\r\n`src/account_manager.py`\r\n\r\n## 安全提示\r\n- `unlock_trade` / `lock_trade` 会改变真实券商账户的交易锁定状态，**必须** `confirm=True`，且仅在用户明确授权后调用。\r\n- 不要通过 agent stdin 收集交易密码；优先使用配置中的 `trade_password_md5`。\r\n- `get_account_info` 默认**不写盘**。仅当用户要求缓存账户列表时使用 `persist=True`（写入 `json/account_info.json`，含账户 ID / 环境 / 券商等元数据，请限制文件权限且勿提交仓库）。\r\n\r\n## 对外接口\r\n\r\n### `get_account_info(persist=False)`\r\n```python\r\nget_account_info(persist: bool = False) -> Dict[str, Any]\r\n```\r\n\r\n行为：\r\n- 调用富途 `get_acc_list()`。\r\n- 返回账户列表结构：`accounts`。\r\n- 仅当 `persist=True` 时覆盖写 `json/account_info.json`，并在结果中设置 `persisted=True/False`。\r\n\r\n### `unlock_trade(password=None, password_md5=None, confirm=False)`\r\n```python\r\nunlock_trade(\r\n    password: Optional[str] = None,\r\n    password_md5: Optional[str] = None,\r\n    confirm: bool = False,\r\n) -> Dict[str, Any]\r\n```\r\n\r\n- `confirm` 必须为 `True`，否则直接失败。\r\n- 密码优先级：显式 `password_md5` → 显式 `password` → 配置 `trade_password_md5` → 配置 `trade_password`。\r\n\r\n### `lock_trade(password=None, password_md5=None, confirm=False)`\r\n同样需要 `confirm=True`。内部调用富途 `unlock_trade(..., is_unlock=False)`。\r\n\r\n## 使用示例\r\n```python\r\nfrom account_manager import get_account_info, unlock_trade, lock_trade\r\n\r\nprint(get_account_info())\r\nprint(unlock_trade(confirm=True))\r\nprint(lock_trade(confirm=True))\r\n```\r\n\r\n## 注意事项\r\n- 依赖 OpenD 连接可用。\r\n- 明文密码和 MD5 都属于敏感信息。\r\n- 对外函数返回后会关闭账户相关 context。"},{"path":"docs/config.md","content":"# Config Manager 文档\n\n所属项目：**Futu Trade Bot Skills**\n\n## 模块位置\n`src/config_manager.py`\n\n## 作用\n统一加载并提供项目配置（富途连接参数、交易密码、日志参数）。\n\n## 配置文件读取规则\n1. 优先读取：`json/config.json`\n2. 回退读取：`json/config_example.json`（存在时）\n3. 兼容读取：`json/config.example.json`（旧命名存在时）\n4. 若都不存在，抛出 `FileNotFoundError`\n\n## 配置示例\n```json\n{\n  \"futu_api\": {\n    \"host\": \"127.0.0.1\",\n    \"port\": 11111,\n    \"security_firm\": \"FUTUSECURITIES\",\n    \"trade_password\": \"\",\n    \"trade_password_md5\": \"\",\n    \"default_env\": \"SIMULATE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(levelname)s - %(message)s\"\n  }\n}\n```\n\n## 默认值（缺省字段自动补全）\n- `host`: `127.0.0.1`\n- `port`: `11111`\n- `security_firm`: `FUTUSECURITIES`\n- `trade_password`: `\"\"`\n- `trade_password_md5`: `\"\"`\n- `default_env`: `SIMULATE`\n\n## 主要接口\n- `get_futu_config()`\n- `get_host()`\n- `get_port()`\n- `get_security_firm()`\n- `get_trade_password()`\n- `get_trade_password_md5()`\n- `get_default_env()`\n- `get_default_env_str()`\n\n## 与其他模块关系\n- `account_manager` 使用本模块读取主机、端口、券商、交易密码。\n- `trade_service` 使用本模块读取主机、端口、券商。\n\n## 安全建议\n- `json/config.json` 不应入库，需加入 `.gitignore`。\n- 使用最小权限：`chmod 600 json/config.json`。\n- 不在日志中输出真实密码或 MD5 值。"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1405,"uniquenessScore":43,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T21:51:03.969Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T21:51:03.969Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T07:22:56.150Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}