请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  数理科学 帖子:3352818 新帖:18

根据扣非净益率筛选白马股,并绘制K线图

K线达人发表于:5 月 22 日 13:47回复(1)

根据扣非净益率筛选白马股,以及介绍K线图的画法¶

在过去的一年里,“白马股”的概念收到了广泛重视,基本面财务状况良好的白马股涨势强劲。本文希望通过过去三段时间的扣非净益率来筛选优质的白马股。

扣非净益率即扣除非正常损益后的净益率,其计算公式为:(净利润+非正常损益)/股东权益

本来我们的算法是连续三年里,取财报中每一年的扣非净益率和股东权益并相除。但除了计算每年的扣非净益率,我们希望算法可以根据季报计算多个季度的扣非净益率,以适用于更灵活的场景。改进后可以选取三段时间内的扣非净益率之和,并除以每段时间末的股东权益。

传入参数:¶

  • q_end:截止时间,由这个时间向前推三个时间段。格式为'20xxqx',表示某年第几个季度,例:'2016q3'
  • p3, p2, p1:由后至前的三个时间段分别覆盖了几个季度。例:3,4,5的输入方式表示最后一段时间覆盖3个季度(2015q4-2016q3),中间一段覆盖4个季度(2014q4-2015q4),第一段覆盖5个季度(2013q3-2014q4)。
  • r3, r2, r1:由后至前的三个时间段的收益率阈值,即这个时间段内的扣非净益率超过多少才会被留下。经验表明,一个年净利率取0.2比较合适,故前面p为4的话,对应r可取0.2左右。
  • date_for_index:根据指数选取指数所含股票的日期。日期不同,指数内包含的函数也不同。

样例:¶

举一个例子:函数输入的时间为2016q3,表示这三段时间的截止时间为2016年第三季度。为了确定三段时间的长度,需要依次输入p3, p2, p1,分别为第三段、第二段、第一段时间包括的季度数量。将每只股在这三个时间段内的扣非净利润加总,再除以每个时间段末的股东权益,就可以得到该公司在这一段时间内的扣非净益率了。

得到三段时间的扣非净益率后,我们根据需要,选取扣非净益率大于阈值的股票。三段时间的阈值也由我们手动输入,这里我们选取三段时间分别为3、4、4个季度,即三段时间由后向前覆盖的季度分别为:2015q4-2016q3、2014q4-2015q4、2013q4-2014q4。根据实验,我们将三段时间内的收益率阈值分别取为0.12,0.18,0.18。

#注意:需先运行下方函数代码,才能运行本段代码
df_use=cal_df('2016q3',3,4,4,0.12,0.18,0.18)
df_use
name rate2016q3 rate2015q4 rate2014q4 start_date days pe_ratio market_cap
600816.XSHG 安信信托 0.276501 0.258681 0.569850 1994-01-28 8761 17.1590 608.8974
600398.XSHG 海澜之家 0.251145 0.348055 0.315459 2000-12-28 6235 14.5766 469.4932
000651.XSHE 格力电器 0.231097 0.253540 0.313417 1996-11-18 7736 17.3254 3404.9038
000895.XSHE 双汇发展 0.218504 0.222022 0.232992 1998-12-10 6984 22.8400 977.3292
002415.XSHE 海康威视 0.218010 0.290447 0.300755 2010-05-28 2797 43.9580 3834.5935
603288.XSHG 海天味业 0.216606 0.278753 0.268159 2014-02-11 1442 46.3211 1548.3317
002294.XSHE 信立泰 0.200795 0.265557 0.272742 2009-09-10 3057 29.9267 434.2012
000848.XSHE 承德露露 0.190111 0.268042 0.323447 1997-11-13 7376 25.2462 102.3577
002508.XSHE 老板电器 0.189775 0.258170 0.224562 2010-11-23 2618 34.9522 512.3828
600566.XSHG 济川药业 0.188286 0.236101 0.208460 2001-08-22 5998 29.0688 338.7467
000625.XSHE 长安汽车 0.187422 0.279748 0.285951 1997-06-10 7532 7.6725 586.5018
000333.XSHE 美的集团 0.185480 0.194735 0.207228 2013-09-18 1588 23.9135 4035.2847
002304.XSHE 洋河股份 0.185201 0.214281 0.226461 2009-11-06 3000 30.7147 2017.8569
600519.XSHG 贵州茅台 0.175991 0.235783 0.280607 2001-08-27 5993 40.0982 9718.4482
600887.XSHG 伊利股份 0.165165 0.199463 0.200177 1996-03-12 7987 34.2538 2126.8645
002143.XSHE 印纪传媒 0.163425 0.281793 0.357169 2007-07-20 3840 33.1850 250.0776
002595.XSHE 豪迈科技 0.163313 0.210597 0.192189 2011-06-28 2401 21.1585 146.0800
000963.XSHE 华东医药 0.161319 0.328377 0.293162 2000-01-27 6571 31.4797 547.8848
601633.XSHG 长城汽车 0.160594 0.199338 0.230228 2011-09-28 2309 17.8671 974.9072
600276.XSHG 恒瑞医药 0.158968 0.209574 0.180528 2000-10-18 6306 72.4153 2163.8599
601877.XSHG 正泰电器 0.155896 0.233938 0.270814 2010-01-21 2924 21.1370 543.0206
000538.XSHE 云南白药 0.147757 0.193324 0.200697 1993-12-15 8805 34.3442 1087.0129
000423.XSHE 东阿阿胶 0.145214 0.211360 0.209774 1996-07-29 7848 23.6939 443.8190
600273.XSHG 嘉化能源 0.141507 0.182860 0.185851 2003-06-27 5324 16.0673 142.3776
600674.XSHG 川投能源 0.137991 0.206518 0.224577 1993-09-24 8887 13.4463 435.8119
002174.XSHE 游族网络 0.136838 0.221184 0.443279 2007-09-25 3773 29.9410 205.5026
002236.XSHE 大华股份 0.136755 0.205652 0.212020 2008-05-20 3535 34.4930 758.8944
600201.XSHG 生物股份 0.133686 0.230658 0.246538 1999-01-15 6948 32.7080 275.4107
601515.XSHG 东风股份 0.120193 0.186100 0.211841 2012-02-16 2168 17.3318 109.8656
import numpy as np
import pandas as pd
from jqdata import *
from datetime import datetime
import datetime as dt
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
from matplotlib.finance import candlestick_ohlc

def back(x):
    if x[-1]=='1':
        return str(int(x[:4])-1)+'q4'
    else:
        return str(x[:5])+str(int(x[-1])-1)
    
today=datetime.strptime(str(datetime.now())[:10], '%Y-%m-%d')
def delta_days(x):
    d2=datetime.strptime(str(x)[:10], '%Y-%m-%d')
    return (today-d2).days

def cal_df(q_end,p3=4,p2=4,p1=4,r3=0.15,r2=0.15,r1=0.15,date_for_index='2017-12-31'):
    #选取上证综指和深证成指的全体股票
    g1=get_index_stocks('000001.XSHG',date=date_for_index)
    g2=get_index_stocks('399001.XSHE',date=date_for_index)
    stocks=g1+g2
    q1=query(indicator).filter(indicator.code.in_(stocks))
    q2=query(balance).filter(balance.code.in_(stocks))
    
    #计算第三段扣非净益率
    df=get_fundamentals(q1,statDate=q_end)[['code','adjusted_profit']]
    df=df.rename(columns={'adjusted_profit':'prof'+q_end})
    df.index=df['code'].values
    df_=get_fundamentals(q2,statDate=q_end)[['code','total_owner_equities']]
    df_.index=df_['code'].values
    df['equity'+q_end]=df_['total_owner_equities']
    q_date=q_end
    for i in range(p3-1):
        q_date=back(q_date)
        df_=get_fundamentals(q1,statDate=q_date)[['code','adjusted_profit']]
        df_.index=df_['code'].values
        df['prof'+q_end]=df['prof'+q_end]+df_['adjusted_profit']
    q_end3=q_end
    df['rate'+q_end3]=df['prof'+q_end3]/df['equity'+q_end3]
    
    #计算第二段扣非净益率
    q_end=back(q_date)
    df_=get_fundamentals(q1,statDate=q_end)[['code','adjusted_profit']]
    df_.index=df_['code'].values
    df['prof'+q_end]=df_['adjusted_profit']
    df_=get_fundamentals(q2,statDate=q_end)[['code','total_owner_equities']]
    df_.index=df_['code'].values
    df['equity'+q_end]=df_['total_owner_equities']
    q_date=q_end
    for i in range(p2-1):
        q_date=back(q_date)
        df_=get_fundamentals(q1,statDate=q_date)[['code','adjusted_profit']]
        df_.index=df_['code'].values
        df['prof'+q_end]=df['prof'+q_end]+df_['adjusted_profit']
    q_end2=q_end
    df['rate'+q_end2]=df['prof'+q_end2]/df['equity'+q_end2]    
    
    #计算第一段扣非净益率
    q_end=back(q_date)
    df_=get_fundamentals(q1,statDate=q_end)[['code','adjusted_profit']]
    df_.index=df_['code'].values
    df['prof'+q_end]=df_['adjusted_profit']
    df_=get_fundamentals(q2,statDate=q_end)[['code','total_owner_equities']]
    df_.index=df_['code'].values
    df['equity'+q_end]=df_['total_owner_equities']
    q_date=q_end
    for i in range(p1-1):
        q_date=back(q_date)
        df_=get_fundamentals(q1,statDate=q_date)[['code','adjusted_profit']]
        df_.index=df_['code'].values
        df['prof'+q_end]=df['prof'+q_end]+df_['adjusted_profit']
    q_end1=q_end
    df['rate'+q_end1]=df['prof'+q_end1]/df['equity'+q_end1]
    
    #选取符合条件的股票
    df=df[(df['rate'+q_end1]>r1) & (df['rate'+q_end2]>r2) & (df['rate'+q_end3]>r3) 
          &(df['prof'+q_end1]>0)&(df['prof'+q_end2]>0)&(df['prof'+q_end3]>0)]
    df=df[['rate'+q_end3,'rate'+q_end2,'rate'+q_end1]]
    
    #对符合条件的股票进行处理
    #start_date:上市日期 days:上市天数 pe_ratio:当天的市盈率 market_cap:当天的市值
    sat_list=list(df.index)
    name_list=list(map(lambda x:get_security_info(x).display_name,sat_list))
    start_list=list(map(lambda x:get_security_info(x).start_date,sat_list))
    df.insert(0,'name',name_list)
    df['start_date']=start_list
    days_list=list(map(lambda x:delta_days(x),start_list))
    df['days']=days_list
    df=df.sort(columns='rate'+q_end3,ascending=False)
    q3=query(valuation).filter(valuation.code.in_(sat_list))
    fund=get_fundamentals(q3)[['code','pe_ratio','market_cap']]
    fund.index=fund['code'].values
    df['pe_ratio']=fund['pe_ratio']
    df['market_cap']=fund['market_cap']
    return df

通过扣非净益率得到符合条件的白马股之后,不考虑未来函数的因素,将这些股票组成一个投资组合,并考察自15年初起该投资组合的K线图。

传入参数:¶

  • df:上一部分计算后得到的dataframe结果。
  • st_date, ed_date:画图选取的开始时间和结束时间。需要注意的是,如果将画图开始时间选得太早,有的股票可能还没上市,所以最好取2015年及其以后的日期作为开始时间。
  • freq:调取价格的频率,默认为5分钟一次。精度越高,对投资组合价格变动的刻画就越精确。
  • delta:画图时,K线图里每一个bar是由多少个价格画出来的。由于一天的交易时间是240分钟,故如果取freq=5m,一天就是48个价格。经验表明,若freq=5m,将delta取为240比较合适,大概需要跑1~2分钟。

这里向大家推荐一个画K线图的函数:matplotlib.finance中的candlestick_ohlc。具体使用方法可以参照下文的函数,也可以点击这里看matplotlib的官方示例。

#注意:需先运行下方函数代码,才能运行本段代码
draw_k(df_use,'2015-01-05','2017-12-29')
def draw_k(df,st_date,ed_date,freq='5m',delta=240):
    #获取需要使用的股票代码,并标记开始和结束的日期
    value_stocks=list(df.index)
    days=get_all_trade_days()
    trade_days=list(map(lambda x:str(x),days))
    for i in range(len(trade_days)):
        if trade_days[i]==st_date:
            day_flag1=i
        if trade_days[i]==ed_date:
            day_flag2=i
    
    #获取对应股票的价格,获取投资组合的价格情况
    prices=get_price(value_stocks,start_date=trade_days[day_flag1],end_date=trade_days[day_flag2],frequency=freq)
    prices['sum']=prices.sum(axis=1)
    close_=prices['close'].sum(axis=1).values
    open_=prices['open'].sum(axis=1).values
    high_=prices['high'].sum(axis=1).values
    low_=prices['low'].sum(axis=1).values
    volum_=prices['volume'].sum(axis=1).values

    closep=list(close_[delta*i+delta-1] for i in range(int(len(close_)/delta)))
    openp=list(close_[delta*i] for i in range(int(len(close_)/delta)))
    highp=list(max(close_[delta*i:delta*i+delta-1]) for i in range(int(len(close_)/delta)))
    lowp=list(min(close_[delta*i:delta*i+delta-1]) for i in range(int(len(close_)/delta)))
    volume=list(np.mean(close_[delta*i:delta*i+delta-1]) for i in range(int(len(close_)/delta)))

    x,y,candleAr=0,len(closep),[]
    date = np.linspace(0,y,y)
    while x < y:
        appendLine = date[x],openp[x],highp[x],lowp[x],closep[x],volume[x]
        candleAr.append(appendLine)
        x += 1
        
    #提取日期,绘制K线图横坐标
    quotes2=get_price('000001.XSHE', start_date=st_date, end_date=ed_date, frequency='daily',skip_paused=False)
    t = quotes2.index.values
    t1 = t[-len(t):].astype(dt.date)/1000000000
    ti=[]
    for i in range(int(len(t)/50)):
        a=i*50
        d = dt.date.fromtimestamp(t1[a])
        t2=d.strftime('$%Y-%m-%d$')
        ti.append(t2)
    d1= dt.date.fromtimestamp(t1[len(t)-1])
    d2=d1.strftime('$%Y-%m-%d$')
    ti.append(d2)
    
    #绘制K线图
    fig = plt.figure(figsize=(16, 8))
    ax1 = plt.subplot2grid((10,4),(0,0),rowspan=10,colspan=4)
    candlestick_ohlc(ax1, candleAr, width=0.5, colorup='r', colordown='g', alpha=0.6)
    ax1.set_xticks(np.linspace(-2,len(closep)+2,len(ti))) 
    ax1.set_xticklabels(ti)
    plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')
    plt.show()

全部回复

0/140

量化课程

    移动端课程