Skill: same1317/stock-a (version 1.0.0)

# Stock-A Skill 💼 A股股票行情数据获取工具，支持多个免费数据源。 ## 功能 - **实时行情** - 获取个股实时价格、涨跌幅、成交量等 - **历史K线** - 获取日线/周线/月线历史数据 - **多数据源** - mootdx、新浪财经、腾讯财经、东方财富、Tushare --- ## 📊 数据源汇总 ### 1. mootdx（通达信/同花顺）⭐ 推荐 | 功能 | 状态 | 说明 | |------|------|------| | 实时行情 | ✅ 可用 | 默认数据源，需本地安装 | | 历史K线 | ✅ 可用 | 支持日线/周线/月线 | | F分钟线 | ✅ 可用 | 1/5/15/30/60分钟 | | 财务数据 | ✅ 可用 | 财务指标、利润表等 | ```bash # mootdx 实时行情 python -c " from mootdx import quotes q = quotes.StdQuotes() result = q.daily(symbol='600519') print(result) " # mootdx 历史K线 python -c " from mootdx import reader r = reader.Reader() df = r.daily(symbol='600519', adjust='qfq') print(df.tail()) " ``` --- ### 2. 新浪财经 | 功能 | 状态 | 说明 | |------|------|------| | 实时行情 | ✅ 可用 | 推荐使用 | | 历史K线 | ✅ 可用 | | ```bash # 新浪财经 - 实时行情 (推荐) python scripts/sina_realtime.py sh600519 # 新浪财经 - 历史K线 python scripts/sina_history.py sh600519 2024-03-01 2024-03-25 ``` --- ### 3. 腾讯财经 | 功能 | 状态 | 说明 | |------|------|------| | 实时行情 | ✅ 可用 | | ```bash # 腾讯财经 - 实时行情 python scripts/tengxun_realtime.py sh600519 ``` --- ### 4. 东方财富 | 功能 | 状态 | 说明 | |------|------|------| | 实时行情 | ⚠️ 不稳定 | 需网络稳定环境 | ```bash # 东方财富 - 实时行情 python scripts/eastmoney_realtime.py sh600519 ``` --- ### 5. Tushare | 功能 | 状态 | 说明 | |------|------|------| | 实时行情 | ⚠️ 备用 | 即将停用，免费Token | ```bash # Tushare - 实时行情 python scripts/tushare_realtime.py 600519 ``` --- ## 📋 数据源测试结果汇总 | 数据源 | 实时行情 | 历史K线 | 财务数据 | 状态 | |--------|----------|---------|----------|------| | **mootdx** | ✅ | ✅ | ✅ | ⭐ 推荐 | | 新浪财经 | ✅ | ✅ | ❌ | ✅ 可用 | | 腾讯财经 | ✅ | ❌ | ❌ | ✅ 可用 | | 东方财富 | ⚠️ | ❌ | ❌ | ⚠️ 不稳定 | | Tushare | ⚠️ | ❌ | ❌ | ⚠️ 备用 | | 网易财经 | ❌ | ❌ | ❌ | ❌ 502错误 | | Tushare Pro | ❌ | ❌ | ❌ | ❌ 需Token | --- ## 🔧 代码说明 - `sh600519` - 上海市场 (60xxxx) - `sz000001` - 深圳市场 (00xxxx) - `sz300750` - 创业板 (30xxxx) - `bjxxxx` - 北交所 (8xxxx/4xxxx) --- ## 📖 使用示例 ### 实时行情输出示例 ``` 贵州茅台 (SH600519) ============================== 最新价: 1408.81 涨跌: +1.48 涨跌幅: +0.11% 开盘: 1410.11 最高: 1417.87 最低: 1401.01 成交量: 1,409手 成交额: 157.35亿 ``` --- ## 安装新数据源 ```bash # 安装 mootdx (如未安装) pip install mootdx # 安装 Tushare (备用) pip install tushare ```

path: scripts/eastmoney_realtime.py
content: #!/usr/bin/env python3
"""
东方财富实时行情 (通过同花顺接口)
用法: python eastmoney_realtime.py <股票代码>
示例: python eastmoney_realtime.py sh600519
"""
import sys
import requests
import json

def get_realtime(code):
    # 转换代码格式
    if code.startswith('sh'):
        secid = f"1.{code[2:]}"
    elif code.startswith('sz'):
        secid = f"0.{code[2:]}"
    else:
        return {"error": "代码格式错误"}
    
    url = "https://push2.eastmoney.com/api/qt/stock/get"
    params = {
        "secid": secid,
        "fields": "f43,f44,f45,f46,f47,f48,f49,f50,f51,f52,f57,f58,f59,f60,f116,f117,f118,f162,f167,f168,f169,f170,f171,f173,f177"
    }
    
    r = requests.get(url, params=params, timeout=10)
    data = r.json()
    
    if data.get("data") is None:
        return {"error": "未获取到数据"}
    
    d = data["data"]
    
    return {
        "code": code,
        "name": d.get("f58", ""),
        "price": d.get("f43", 0) / 100,  # 分转元
        "change": d.get("f46", 0) / 100,
        "pct_change": d.get("f45", 0) / 100,
        "volume": d.get("f47", 0),
        "amount": d.get("f48", 0) / 100000000,  # 亿元
        "open": d.get("f50", 0) / 100,
        "high": d.get("f44", 0) / 100,
        "low": d.get("f45", 0) / 100,
        "pre_close": d.get("f52", 0) / 100,
    }

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("用法: python eastmoney_realtime.py <股票代码>")
        print("示例: python eastmoney_realtime.py sh600519")
        sys.exit(1)
    
    code = sys.argv[1]
    result = get_realtime(code)
    
    if "error" in result:
        print(f"错误: {result['error']}")
        sys.exit(1)
    
    print(f"{result['name']} ({result['code'].upper()})")
    print("=" * 30)
    print(f"最新价: {result['price']:.2f}")
    print(f"涨跌: {result['change']:+.2f}")
    print(f"涨跌幅: {result['pct_change']:+.2f}%")
    print(f"开盘: {result['open']:.2f}")
    print(f"最高: {result['high']:.2f}")
    print(f"最低: {result['low']:.2f}")
    print(f"成交量: {result['volume']:,}手")
    print(f"成交额: {result['amount']:.2f}亿")


path: scripts/sina_history.py
content: #!/usr/bin/env python3
"""
新浪财经历史K线
用法: python sina_history.py <股票代码> <开始日期> <结束日期>
示例: python sina_history.py sh600519 20240101 20240325
"""
import sys
import requests
import json
import urllib.parse

def get_history(code, start_date, end_date):
    # scale: 240=日线, 1440=周线, 4320=月线
    url = "https://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData"
    params = {
        "symbol": code,
        "scale": "240",
        "ma": "no",
        "datalen": "1024"
    }
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
        'Referer': 'https://finance.sina.com.cn/'
    }
    
    r = requests.get(url, params=params, headers=headers, timeout=10)
    data = r.json()
    
    if not isinstance(data, list):
        return {"error": data.get("error", "获取失败")}
    
    # 筛选日期范围 (日期格式: 2026-01-06)
    start = start_date.replace('/', '-')
    end = end_date.replace('/', '-')
    
    result = []
    for item in data:
        day = item.get('day', '')
        # 处理日期格式转换 20240301 -> 2024-03-01
        if len(day) == 10:
            if start <= day <= end:
                result.append({
                    "date": day,
                    "open": float(item.get('open', 0)),
                    "high": float(item.get('high', 0)),
                    "low": float(item.get('low', 0)),
                    "close": float(item.get('close', 0)),
                    "volume": int(item.get('volume', 0))
                })
    
    return result[:500]  # 限制返回数量

if __name__ == "__main__":
    if len(sys.argv) < 4:
        print("用法: python sina_history.py <股票代码> <开始日期> <结束日期>")
        print("示例: python sina_history.py sh600519 2024-03-01 2024-03-25")
        sys.exit(1)
    
    code = sys.argv[1]
    start_date = sys.argv[2]
    end_date = sys.argv[3]
    
    result = get_history(code, start_date, end_date)
    
    if "error" in result:
        print(f"错误: {result['error']}")
        sys.exit(1)
    
    print(f"获取到 {len(result)} 条K线数据")
    print(json.dumps(result[:5], ensure_ascii=False, indent=2))
    if len(result) > 5:
        print("...")


path: scripts/sina_realtime.py
content: #!/usr/bin/env python3
"""
新浪财经实时行情
用法: python sina_realtime.py <股票代码>
示例: python sina_realtime.py sh600519
"""
import sys
import requests
import json

def get_realtime(code):
    url = f"https://hq.sinajs.cn/list={code}"
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
        'Referer': 'https://finance.sina.com.cn/'
    }
    
    r = requests.get(url, headers=headers, timeout=10)
    text = r.text
    
    if 'var hq_str_' not in text:
        return {"error": "未获取到数据"}
    
    # 解析: 贵州茅台,1410.110,1407.330,1408.810,1417.870,1401.010,1408.810,1409.270,1573458,221...
    data = text.split('"')[1].split(',')
    
    if len(data) < 10:
        return {"error": "数据格式错误"}
    
    name = data[0]
    open_price = float(data[1])
    pre_close = float(data[2])
    price = float(data[3])
    high = float(data[4])
    low = float(data[5])
    volume = int(float(data[7]))  # 处理可能的浮点数
    amount = float(data[8]) / 10000  # 亿元
    
    change = price - pre_close
    pct_change = (change / pre_close) * 100
    
    return {
        "code": code,
        "name": name,
        "price": price,
        "open": open_price,
        "pre_close": pre_close,
        "high": high,
        "low": low,
        "change": round(change, 2),
        "pct_change": round(pct_change, 2),
        "volume": volume,
        "amount": round(amount, 2)
    }

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("用法: python sina_realtime.py <股票代码>")
        print("示例: python sina_realtime.py sh600519")
        sys.exit(1)
    
    code = sys.argv[1]
    result = get_realtime(code)
    
    if "error" in result:
        print(f"错误: {result['error']}")
        sys.exit(1)
    
    print(f"{result['name']} ({result['code'].upper()})")
    print("=" * 30)
    print(f"最新价: {result['price']:.2f}")
    print(f"涨跌: {result['change']:+.2f}")
    print(f"涨跌幅: {result['pct_change']:+.2f}%")
    print(f"开盘: {result['open']:.2f}")
    print(f"最高: {result['high']:.2f}")
    print(f"最低: {result['low']:.2f}")
    print(f"成交量: {result['volume']:,}手")
    print(f"成交额: {result['amount']:.2f}亿")


path: scripts/tengxun_realtime.py
content: #!/usr/bin/env python3
"""
腾讯财经实时行情
用法: python tengxun_realtime.py <股票代码>
示例: python tengxun_realtime.py sh600519
"""
import sys
import requests
import json

def get_realtime(code):
    url = f"https://qt.gtimg.cn/q={code}"
    r = requests.get(url, timeout=10)
    text = r.text
    
    if 'v_' not in text:
        return {"error": "未获取到数据"}
    
    # 解析格式: v_sh600519="1~贵州茅台~600519~1408.81~1407.33~1410.11~15735~7810~7925~1408.81~..."
    # 字段: 0市场,1名称,2代码,3当前价,4昨收,5开盘,6成交量,7成交额,8内盘,9最高,10最低...
    raw = text.split('"')[1]
    data = raw.split('~')
    
    if len(data) < 11:
        return {"error": "数据格式错误"}
    
    name = data[1]
    price = float(data[3]) if data[3] else 0
    pre_close = float(data[4]) if data[4] else 0
    open_price = float(data[5]) if data[5] else 0
    volume = int(float(data[6])) if data[6] else 0
    amount = float(data[7]) / 1000 if data[7] else 0  # 千元转为万元
    high = float(data[9]) if data[9] else 0
    low = float(data[10]) if data[10] else 0
    
    change = price - pre_close
    pct_change = (change / pre_close * 100) if pre_close else 0
    
    return {
        "code": code,
        "name": name,
        "price": price,
        "change": round(change, 2),
        "pct_change": round(pct_change, 2),
        "volume": volume,
        "amount": round(amount, 2),
        "open": open_price,
        "high": high,
        "low": low,
        "pre_close": pre_close
    }

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("用法: python tengxun_realtime.py <股票代码>")
        print("示例: python tengxun_realtime.py sh600519")
        sys.exit(1)
    
    code = sys.argv[1]
    result = get_realtime(code)
    
    if "error" in result:
        print(f"错误: {result['error']}")
        sys.exit(1)
    
    print(f"{result['name']} ({result['code'].upper()})")
    print("=" * 30)
    print(f"最新价: {result['price']:.2f}")
    print(f"涨跌: {result['change']:+.2f}")
    print(f"涨跌幅: {result['pct_change']:+.2f}%")
    print(f"开盘: {result['open']:.2f}")
    print(f"最高: {result['high']:.2f}")
    print(f"最低: {result['low']:.2f}")
    print(f"昨收: {result['pre_close']:.2f}")
    print(f"成交量: {result['volume']:,}手")
    print(f"成交额: {result['amount']:.2f}万")


path: scripts/tushare_realtime.py
content: #!/usr/bin/env python3
"""
Tushare普通接口实时行情 (即将停用,作为备用)
用法: python tushare_realtime.py <股票代码>
示例: python tushare_realtime.py 600519
"""
import sys
import tushare as ts
import warnings
warnings.filterwarnings('ignore')

def get_realtime(code):
    # 代码转换 600519 -> 600519
    if '.' in code:
        code = code.split('.')[0].replace('sh', '').replace('sz', '')
    
    try:
        df = ts.get_realtime_quotes(code)
        if df.empty:
            return {"error": "未获取到数据"}
        
        row = df.iloc[0]
        price = float(row['price'])
        pre_close = float(row['pre_close'])
        change = price - pre_close
        pct_change = (change / pre_close * 100) if pre_close else 0
        
        return {
            "code": code,
            "name": row['name'],
            "price": price,
            "change": round(change, 2),
            "pct_change": round(pct_change, 2),
            "open": float(row['open']),
            "high": float(row['high']),
            "low": float(row['low']),
            "volume": int(float(row['volume'])),
            "amount": float(row['amount']) / 10000,  # 万元
            "pre_close": pre_close,
            "warning": "此接口即将停用,建议使用Pro版"
        }
    except Exception as e:
        return {"error": str(e)[:50]}

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("用法: python tushare_realtime.py <股票代码>")
        print("示例: python tushare_realtime.py 600519")
        sys.exit(1)
    
    code = sys.argv[1]
    result = get_realtime(code)
    
    if "error" in result:
        print(f"错误: {result['error']}")
        sys.exit(1)
    
    print(f"{result['name']} ({result['code']})")
    print("=" * 30)
    print(f"最新价: {result['price']:.2f}")
    print(f"涨跌: {result['change']:+.2f}")
    print(f"涨跌幅: {result['pct_change']:+.2f}%")
    print(f"开盘: {result['open']:.2f}")
    print(f"最高: {result['high']:.2f}")
    print(f"最低: {result['low']:.2f}")
    print(f"昨收: {result['pre_close']:.2f}")
    print(f"成交量: {result['volume']:,}手")
    print(f"成交额: {result['amount']:.2f}万")
    print("⚠️", result.get("warning", ""))


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