openclaw 盯盘实践

0 阅读10分钟

openclaw 盯盘实践

image.png

image.png

动态生成的脚本(大家可以拿去直接使用)

/root/gupiao/get_limit_up.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
获取东方财富网涨停股数据并保存为 Excel - 备用版本
"""

import requests
import pandas as pd
from datetime import datetime
import time

def get_limit_up_stocks_v2():
    """获取涨停股数据 - 备用方法"""
    
    # 使用涨停池 API
    url = "https://data-interface.eastmoney.com/SEC_Security/GetZTList"
    
    params = {
        'callback': 'jQuery',
        'type': 'ZT',
        'page': '1',
        'pageSize': '100',
        'field': 'SECURITY_CODE,SECURITY_NAME,NEW_PRICE,CHANGE_RATE,CHANGE_AMOUNT,VOLUME,DEAL_AMOUNT',
        '_': int(datetime.now().timestamp() * 1000)
    }
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Referer': 'https://data.eastmoney.com/stock/ztpool/SH.html'
    }
    
    try:
        response = requests.get(url, params=params, headers=headers, timeout=15)
        response.raise_for_status()
        text = response.text
        
        # 解析 JSONP
        if text.startswith('jQuery'):
            text = text[6:]  # 去掉 'jQuery'
        if text.startswith('(') and text.endswith(')'):
            text = text[1:-1]  # 去掉括号
        
        import json
        data = json.loads(text)
        
        if data.get('data'):
            return data['data']
        return []
    except Exception as e:
        print(f"备用 API 失败:{e}")
        return []

def get_limit_up_stocks_v3():
    """获取涨停股数据 - 直接获取 HTML 并解析"""
    
    url = "https://quote.eastmoney.com/center/gridlist.html"
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    }
    
    try:
        # 获取涨停股列表 API
        api_url = "https://push2.eastmoney.com/api/qt/clist/get"
        params = {
            'pn': '1',
            'pz': '100',
            'po': '1',
            'np': '1',
            'ut': 'bd1d9ddb04089700cf9c27f6f7426281',
            'fltt': '2',
            'invt': '2',
            'fid': 'f3',
            'fs': 'm:0+t:6,m:0+t:80,m:1+t:2',
            'fields': 'f12,f14,f2,f3,f4,f10,f15,f16,f17,f18,f20,f21,f22,f23,f24,f25,f26',
            '_': str(int(datetime.now().timestamp() * 1000))
        }
        
        response = requests.get(api_url, params=params, headers=headers, timeout=15)
        response.raise_for_status()
        data = response.json()
        
        if data.get('data') and data['data'].get('diff'):
            return data['data']['diff']
        return []
    except Exception as e:
        print(f"API v3 失败:{e}")
        return []

def get_hot_sectors():
    """获取热门板块数据"""
    
    # 概念板块
    url = "https://push2.eastmoney.com/api/qt/clist/get"
    
    params = {
        'pn': '1',
        'pz': '100',
        'po': '1',
        'np': '1',
        'ut': 'bd1d9ddb04089700cf9c27f6f7426281',
        'fltt': '2',
        'invt': '2',
        'fid': 'f3',
        'fs': 'm:90+t:2',  # 概念板块
        'fields': 'f12,f14,f2,f3,f4,f10,f15,f16,f17,f18,f20,f21,f22',
        '_': str(int(datetime.now().timestamp() * 1000))
    }
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    }
    
    try:
        response = requests.get(url, params=params, headers=headers, timeout=15)
        response.raise_for_status()
        data = response.json()
        
        if data.get('data') and data['data'].get('diff'):
            return data['data']['diff']
        return []
    except Exception as e:
        print(f"获取板块失败:{e}")
        return []

def get_industry_sectors():
    """获取行业板块数据"""
    
    url = "https://push2.eastmoney.com/api/qt/clist/get"
    
    params = {
        'pn': '1',
        'pz': '100',
        'po': '1',
        'np': '1',
        'ut': 'bd1d9ddb04089700cf9c27f6f7426281',
        'fltt': '2',
        'invt': '2',
        'fid': 'f3',
        'fs': 'm:90+t:1',  # 行业板块
        'fields': 'f12,f14,f2,f3,f4,f10,f15',
        '_': str(int(datetime.now().timestamp() * 1000))
    }
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    }
    
    try:
        response = requests.get(url, params=params, headers=headers, timeout=15)
        response.raise_for_status()
        data = response.json()
        
        if data.get('data') and data['data'].get('diff'):
            return data['data']['diff']
        return []
    except Exception as e:
        print(f"获取行业板块失败:{e}")
        return []

def create_excel(stocks, concept_sectors, industry_sectors, filename):
    """创建 Excel 文件"""
    
    # 准备股票数据 - 筛选涨停股(涨跌幅 >= 9.5%)
    stock_data = []
    for stock in stocks:
        change_rate = float(stock.get('f3', 0) or 0)
        if change_rate >= 9.5:
            stock_data.append({
                '股票代码': stock.get('f12', ''),
                '股票名称': stock.get('f14', ''),
                '最新价': float(stock.get('f2', 0) or 0),
                '涨跌幅%': change_rate,
                '涨跌额': float(stock.get('f4', 0) or 0),
                '成交量': int(stock.get('f10', 0) or 0),
                '成交额': float(stock.get('f15', 0) or 0),
                '振幅%': float(stock.get('f16', 0) or 0),
                '最高价': float(stock.get('f17', 0) or 0),
                '最低价': float(stock.get('f18', 0) or 0),
                '总市值': float(stock.get('f20', 0) or 0),
                '流通市值': float(stock.get('f21', 0) or 0),
            })
    
    # 准备概念板块数据
    concept_data = []
    for sector in concept_sectors:
        change_rate = float(sector.get('f3', 0) or 0)
        if change_rate > 0:
            concept_data.append({
                '板块代码': sector.get('f12', ''),
                '板块名称': sector.get('f14', ''),
                '最新价': float(sector.get('f2', 0) or 0),
                '涨跌幅%': change_rate,
                '涨跌额': float(sector.get('f4', 0) or 0),
                '成交量': int(sector.get('f10', 0) or 0),
                '成交额': float(sector.get('f15', 0) or 0),
            })
    
    # 准备行业板块数据
    industry_data = []
    for sector in industry_sectors:
        change_rate = float(sector.get('f3', 0) or 0)
        if change_rate > 0:
            industry_data.append({
                '板块代码': sector.get('f12', ''),
                '板块名称': sector.get('f14', ''),
                '最新价': float(sector.get('f2', 0) or 0),
                '涨跌幅%': change_rate,
                '涨跌额': float(sector.get('f4', 0) or 0),
                '成交量': int(sector.get('f10', 0) or 0),
                '成交额': float(sector.get('f15', 0) or 0),
            })
    
    # 排序
    stock_data.sort(key=lambda x: x['涨跌幅%'], reverse=True)
    concept_data.sort(key=lambda x: x['涨跌幅%'], reverse=True)
    industry_data.sort(key=lambda x: x['涨跌幅%'], reverse=True)
    
    # 创建 Excel
    with pd.ExcelWriter(filename, engine='openpyxl') as writer:
        # 涨停股数据
        if stock_data:
            df_stocks = pd.DataFrame(stock_data)
            df_stocks.to_excel(writer, sheet_name='涨停股', index=False)
        else:
            # 创建空 sheet
            pd.DataFrame({'提示': ['今日暂无涨停股数据']}).to_excel(writer, sheet_name='涨停股', index=False)
        
        # 概念板块
        if concept_data:
            df_concept = pd.DataFrame(concept_data[:50])
            df_concept.to_excel(writer, sheet_name='热门概念板块', index=False)
        
        # 行业板块
        if industry_data:
            df_industry = pd.DataFrame(industry_data[:50])
            df_industry.to_excel(writer, sheet_name='热门行业板块', index=False)
    
    return len(stock_data), len(concept_data), len(industry_data)

def main():
    print("=" * 50)
    print("股票涨停数据分析工具")
    print("=" * 50)
    
    # 获取股票数据 - 尝试多次
    print("\n正在获取股票数据...")
    stocks = []
    for i in range(3):
        if i > 0:
            print(f"重试第 {i} 次...")
            time.sleep(2)
        stocks = get_limit_up_stocks_v3()
        if stocks:
            print(f"成功获取 {len(stocks)} 只股票数据")
            break
    
    if not stocks:
        print("警告:无法获取股票数据,将只生成板块数据")
    
    # 获取概念板块
    print("\n正在获取概念板块数据...")
    concept_sectors = get_hot_sectors()
    print(f"成功获取 {len(concept_sectors)} 个概念板块")
    
    # 获取行业板块
    print("\n正在获取行业板块数据...")
    industry_sectors = get_industry_sectors()
    print(f"成功获取 {len(industry_sectors)} 个行业板块")
    
    # 生成文件名
    today = datetime.now().strftime('%Y%m%d')
    filename = f'/root/gupiao/{today}_涨停股分析.xlsx'
    
    print(f"\n正在生成 Excel 文件:{filename}")
    stock_count, concept_count, industry_count = create_excel(
        stocks, concept_sectors, industry_sectors, filename
    )
    
    print("\n" + "=" * 50)
    print("完成!")
    print(f"  - 涨停股:{stock_count} 只")
    print(f"  - 热门概念板块:{concept_count} 个")
    print(f"  - 热门行业板块:{industry_count} 个")
    print(f"\n文件已保存至:{filename}")
    print("=" * 50)

if __name__ == '__main__':
    main()

/root/gupiao/get_sectors.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
获取热门板块数据
"""

import requests
import pandas as pd
from datetime import datetime
import time

def get_sectors_with_retry(url_params, max_retries=5):
    """获取板块数据,带重试机制"""
    
    url = "https://push2.eastmoney.com/api/qt/clist/get"
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Accept': '*/*',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Referer': 'https://quote.eastmoney.com/',
    }
    
    for i in range(max_retries):
        try:
            if i > 0:
                print(f"  重试第 {i+1} 次...")
                time.sleep(3)
            
            response = requests.get(url, params=url_params, headers=headers, timeout=20)
            response.raise_for_status()
            data = response.json()
            
            if data.get('data') and data['data'].get('diff'):
                return data['data']['diff']
            return []
        except Exception as e:
            print(f"  尝试失败:{e}")
            continue
    
    return []

def get_concept_sectors():
    """获取概念板块"""
    print("获取概念板块...")
    params = {
        'pn': '1',
        'pz': '100',
        'po': '1',
        'np': '1',
        'ut': 'bd1d9ddb04089700cf9c27f6f7426281',
        'fltt': '2',
        'invt': '2',
        'fid': 'f3',
        'fs': 'm:90+t:2',
        'fields': 'f12,f14,f2,f3,f4,f10,f15',
        '_': str(int(datetime.now().timestamp() * 1000))
    }
    return get_sectors_with_retry(params)

def get_industry_sectors():
    """获取行业板块"""
    print("获取行业板块...")
    params = {
        'pn': '1',
        'pz': '100',
        'po': '1',
        'np': '1',
        'ut': 'bd1d9ddb04089700cf9c27f6f7426281',
        'fltt': '2',
        'invt': '2',
        'fid': 'f3',
        'fs': 'm:90+t:1',
        'fields': 'f12,f14,f2,f3,f4,f10,f15',
        '_': str(int(datetime.now().timestamp() * 1000))
    }
    return get_sectors_with_retry(params)

def get_region_sectors():
    """获取地区板块"""
    print("获取地区板块...")
    params = {
        'pn': '1',
        'pz': '100',
        'po': '1',
        'np': '1',
        'ut': 'bd1d9ddb04089700cf9c27f6f7426281',
        'fltt': '2',
        'invt': '2',
        'fid': 'f3',
        'fs': 'm:90+t:3',
        'fields': 'f12,f14,f2,f3,f4,f10,f15',
        '_': str(int(datetime.now().timestamp() * 1000))
    }
    return get_sectors_with_retry(params)

def main():
    print("=" * 50)
    print("获取板块数据")
    print("=" * 50)
    
    concept = get_concept_sectors()
    print(f"概念板块:{len(concept)} 个")
    
    industry = get_industry_sectors()
    print(f"行业板块:{len(industry)} 个")
    
    region = get_region_sectors()
    print(f"地区板块:{len(region)} 个")
    
    # 保存到 Excel
    today = datetime.now().strftime('%Y%m%d')
    filename = f'/root/gupiao/{today}_板块数据.xlsx'
    
    with pd.ExcelWriter(filename, engine='openpyxl') as writer:
        if concept:
            df = pd.DataFrame([{
                '代码': s.get('f12', ''),
                '名称': s.get('f14', ''),
                '价格': float(s.get('f2', 0) or 0),
                '涨跌幅%': float(s.get('f3', 0) or 0),
                '涨跌额': float(s.get('f4', 0) or 0),
                '成交量': int(s.get('f10', 0) or 0),
                '成交额': float(s.get('f15', 0) or 0),
            } for s in concept])
            df = df.sort_values('涨跌幅%', ascending=False)
            df.to_excel(writer, sheet_name='概念板块', index=False)
        
        if industry:
            df = pd.DataFrame([{
                '代码': s.get('f12', ''),
                '名称': s.get('f14', ''),
                '价格': float(s.get('f2', 0) or 0),
                '涨跌幅%': float(s.get('f3', 0) or 0),
                '涨跌额': float(s.get('f4', 0) or 0),
                '成交量': int(s.get('f10', 0) or 0),
                '成交额': float(s.get('f15', 0) or 0),
            } for s in industry])
            df = df.sort_values('涨跌幅%', ascending=False)
            df.to_excel(writer, sheet_name='行业板块', index=False)
        
        if region:
            df = pd.DataFrame([{
                '代码': s.get('f12', ''),
                '名称': s.get('f14', ''),
                '价格': float(s.get('f2', 0) or 0),
                '涨跌幅%': float(s.get('f3', 0) or 0),
                '涨跌额': float(s.get('f4', 0) or 0),
                '成交量': int(s.get('f10', 0) or 0),
                '成交额': float(s.get('f15', 0) or 0),
            } for s in region])
            df = df.sort_values('涨跌幅%', ascending=False)
            df.to_excel(writer, sheet_name='地区板块', index=False)
    
    print(f"\n板块数据已保存至:{filename}")

if __name__ == '__main__':
    main()

/root/gupiao/merge_report.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
合并涨停股和板块数据为完整分析报告
"""

import pandas as pd
from datetime import datetime

def main():
    today = datetime.now().strftime('%Y%m%d')
    today_cn = datetime.now().strftime('%Y年%m月%d日')
    
    # 读取数据
    limit_up_file = f'/root/gupiao/{today}_涨停股分析.xlsx'
    sectors_file = f'/root/gupiao/{today}_板块数据.xlsx'
    output_file = f'/root/gupiao/{today}_股票涨停分析报告.xlsx'
    
    print(f"正在生成 {today_cn} 股票涨停分析报告...")
    
    with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
        # 1. 封面页
        cover_data = {
            '项目': ['报告日期', '涨停股数量', '概念板块数量', '行业板块数量', '地区板块数量'],
            '数值': [today_cn, '', '', '', '']
        }
        pd.DataFrame(cover_data).to_excel(writer, sheet_name='封面', index=False)
        
        # 2. 读取涨停股数据
        try:
            df_limit = pd.read_excel(limit_up_file, sheet_name='涨停股')
            if '提示' not in df_limit.columns:
                # 按涨跌幅排序
                df_limit = df_limit.sort_values('涨跌幅%', ascending=False)
                df_limit.to_excel(writer, sheet_name='涨停股明细', index=False)
                print(f"  ✓ 涨停股:{len(df_limit)} 只")
                
                # 涨停股统计
                summary_data = []
                if '股票代码' in df_limit.columns:
                    # 按股票代码前缀统计(00=深市主板,30=创业板,60=沪市主板,68=科创板)
                    for prefix, name in [('00', '深市主板'), ('30', '创业板'), ('60', '沪市主板'), ('68', '科创板')]:
                        count = len(df_limit[df_limit['股票代码'].astype(str).str.startswith(prefix)])
                        if count > 0:
                            summary_data.append({'板块': name, '涨停数量': count})
                    
                    if summary_data:
                        pd.DataFrame(summary_data).to_excel(writer, sheet_name='涨停股统计', index=False)
        except Exception as e:
            print(f"  ✗ 读取涨停股数据失败:{e}")
        
        # 3. 读取板块数据
        try:
            # 概念板块
            df_concept = pd.read_excel(sectors_file, sheet_name='概念板块')
            df_concept = df_concept.sort_values('涨跌幅%', ascending=False)
            df_concept_top50 = df_concept.head(50)
            df_concept_top50.to_excel(writer, sheet_name='热门概念板块', index=False)
            print(f"  ✓ 概念板块:{len(df_concept)} 个")
            
            # 行业板块
            df_industry = pd.read_excel(sectors_file, sheet_name='行业板块')
            df_industry = df_industry.sort_values('涨跌幅%', ascending=False)
            df_industry.to_excel(writer, sheet_name='热门行业板块', index=False)
            print(f"  ✓ 行业板块:{len(df_industry)} 个")
            
            # 地区板块
            df_region = pd.read_excel(sectors_file, sheet_name='地区板块')
            df_region = df_region.sort_values('涨跌幅%', ascending=False)
            df_region.to_excel(writer, sheet_name='热门地区板块', index=False)
            print(f"  ✓ 地区板块:{len(df_region)} 个")
            
            # 板块涨幅前十
            top_concept = df_concept.head(10)[['名称', '涨跌幅%']].copy()
            top_concept.columns = ['概念板块', '涨跌幅%']
            top_concept['类型'] = '概念'
            
            top_industry = df_industry.head(10)[['名称', '涨跌幅%']].copy()
            top_industry.columns = ['板块', '涨跌幅%']
            top_industry['类型'] = '行业'
            
            # 合并展示
            top_all = pd.concat([
                df_concept.head(10)[['名称', '涨跌幅%']].assign(类型='概念'),
                df_industry.head(10)[['名称', '涨跌幅%']].assign(类型='行业')
            ], ignore_index=True)
            top_all = top_all.sort_values('涨跌幅%', ascending=False).head(20)
            top_all.columns = ['板块名称', '涨跌幅%', '类型']
            top_all.to_excel(writer, sheet_name='板块涨幅排行', index=False)
            
        except Exception as e:
            print(f"  ✗ 读取板块数据失败:{e}")
    
    print(f"\n{'='*50}")
    print(f"报告生成完成!")
    print(f"文件:{output_file}")
    print(f"{'='*50}")

if __name__ == '__main__':
    main()

运行结果

image.png

image.png

image.png

image.png

下载后查看效果

image.png