Skill: robin797860/stock-watcher (version 1.0.0)

--- name: stock-watcher description: Manage and monitor a personal stock watchlist with support for adding, removing, listing stocks, and summarizing their recent performance using data from 10jqka.com.cn. Use when the user wants to track specific stocks, get performance summaries, or manage their watchlist. --- # Stock Watcher Skill This skill provides comprehensive stock watchlist management capabilities, allowing users to track their favorite stocks and get performance summaries using real-time data from 同花顺 (10jqka.com.cn). ## 自选股行情查看 当你要求查看自选股行情时，系统会直接显示以下信息： - 每只股票的代码和名称 - 近期表现指标（涨跌幅等关键数据） - 详细信息链接（可点击查看） 无需额外命令，直接为你呈现简洁明了的行情概览。 ## 管理自选股 ### 添加股票 使用股票代码（6位数字）添加到自选股： - 例如：添加 600053 九鼎投资 ### 删除股票 通过股票代码删除自选股： - 例如：删除 600053 ### 查看自选股列表 显示当前所有自选股的完整列表 ### 清空自选股列表 完全清空所有自选股 ## 数据来源 主要使用**同花顺 (10jqka.com.cn)** 作为数据源： - **股票页面**: `https://stockpage.10jqka.com.cn/{stock_code}/` - 支持沪深A股及科创板市场 - 提供实时行情、技术分析和资金流向数据 ## 自选股管理 ### 文件格式 自选股存储在 `~/.clawdbot/stock_watcher/watchlist.txt`： ``` 600053|九鼎投资 600018|上港集团 688785|恒运昌 ``` ### 支持操作 1. **添加股票**: 验证股票代码格式并添加到自选股 2. **删除股票**: 按股票代码精确匹配删除 3. **查看列表**: 显示当前自选股 4. **清空列表**: 完全清空自选股 5. **行情总结**: 获取所有股票的最新数据并提供简洁摘要 ## 行情摘要特点 - 直接显示关键行情指标，无冗余信息 - 提供股票详情链接便于深入查看 - 自动处理网络错误和数据异常 - 合理控制请求频率（每秒1次） ## 注意事项 - **股票代码格式**: 使用6位数字代码（如 `600053`） - **数据延迟**: 行情可能有1-3分钟延迟 - **网络依赖**: 需要网络连接获取实时数据 - **市场范围**: 主要支持A股市场（沪市/深市/科创板） ## 安装与卸载 ### 安装 运行 `scripts/install.sh` 脚本自动创建必要的目录结构。 ### 卸载 运行 `scripts/uninstall.sh` 脚本完全移除所有相关文件。 ## 脚本说明 所有脚本都使用统一的配置文件 `config.py` 来管理存储路径，确保路径一致性： - `add_stock.py` - 添加股票到自选股 - `remove_stock.py` - 从自选股删除股票 - `list_stocks.py` - 列出所有自选股 - `clear_watchlist.py` - 清空自选股列表 - `summarize_performance.py` - 获取股票行情摘要

path: README.md
content: # Stock Watcher Skill

A standardized stock watchlist management skill for Clawdbot that provides clean, consistent functionality for tracking Chinese A-share stocks.

## Features

- ✅ **Add stocks** to watchlist using 6-digit stock codes
- ✅ **View watchlist** with clear formatting
- ✅ **Remove individual stocks** from watchlist
- ✅ **Clear entire watchlist** with one command
- ✅ **Get performance summary** for all watched stocks
- ✅ **Standardized storage path** - no more path confusion!
- ✅ **Easy installation/uninstallation**

## Installation

For new users, the skill will be automatically installed when first used. The installation script creates:

- Standardized watchlist directory: `~/.clawdbot/stock_watcher/`
- Watchlist file: `~/.clawdbot/stock_watcher/watchlist.txt`
- All necessary scripts in the skill directory

## Usage Commands

### Add a stock
```bash
cd ~/.clawdbot/skills/stock-watcher/scripts && python3 add_stock.py 600053
```

### View watchlist
```bash
cd ~/.clawdbot/skills/stock-watcher/scripts && python3 list_stocks.py
```

### Remove a stock
```bash
cd ~/.clawdbot/skills/stock-watcher/scripts && python3 remove_stock.py 600053
```

### Clear watchlist
```bash
cd ~/.clawdbot/skills/stock-watcher/scripts && python3 clear_watchlist.py
```

### Get performance summary
```bash
cd ~/.clawdbot/skills/stock-watcher/scripts && python3 summarize_performance.py
```

## Data Source

- **Primary source**: 同花顺 (10jqka.com.cn)
- **Stock pages**: `https://stockpage.10jqka.com.cn/{stock_code}/`
- **Supported markets**: Shanghai A-shares, Shenzhen A-shares, STAR Market

## File Structure

```
stock-watcher/
├── SKILL.md                 # Skill metadata and instructions
├── scripts/
│   ├── config.py           # Centralized configuration
│   ├── add_stock.py        # Add stock to watchlist
│   ├── list_stocks.py      # List all stocks in watchlist
│   ├── remove_stock.py     # Remove specific stock
│   ├── clear_watchlist.py  # Clear entire watchlist
│   ├── summarize_performance.py # Get stock performance data
│   ├── install.sh          # Installation script
│   └── uninstall.sh        # Uninstallation script
└── references/             # (Reserved for future reference docs)
```

## Storage Location

All user data is stored in a single, standardized location:
- **Directory**: `~/.clawdbot/stock_watcher/`
- **Watchlist file**: `~/.clawdbot/stock_watcher/watchlist.txt`

Format: `stock_code|stock_name` (e.g., `600053|九鼎投资`)

## Troubleshooting

### "Command not found" errors
Ensure you have Python 3 and required packages installed:
```bash
pip3 install requests beautifulsoup4
```

### Network issues
The skill fetches data from 10jqka.com.cn. Ensure you have internet access and the site is accessible.

### Permission errors
Make sure the `~/.clawdbot/` directory is writable by your user.

## Uninstallation

To completely remove the skill and all data:
```bash
cd ~/.clawdbot/skills/stock-watcher/scripts && ./uninstall.sh
```

This will remove both the skill scripts and your watchlist data.

path: scripts/add_stock.py
content: #!/usr/bin/env python3
"""
Add stock to watchlist
Usage: python3 add_stock.py <stock_code> [stock_name]
"""
import sys
import os
import requests
from bs4 import BeautifulSoup
from config import WATCHLIST_FILE

def get_stock_name_from_code(stock_code):
    """Get stock name from 10jqka.com.cn using stock code"""
    try:
        url = f"https://stockpage.10jqka.com.cn/{stock_code}/"
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
        response = requests.get(url, headers=headers, timeout=10)
        response.encoding = 'utf-8'
        
        if response.status_code == 200:
            soup = BeautifulSoup(response.text, 'html.parser')
            title = soup.find('title')
            if title:
                title_text = title.get_text()
                if '(' in title_text and ')' in title_text:
                    stock_name = title_text.split('(')[0].strip()
                    return stock_name
    except Exception as e:
        pass
    return None

def add_stock(stock_code, stock_name=None):
    """Add stock to watchlist.txt in the correct location"""
    # Ensure the directory exists
    os.makedirs(os.path.dirname(WATCHLIST_FILE), exist_ok=True)
    
    # Get stock name if not provided
    if not stock_name:
        stock_name = get_stock_name_from_code(stock_code)
        if not stock_name:
            stock_name = stock_code  # fallback to code if name cannot be fetched
    
    # Read existing watchlist
    existing_stocks = []
    if os.path.exists(WATCHLIST_FILE):
        with open(WATCHLIST_FILE, 'r', encoding='utf-8') as f:
            for line in f:
                line = line.strip()
                if line:
                    existing_stocks.append(line)
    
    # Check if stock already exists
    stock_entry = f"{stock_code}|{stock_name}"
    stock_exists = False
    for existing in existing_stocks:
        if existing.startswith(f"{stock_code}|"):
            stock_exists = True
            break
    
    if stock_exists:
        print(f"Stock {stock_code} already in watchlist")
        return False
    
    # Add new stock
    existing_stocks.append(stock_entry)
    
    # Write back to file with proper newlines
    with open(WATCHLIST_FILE, 'w', encoding='utf-8') as f:
        for stock in existing_stocks:
            f.write(stock + '\n')
    
    print(f"Added stock {stock_code} ({stock_name}) to watchlist")
    return True

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python3 add_stock.py <stock_code> [stock_name]")
        sys.exit(1)
    
    stock_code = sys.argv[1]
    stock_name = sys.argv[2] if len(sys.argv) > 2 else None
    add_stock(stock_code, stock_name)

path: scripts/clear_watchlist.py
content: #!/usr/bin/env python3
"""
Clear the entire watchlist.
This script removes all stocks from the watchlist file.
"""
import os
import sys

# Define the watchlist file path directly
WATCHLIST_FILE = os.path.expanduser("~/.clawdbot/stock_watcher/watchlist.txt")

def clear_watchlist():
    """Clear the entire watchlist."""
    # Ensure the directory exists
    os.makedirs(os.path.dirname(WATCHLIST_FILE), exist_ok=True)
    
    # Clear the file by opening in write mode and closing immediately
    with open(WATCHLIST_FILE, 'w', encoding='utf-8') as f:
        pass
    
    print("Watchlist cleared successfully.")

if __name__ == "__main__":
    clear_watchlist()

path: scripts/config.py
content: #!/usr/bin/env python3
"""
Configuration for stock-watcher skill.
Centralized configuration to avoid path confusion.
"""
import os

# Standardized watchlist file path
WATCHLIST_DIR = os.path.expanduser("~/.clawdbot/stock_watcher")
WATCHLIST_FILE = os.path.join(WATCHLIST_DIR, "watchlist.txt")

# Ensure directory exists
os.makedirs(WATCHLIST_DIR, exist_ok=True)

path: scripts/install.sh
content: #!/bin/bash
# Install stock-watcher skill dependencies and initialize watchlist directory

set -e

echo "Installing stock-watcher skill dependencies..."

# Create the watchlist directory
mkdir -p ~/.clawdbot/stock_watcher

# Create empty watchlist file if it doesn't exist
WATCHLIST_FILE="$HOME/.clawdbot/stock_watcher/watchlist.txt"
if [ ! -f "$WATCHLIST_FILE" ]; then
    touch "$WATCHLIST_FILE"
    echo "Created empty watchlist file: $WATCHLIST_FILE"
fi

# Check if required Python packages are available
if ! python3 -c "import requests, bs4" 2>/dev/null; then
    echo "Warning: Required Python packages (requests, beautifulsoup4) not found."
    echo "You may need to install them with: pip install requests beautifulsoup4"
fi

echo "Stock-watcher skill installed successfully!"
echo "Watchlist directory: ~/.clawdbot/stock_watcher/"
echo "Watchlist file: ~/.clawdbot/stock_watcher/watchlist.txt"

path: scripts/list_stocks.py
content: #!/usr/bin/env python3
"""
List all stocks in the user's watchlist.
This script reads from the standard watchlist file and displays the current watchlist.
"""
import sys
import os

# Standardized watchlist file path
WATCHLIST_FILE = os.path.expanduser("~/.clawdbot/stock_watcher/watchlist.txt")

def list_stocks():
    """List all stocks in the watchlist."""
    if not os.path.exists(WATCHLIST_FILE):
        print("Watchlist is empty.")
        return
    
    with open(WATCHLIST_FILE, 'r', encoding='utf-8') as f:
        lines = [line.strip() for line in f if line.strip()]
    
    if not lines:
        print("Watchlist is empty.")
        return
    
    print("Your Stock Watchlist:")
    print("-" * 40)
    for i, line in enumerate(lines, 1):
        parts = line.split('|')
        if len(parts) == 2:
            code, name = parts
            print(f"{i}. {code} - {name}")
        else:
            print(f"{i}. {line}")

if __name__ == "__main__":
    list_stocks()

path: scripts/remove_stock.py
content: #!/usr/bin/env python3
"""
Remove stock from watchlist
Usage: python3 remove_stock.py <stock_code>
"""
import sys
import os

# Standardized watchlist file path
WATCHLIST_DIR = os.path.expanduser("~/.clawdbot/stock_watcher")
WATCHLIST_FILE = os.path.join(WATCHLIST_DIR, "watchlist.txt")

def remove_stock(stock_code):
    """Remove stock from watchlist."""
    if not os.path.exists(WATCHLIST_FILE):
        print("Watchlist is empty.")
        return False
    
    # Read existing watchlist
    existing_stocks = []
    with open(WATCHLIST_FILE, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            if line:
                existing_stocks.append(line)
    
    # Find and remove the stock
    stock_found = False
    updated_stocks = []
    for stock in existing_stocks:
        if stock.startswith(f"{stock_code}|"):
            stock_found = True
        else:
            updated_stocks.append(stock)
    
    if not stock_found:
        print(f"Stock {stock_code} not found in watchlist")
        return False
    
    # Write back to file
    with open(WATCHLIST_FILE, 'w', encoding='utf-8') as f:
        for stock in updated_stocks:
            f.write(stock + '\n')
    
    print(f"Removed stock {stock_code} from watchlist")
    return True

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python3 remove_stock.py <stock_code>")
        sys.exit(1)
    
    stock_code = sys.argv[1]
    remove_stock(stock_code)

path: scripts/summarize_performance.py
content: #!/usr/bin/env python3
"""
Summarize the performance of all stocks in the watchlist.
This script fetches current stock data from 10jqka.com.cn for each stock
in the watchlist and provides a summary of their recent performance.
"""
import os
import sys
import requests
from bs4 import BeautifulSoup
import time

# Standardized watchlist file path
WATCHLIST_FILE = os.path.expanduser("~/.clawdbot/stock_watcher/watchlist.txt")

def fetch_stock_data(stock_code):
    """Fetch stock data from 10jqka.com.cn."""
    url = f"https://stockpage.10jqka.com.cn/{stock_code}/"
    
    try:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
        response = requests.get(url, headers=headers, timeout=10)
        response.encoding = 'utf-8'
        
        if response.status_code != 200:
            return None
            
        soup = BeautifulSoup(response.text, 'html.parser')
        
        # Extract basic info
        title = soup.find('title')
        stock_name = ""
        if title:
            title_text = title.get_text()
            if '(' in title_text and ')' in title_text:
                stock_name = title_text.split('(')[0].strip()
        
        # Look for performance data
        performance_data = {}
        
        # Try to find recent performance indicators
        # This is a simplified version - in practice, you'd need more robust parsing
        text_content = soup.get_text()
        
        # Look for key phrases
        if '涨跌幅' in text_content:
            # Extract percentage changes
            import re
            percentages = re.findall(r'[-+]?\d+\.?\d*%', text_content)
            if percentages:
                performance_data['recent_changes'] = percentages[:3]  # Get first 3 percentages
        
        return {
            'code': stock_code,
            'name': stock_name,
            'url': url,
            'performance': performance_data
        }
        
    except Exception as e:
        print(f"Error fetching data for {stock_code}: {e}", file=sys.stderr)
        return None

def summarize_performance():
    """Summarize performance of all stocks in watchlist."""
    if not os.path.exists(WATCHLIST_FILE):
        return
    
    with open(WATCHLIST_FILE, 'r', encoding='utf-8') as f:
        lines = f.readlines()
    
    if not lines or all(not line.strip() for line in lines):
        return
    
    # Directly output performance summary without any command prompts
    for line in lines:
        line = line.strip()
        if line:
            parts = line.split('|')
            if len(parts) == 2:
                code, name = parts
                
                # Fetch data
                stock_data = fetch_stock_data(code)
                if stock_data:
                    if stock_data['performance']:
                        for i, change in enumerate(stock_data['performance'].get('recent_changes', []), 1):
                            print(f"{code} - {name} - 指标{i}: {change}")
                    else:
                        print(f"{code} - {name} - 行情数据暂不可用")
                else:
                    print(f"{code} - {name} - 获取数据失败")
                
                # Be respectful to the server
                time.sleep(1)

if __name__ == "__main__":
    summarize_performance()

path: scripts/uninstall.sh
content: #!/bin/bash
# Uninstall stock-watcher skill

set -e

# Remove watchlist directory and files
WATCHLIST_DIR="$HOME/.clawdbot/stock_watcher"
if [ -d "$WATCHLIST_DIR" ]; then
    rm -rf "$WATCHLIST_DIR"
    echo "Removed watchlist directory: $WATCHLIST_DIR"
fi

echo "Stock watcher skill uninstalled successfully."

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