• 【量化小技巧】Python通过统计数据来进行过滤tushare涨停Dataframe,df.loc,或许有些启示与帮助


    库的引入

    from datetime import datetime as dt
    from datetime import timedelta
    import numpy as np
    import pandas as pd
    import tushare as ts
    
    # 对于tushare的一些初始化设置
    token = "[你的tushare密钥]"
    ts.set_token(token)
    pro = ts.pro_api(token)
    
    # 对于warnings的一个过滤,除非你知道你在干嘛,如果不了解建议别乱过滤
    from warnings import simplefilter
    from pandas.errors import PerformanceWarning, SettingWithCopyWarning
    
    def ignore_warnings():
        simplefilter(action="ignore", category=FutureWarning)
        simplefilter(action="ignore", category=DeprecationWarning)
        simplefilter(action="ignore", category=UserWarning)
        simplefilter(action="ignore", category=SyntaxWarning)
        simplefilter(action="ignore", category=PerformanceWarning)
        simplefilter(action="ignore", category=SettingWithCopyWarning)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    前导

    发生了什么事儿?

    前几天在进行日常的代码学习和检查,忽然发现一个问题:就是我的股票池有一个返回值连续两天是空值,我就开始了我的核查。后来发现是tushare之前的张婷的股票查询进行了升级和改动。现在返回值和过去的返回值都变了,所以呢我就需要对代码进行一些微调。即使是微调,我还是发现了一个我的知识盲区。

    上代码

    将日期设定好

    d00 = dt.now()
    d01 = d00 - timedelta(days=22)
    today = d00.strftime("%Y%m%d")
    month = d01.strftime("%Y%m%d")
    
    • 1
    • 2
    • 3
    • 4

    将列值提前设置好

    我们需要返回的列有:日期,交易代码,行业,企业名称,收盘价,涨幅,流动市值,换手率,炸板次数,封板频率,连续封板次数

    fields = ['trade_date', 'ts_code', 'industry',
              'name', 'close', 'pct_chg', 'float_mv',
              'turnover_ratio', 'open_times',
              'up_stat', 'limit_times']
    
    • 1
    • 2
    • 3
    • 4

    我们现在来调取tushare的涨停板信息

    data = pro.limit_list_d(start_date=month, end_date=today, limit_type="U", fields=fields)
    
    >>> #,trade_date,ts_code,industry,name,close,pct_chg,float_mv,turnover_ratio,open_times,up_stat,limit_times
    >>> 0,20230922,688498.SH,半导体,源杰科技,183.92,20.00,3.725956e+09,21.62,0,1/1,1
    >>> 1,20230922,605277.SH,消费电子,新亚电子,14.82,10.02,1.629821e+09,16.94,0,1/1,1
    >>> 2,20230922,603496.SH,互联网服,恒为科技,21.47,9.99,6.874892e+09,11.57,8,1/1,1
    >>> 3,20230922,603220.SH,通信服务,中贝通信,26.65,9.99,8.896354e+09,21.88,3,1/1,1
    >>> 4,20230922,603206.SH,通信服务,嘉环科技,18.00,10.02,1.569600e+09,14.88,0,1/1,1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    接下来我们稍微进行一个过滤筛选

    data = data[~data.name.str.contains('\*')]   # 去除带星名称的
    data = data[~data.name.str.contains('ST')]   # 去除带ST名称的
    data = data[~data.name.str.contains('N')]   # 去除带N名称的
    data = data[data.open_times <= 5]   # 当天炸板不能多余5次
    data = data[data.limit_times <= 3]   # 连续涨停不能超过3天
    data = data[data.turnover_ratio <= 20]   # 换手率20以内
    data = data[data.float_mv >= 4*10**9]   # 只看40+亿市值的公司
    
    >>> #,trade_date,ts_code,industry,name,close,pct_chg,float_mv,turnover_ratio,open_times,up_stat,limit_times
    >>>  5,20230922,603123.SH,商业百货,翠微股份,11.24,9.98,7.331582e+09,8.30,1,1/1,1
    >>>  6,20230922,603118.SH,通信设备,共进股份,11.62,10.04,9.144775e+09,6.60,0,1/1,1
    >>>  7,20230922,603083.SH,通信设备,剑桥科技,48.10,9.99,1.253020e+10,11.24,0,1/1,1
    >>>  9,20230922,601858.SH,文化传媒,中国科传,30.92,10.00,2.444226e+10,5.75,4,1/1,1
    >>> 14,20230922,300570.SZ,通信设备,太辰光,39.20,19.99,7.598915e+09,16.16,0,1/1,1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    即将发生的事儿

    我的考虑

    我是故意将行业放入在数据列中的,我的目的是想看哪些行业的股票再这过去的22天内,那些个行业出现的频率次数最多,然后过滤掉那些频率低的。我更看好大概率事件,而非偶然的个例。然后我就开始头大了,因为我还真没这么过滤过数据。

    错误的方法

    data = data[data.industry.value_counts() > 5]
    
    >>> IndexingError: Unalignable boolean Series provided as indexer 
    (index of the boolean Series and of the indexed object do not match).  
    
    • 1
    • 2
    • 3
    • 4

    这行代码看着好像与之前的过滤方式有异曲同工之妙之处。但是,我们引用value_count()这个函数, 导致我们的过滤并非是一个简简单单的对于某列进行简易的筛选,所以我们不能这样做,而且也不会成功,因为它报错了: IndexError。说明我们的索引出现了问题,我们的判定是True 和 False 的返回,并不是数值返回,所以我们需要对代码进行修改。报错的提示很明了,我们看到的是IndexError,那我们应该从Index上入手。我们要过滤的是industry行业列,那我们就把行业列设为Index。然后我们只是需要在上面的代码加上.loc函数即可,这样我们的目的就达到了,我们来看看输出如何。

    data.index = data.industry
    data = data.loc[data.industry.value_counts() > 5]
    
    >>> #,industry,trade_date,ts_code,industry,name,close,pct_chg,float_mv,turnover_ratio,open_times,up_stat,limit_times
    >>> 1,商业百货,20230922,603123.SH,商业百货,翠微股份,11.24,9.98,7.331582e+09,8.30,1,1/1,1
    >>> 2,通信设备,20230922,603118.SH,通信设备,共进股份,11.62,10.04,9.144775e+09,6.60,0,1/1,1
    >>> 3,通信设备,20230922,603083.SH,通信设备,剑桥科技,48.10,9.99,1.253020e+10,11.24,0,1/1,1
    >>> 4,文化传媒,20230922,601858.SH,文化传媒,中国科传,30.92,10.00,2.444226e+10,5.75,4,1/1,1
    >>> 5,通信设备,20230922,300570.SZ,通信设备,太辰光,39.20,19.99,7.598915e+09,16.16,0,1/1,1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    总结

    当我们运用到通过一些函数来对于数据Dataframe进行过滤筛选的时候,我们最好是把需要过滤筛选的列作为索引先,然后用df.loc来进行过滤筛选数据。这个方法你学废了么?

  • 相关阅读:
    .NET C#版本和.NET版本以及VS版本的对应关系
    贪心算法——硬币找零2——python
    助力电力行业数字化转型:智慧风电项目介绍
    对“方法”的解读
    【数据结构与算法】03 队列(顺序队列--循环队列--优先级队列--链队列)
    flask搭建简易版学生信息管理系统
    大数据-Hadoop-基础篇-第九章-Storm
    46.全排列 | 51.N皇后
    基于miniprogram-ci的微信小程序的CI以及接入钉钉通知
    tailwindcss安装完插件代码不提示
  • 原文地址:https://blog.csdn.net/weixin_44736043/article/details/133261051