楼主: 数据洞见
609 0

概念,行业,龙头 热点追踪器 [推广有奖]

  • 0关注
  • 0粉丝

硕士生

20%

还不是VIP/贵宾

-

威望
0
论坛币
197090 个
通用积分
447.7601
学术水平
4750 点
热心指数
4741 点
信用等级
4737 点
经验
222917 点
帖子
147
精华
0
在线时间
127 小时
注册时间
2021-6-20
最后登录
2024-3-23

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
from IPython.core.display import display
from jqdata import *
import pandas as pd
import warnings
import pyecharts.globals as g
from pyecharts.charts import *
from pyecharts import options as opts
import datetime as dt
import ipywidgets as widgets
import IPython.display as dspl
from functools import lru_cache


# 获取股票的行业代码
def stock_industry(stocks_list=list(get_all_securities().index), industries_type="sw_l3"):
    stocks_industry_dict = get_industry(stocks_list)
    stocks_industry_df = pd.DataFrame(stocks_industry_dict).T[[industries_type]]
    stocks_industry_df[industries_type] = stocks_industry_df[industries_type].dropna().apply(
        lambda x: x['industry_name'])
    df_category = stocks_industry_df[[industries_type]].dropna().reset_index()
    df_category.columns = ['code', 'category']
    return df_category

#所有股票的概念列表
@lru_cache(maxsize=128, typed=False)
def stock_concepts():
    """所有股票的概念列表"""
    q = query(jy.LC_ConceptList.ConceptCode, jy.LC_ConceptList.ConceptName)
    dict_concept = jy.run_query(q).set_index('ConceptCode')['ConceptName'].to_dict()
    stocks = jy.run_query(query(jy.SecuMain.InnerCode, jy.SecuMain.SecuCode).filter(jy.SecuMain.SecuCategory == 1,
                                                                                    jy.SecuMain.SecuMarket.in_(
                                                                                        [83, 90]),
                                                                                    jy.SecuMain.ListedState.in_(
                                                                                        [1])))
    s_code = stocks.set_index("InnerCode")['SecuCode']

    dfs = []
    min_id = 9953668143482
    while len(dfs) < 30 and min_id > 0:
        q = query(
            jy.LC_COConcept
        ).filter(jy.LC_COConcept.IndiState == 1, jy.LC_COConcept.ID < min_id).order_by(jy.LC_COConcept.ID.desc())
        df = jy.run_query(q)
        min_id = df.ID.min()
        if len(df) > 0:
            dfs.append(df)
        else:
            break
    df = pd.concat(dfs, ignore_index=True)

    sc = df.groupby('InnerCode').apply(
        lambda dx: ",".join([dict_concept[code] for code in dx.ConceptCode.unique()]))
    df_concept = pd.DataFrame({"concept": sc, 'code': s_code})
    df_concept['symbol'] = df_concept.code.map(normalize_code, na_action='ignore')
    s_concept = df_concept.dropna().set_index('symbol')['concept']
    df = pd.DataFrame(s_concept.str.split(',').tolist(), index=s_concept.index).stack()
    df = df.reset_index([0, 'symbol'])
    df.columns = ['code', 'category']
    return df

  # 股票价格是否在N日均线上方
def score_by_bias(stock_list=list(get_all_securities().index), ma_len=20, end_date=dt.datetime.now(), count=510):
    """
    :param stock_list:
    :param ma_len:
    :param end_date:
    :param count:
    :return: index,2020-05-01
       000001.XSHE,         1
    """
    close = get_price(stock_list, end_date=end_date, count=count + ma_len + 1, fields=['close'])['close']
    ma = close.rolling(ma_len).mean()
    return (close > ma).astype(int).iloc[-count:].T

def score_by_return(stock_list=list(get_all_securities().index), return_days=1, return_filter=0.099,
                    end_date=dt.datetime.now(), count=510):
    """
    :param stock_list:  股票代码
    :param return_days: 收益率统计周期
    :param return_filter: 收益率阈值过滤
    :param end_date: 截止日期
    :param count: 查看的周期
    :return:
    """
    close = get_price(stock_list, end_date=end_date, count=count + return_days, fields=['close'], panel=True)[
        'close']
    df_return = (close / close.shift(return_days) - 1).iloc[return_days:]
    df_filter = (df_return > return_filter).astype(int)
    df_filter.index = df_return.index.strftime('%Y-%m-%d')
    return df_filter.T

#涨停统计
def zhangting(end_date,count,filter_longtou=False):
    #filter_longtou 为True 只显示成为过某日最高板的股票
    df_stock=get_all_securities()
    old_stock=df_stock['start_date']<(end_date-dt.timedelta(days=count+180)).date()
    not_st=~(df_stock['display_name'].str.contains('ST')|(df_stock['display_name'].str.contains('退')))
    select_stock=df_stock[not_st&old_stock]
    names=df_stock['display_name'].to_dict()
    panel=get_price(list(select_stock.index),end_date=end_date,count=count,fields=['close','pre_close','high_limit'],panel=True)
    close=panel['close']
    pre_close=panel['pre_close']
    high_limit=panel['high_limit']
    #涨停标记1
    df_zhangting=((close>=high_limit)&(close>pre_close)).astype(int)
    # 过滤出现过涨停的股票
    df_has_zhangting=df_zhangting.loc[:,(df_zhangting>0).any()]
    # 股票代码换成股票名称
    df_has_zhangting.columns=[names[col] for col in df_has_zhangting.columns]
   
    # 统计股票连板数
    np_sum=df_has_zhangting.values
    for row in range(0,np_sum.shape[0]):
        for col in range(0,np_sum.shape[1]):
            if np_sum[row,col]>0 and (row==0 or np_sum[row-1,col]==0):
                np_sum[row,col]=1
            elif np_sum[row,col]>0 and row>0 and np_sum[row-1,col]>0:
                np_sum[row,col]=np_sum[row-1,col]+1
    df_sum=pd.DataFrame(data=np_sum,index=df_has_zhangting.index,columns=df_has_zhangting.columns)
               
    #转换成 日期,股票,连板数的格式,只保留涨停板数据      
    df_zhangting_record=df_sum.reset_index().melt(id_vars='index')
    df_zhangting_record=df_zhangting_record.fillna(0)
    df_zhangting_record=df_zhangting_record[(df_zhangting_record['value']>0)]
    df_zhangting_record.columns=['date','category','score']
    df_zhangting_record['date']=df_zhangting_record['date'].dt.strftime('%Y-%m-%d')
   
    #计算每天最高板
    df_date_max=df_zhangting_record[['date','score']].groupby('date').max()
    df1=df_zhangting_record.merge(df_date_max,left_on='date',right_index=True)
    #相对每天最高板的比例*100 作为rank 字段,最高板显示红色
    df1['rank']=(df1['score_x']/df1['score_y']*100).astype(int)
    #只保留每日最高版出现过的龙头股
    if filter_longtou==True:
        df2=df1[df1['category'].isin(list(df1[df1['score_x']==df1['score_y']].category.unique()))]
    else:
        df2=df1
    #添加一列最高板数据
    df_date_highest=df2[['date','score_x']].groupby('date').max()
    df_date_highest['category']='*最高板'
    df_date_highest['score_y']=df_date_highest['score_x']
    df_date_highest['rank']=100
    df_date_highest=df_date_highest.reset_index()
   
    return pd.concat([df2[['category','date','score_x','rank','score_y']],df_date_highest[['category','date','score_x','rank','score_y']]])

# 分类热度统计,默认实现聚宽支持的行业分类,还有聚源数据的概念分类
class Category:
    def __init__(self):
        warnings.filterwarnings('ignore')
        g.WarningType.ShowWarning = False

    # 数据格式 dat,cat,value,score
    def plot_category_hot(self,df, title):
        """
        :param df: 数据格式 category,date,score,rank
        :param title: series name
        :return: pyecharts Bar3D 图
        """
        return Bar3D(init_opts=opts.InitOpts(width="100%", height="800px")) \
            .add(
            series_name=title,
            shading="lambert",
            data=df.values.tolist(),
            xaxis3d_opts=opts.Axis3DOpts(type_="category", data=sorted(list(df['category'].unique()))),
            yaxis3d_opts=opts.Axis3DOpts(type_="category", data=sorted(list(df['date'].unique()))),
            zaxis3d_opts=opts.Axis3DOpts(type_="value"),
        ).set_global_opts(
            visualmap_opts=opts.VisualMapOpts(
                max_=100,
                dimension=3,
                range_color=[
                    "#313695",
                    "#4575b4",
                    "#74add1",
                    "#abd9e9",
                    "#e0f3f8",
                    "#ffffbf",
                    "#fee090",
                    "#fdae61",
                    "#f46d43",
                    "#d73027",
                    "#a50026"
                ]
            )
        ).render_notebook()

    def category_score(self,df_score, df_category=None, count=30, daily_top_filter=20):
        """
        :param df_score: 格式 code,2015-01-01,2015-01-02...
        :param df_category: 格式 code,category
        :param count: 查看最近周期(热度在这个周期的排行)
        :param daily_top_filter: 只保留每天的top多少,按score排行
        :return:
        """
        code_category_dict = df_category.groupby('code').apply(lambda dx: list(dx['category'].unique())).to_dict()
        dats = df_score.columns
        # 统计分类得分
        dat_cat_dict = {}  # {'2020-05-01':{'光伏概念':30,'连板':50}}
        for i in range(0, len(dats)):
            codes = list(df_score[df_score[dats[i]] > 0].index)
            s_score = df_score[dats[i]]
            category_count_dict = {}
            for code in codes:
                if code in code_category_dict:
                    categories = code_category_dict[code]
                    for category in categories:
                        if category not in category_count_dict:
                            category_count_dict[category] = float(s_score[code])
                        else:
                            category_count_dict[category] = float(category_count_dict[category]) + float(s_score[code])
            dat_cat_dict[dats[i]] = category_count_dict
        # df_category_score 格式 index 2020-05-01
        #                  光伏概念        5
        df_category_score = pd.DataFrame.from_dict(dat_cat_dict, orient='index').fillna(0).tail(count).T
        # 每日概念得分排行100分制
        df_category_score_rank = (df_category_score.rank(pct=True, axis='columns', method='min') * 100).astype(int)

        # 计算每天的得分排名,转换成 category,date,rank 保留排行前N
        df_category_daily_rank = df_category_score.rank(ascending=False, method='first').astype(int)
        df_category_daily_rank_melt = df_category_daily_rank.reset_index().melt(id_vars=['index'])
        df_daily_tops = df_category_daily_rank_melt[df_category_daily_rank_melt['value'] <= daily_top_filter]

        # 两次左连接,保留topN得分的,每日分类热度数据
        df_cat_melt = df_category_score.reset_index().melt(id_vars=['index'])
        df_cat_rank_melt = df_category_score_rank.reset_index().melt(id_vars=['index'])
        df_top_score = df_daily_tops.merge(df_cat_melt, left_on=['index', 'variable'], right_on=['index', 'variable'],
                                           how='left')
        df_final = df_top_score.merge(df_cat_rank_melt, left_on=['index', 'variable'], right_on=['index', 'variable'],
                                      how='left')
        df_final.columns = ['category', 'date', 'order', 'score', 'rank']
        return df_final[['category', 'date', 'score', 'rank', 'order']]
   
    def display_filter_category(self,df,title):
        category_list = list(df['category'].unique())
        select = widgets.SelectMultiple(
            options=['全部'] + category_list,
            rows=10,
            value=['全部'],
            disabled=False
        )
        dates=sorted(list(df['date'].unique()))
        options = [(i[-5:].replace("-",""), i) for i in dates]
        slider=widgets.SelectionRangeSlider(
            options=options,
            index=(0, len(dates)-1),
            description='日期',
            disabled=False
        )
        btn = widgets.Button(
            description='应用',
        )
        out = widgets.Output()
        box = widgets.VBox([widgets.HBox([slider,select,btn]), out])
        display(box)
        def on_value_change(change):
            categories = df[(df['date']>=slider.value[0])&(df['date']<=slider.value[1])]['category'].unique()
            select.options=['全部']+list(categories)
            select.value=['全部']
        slider.observe(on_value_change, names='value')
        @out.capture()
        def button_click(e):
            cats = list(select.value)
            dfs = df[(df['date']>=slider.value[0])&(df['date']<=slider.value[1])]
            if "全部" not in cats:
                dfs = df[df['category'].isin(cats)]
            dspl.clear_output('wait')
            display(self.plot_category_hot(dfs, title))
        btn.on_click(button_click)




二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:追踪器 Industries Securities categories Dataframe

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-25 13:54