聚宽函数库

目录

每月/每周的 (倒数) 第N个交易日

计算拥挤率

计算价格相关性

统计历史上N只乌鸦出现的次数

日内走势编码

计算RSI


获取前后n个交易日

def get_before_after_trade_days(date, count, is_before=True):
    """
    date :查询日期
    count : 前后追朔的数量
    is_before : True , 前count个交易日  ; False ,后count个交易日

    返回 : 基于date的日期, 向前或者向后count个交易日的日期 ,一个datetime.date 对象
    """
    from jqdata import  get_trade_days
    import pandas as pd
    all_date = pd.Series(get_all_trade_days())
    if isinstance(date,str):
        all_date = all_date.astype(str)
    if isinstance(date,datetime.datetime):
        date = date.date()

    if is_before :
        return all_date[all_date< date].tail(count).values[0]
    else :
        return all_date[all_date>date].head(count).values[-1]



date = "2019-10-20"#datetime.date(2019,10,20)
count = 10
is_before = False    
get_before_after_trade_days(date, count, is_before)

每月/每周的 (倒数) 第N个交易日

import pandas as pd 
from jqdata import *

def get_trade_day_bar(unit='W' , n=1 ,start_date=None,end_date=None,count=None):
    """
    unit : 频率 , "W"代表周 或者 "M"代表月
    n : 第几个交易日 , 每月第一个交易日: n=1 , 每月最后一个交易日 : n= -1 ,每月倒数第三个交易日 : n= -3 , 如果不足abs(n)个交易日,则返回符合条件的最近的一个交易日 
    start_date : 开始时间
    end_date : 结束时间
    count : 返回数据条数 , 指定start_date及count时返回start_date向后count条数据 , 指定end_date及count时返回end_date向前count条数据

    返回的数据会在 get_all_trade_days 以内
    返回 : 一个dataframe ,具体列含义见源码, date列就是需要获取的交易日了(datetime格式) 
    """


    df = pd.DataFrame(pd.to_datetime(get_all_trade_days()),columns=['date'])
    week_stamp = 24*60*60*7
    day_stamp = 24*60*60
    df['timestamp'] = df.date.apply(lambda x: x.timestamp() - day_stamp*3  )  #基于1970-01-01偏移三天
    df['mkweek'] = df.timestamp // week_stamp     # 1970-01-01 至今的第几周, 直接取每年的第几周再换年时会有问题
    df['weekday'] = (df.timestamp %  week_stamp)/day_stamp   #周几
    df['monthday'] = df.date.apply(lambda x : x.day)  #日
    df['month'] = df.date.apply(lambda x : x.month)   #月
    df['year'] = df.date.apply(lambda x : x.year)     #年

    if unit == "W":
        group_list = ['mkweek']
    elif unit =="M":
        group_list = ["year","month"]
    else :
        raise ValueError ('只支持M参数为 "M"或"W" ')

    if not isinstance(n , int):
        raise ValueError ('n 参数应该是一个int')
    elif n >0 :
        res =  df.groupby(group_list,as_index=False).head(n).groupby(group_list,as_index=False).last()
    elif n< 0:
        res =  df.groupby(group_list,as_index=False).tail(-n).groupby(group_list,as_index=False).first()    
    else :
        raise ValueError ('n 参数错误 : n={}'.format(n))


    if start_date and end_date and count:
        raise ValueError ('start_date ,end_date ,count 必须三选二')

    elif start_date and count :
        return res[res.date>=start_date].head(count)
    elif end_date and count :
        return res[res.date<= end_date].tail(count)
    elif start_date and end_date:
        return res[(res.date<= end_date) & (res.date>=start_date)]
    elif not  start_date and not end_date and not  count:
        return res
    else:
        raise ValueError ('start_date ,end_date ,count 必须三选二')


res = get_trade_day_bar("W",1,count=10,start_date='2015-09-15')
res

计算拥挤率

def crowd(date):
    stocks=list(get_all_securities(date=date).index)
    h = get_price(stocks, end_date=date, frequency='1d',fields='money',count=1, panel=False).pivot(index='code',columns='time',values='money')
    s2 = h.dropna().sort_values(by=h.columns[0],ascending=False)
    crowd5=((100 * s2.iloc[:len(s2)//20].sum()) / s2.sum()).iloc[0]
    crowd10=((100 * s2.iloc[:len(s2)//10].sum()) / s2.sum()).iloc[0]
    return crowd5,crowd10

计算价格相关性

def Relate(data_list1,data_list2,diff=0,timeperiod=10):
    # datalist 价格列表
    # diff ==1 计算价差的相关性
  
    if len(data_list1)!=len(data_list2):
        return 0
    else:
        days=len(data_list1)
        a1=np.array(data_list1)
        a2=np.array(data_list2)
        #价格相关性
        if diff==0:
            relate=[np.nan]*(timeperiod-1)
            for i in range(timeperiod,days+1):
                relate.append(np.corrcoef(a1[i-timeperiod:i]/a1[i-timeperiod],a2[i-timeperiod:i]/a2[i-timeperiod])[0,1])
        #价差相关性
        if diff==1:
            dif1=(a1[1:]-a1[:-1])/a1[:-1]
            dif2=(a2[1:]-a2[:-1])/a2[:-1]
            relate=[np.nan]*timeperiod
            for i in range(timeperiod,days):
                relate.append(np.corrcoef(dif1[i-timeperiod:i],dif2[i-timeperiod:i])[0,1])
            
        return relate

统计历史上N只乌鸦出现的次数

def count_N_crow(index,today,days,N=3): #N只乌鸦
    #index 代码
    #查询日期
    #days 查询天数


    if N<2:
        return 0
    else:
        results=pd.DataFrame(columns=['date','1day','5day'])
        count=0
        prices= get_price(index,end_date=today, count=days,frequency='1d',fields=['close','open'])
        dates=prices.index
        for i in range (len(dates)-N):
            nc=0
            while(ncprices.iloc[i+nc+1,0]:
                    nc +=1
                else:
                    break
            if nc==N-1:
                no=0
                while(no

日内走势编码

def inday_trade_tend(stock,field,date):
    #stock 代码
    #field 域

    scores=[]
    daily=get_price(stock,end_date=date,count=2, frequency='1d',skip_paused=True , fields=[field],fq='pre')
    minutes=get_price(stock,end_date=date,count=240, frequency='1m', fields=[field],fq='pre')        
    if field=='volume':
        pre=daily.iloc[0,0]/240
    else:
        pre=daily.iloc[0,0]

    means=[]
    score=0
    means.append(mean(minutes.iloc[0:61,0]))
    means.append(mean(minutes.iloc[61:121,0]))
    means.append(mean(minutes.iloc[121:181,0]))
    means.append(mean(minutes.iloc[181:,0]))
    for i in range(0,4):
        if means[i]<=pre*0.93:
            score=score+0*6**i
        elif means[i]>pre*0.93 and means[i]<=pre*0.97:
            score=score+1*6**i
        elif means[i]>pre*0.97 and means[i]<=pre:
            score=score+2*6**i
        elif means[i]>pre and means[i]<=pre*1.03:
            score=score+3*6**i
        elif means[i]>pre*1.03 and means[i]<=pre*1.07:
            score=score+4*6**i
        elif means[i]>pre*1.07:
            score=score+5*6**i
    scores.append(score)
    return scores

计算RSI

def RSI(stock,start_date,end_date,timeperiod=6):
    #日期换算,由于RSI累计时间越长越准确,因此从计算周期前150天开始算
    date_s1 = datetime.datetime.strptime(start_date,'%Y-%m-%d')

    date_s2 =date_s1 - datetime.timedelta(days = 150)

    return_days=len(get_trade_days(start_date=start_date,end_date=end_date))
    daily_price=get_price(stock, start_date=date_s2,end_date=end_date, frequency='1d', fields=['close'], skip_paused=False, fq='pre')
    dates=daily_price.index
    days=len(dates)#此处的日期包含了计算周期+150天
    close=np.array(daily_price['close'])
    diff=list(close[1:days]-close[0:days-1])
    diff.insert(0, 0) 
    A=0
    B=0
    rsi=[0]*(timeperiod+1)
    aA=[0]*(timeperiod+1)
    aB=[0]*(timeperiod+1)
    for i in range (1,timeperiod):
        if diff[i]>=0:
            A=A+diff[i]
        else:
            B=B+diff[i]
    rsi[-1]=A/(A-B)*100  #计算得到第一个RSI
    aA[-1]=A/timeperiod
    aB[-1]=B/timeperiod
    
    #后面的RSI都根据第一天依次计算
    for i in range(timeperiod+1,days):
        if diff[i]>=0:
            aA.append((aA[-1]*(timeperiod-1)+ diff[i])/timeperiod)
            aB.append(aB[-1]*(timeperiod-1)/timeperiod)
        else:
            aA.append(aA[-1]*(timeperiod-1)/timeperiod)
            aB.append((aB[-1]*(timeperiod-1)+ diff[i])/timeperiod)
        rsi.append(aA[-1]/(aA[-1]-aB[-1])*100)
    
    print(return_days)
    return rsi[-return_days:]

过滤股票 (回测函数)


#2-1 过滤停牌股票
def filter_paused_stock(stock_list):
    current_data = get_current_data()
    return [stock for stock in stock_list if not current_data[stock].paused]

#2-2 过滤ST及其他具有退市标签的股票
def filter_st_stock(stock_list):
    current_data = get_current_data()
    return [stock for stock in stock_list
            if not current_data[stock].is_st
            and 'ST' not in current_data[stock].name
            and '*' not in current_data[stock].name
            and '退' not in current_data[stock].name]

#2-3 过滤科创北交股票
def filter_kcbj_stock(stock_list):
    for stock in stock_list[:]:
        if stock[0] == '4' or stock[0] == '8' or stock[:2] == '68':
            stock_list.remove(stock)
    return stock_list

#2-4 过滤涨停的股票
def filter_limitup_stock(context, stock_list):
    last_prices = history(1, unit='1m', field='close', security_list=stock_list)
    current_data = get_current_data()
    return [stock for stock in stock_list if stock in context.portfolio.positions.keys()
            or last_prices[stock][-1] <    current_data[stock].high_limit]

#2-5 过滤跌停的股票
def filter_limitdown_stock(context, stock_list):
    last_prices = history(1, unit='1m', field='close', security_list=stock_list)
    current_data = get_current_data()
    return [stock for stock in stock_list if stock in context.portfolio.positions.keys()
            or last_prices[stock][-1] > current_data[stock].low_limit]

#2-6 过滤次新股
def filter_new_stock(context,stock_list):
    yesterday = context.previous_date
    return [stock for stock in stock_list if not yesterday - get_security_info(stock).start_date <    datetime.timedelta(days=375)]

你可能感兴趣的:(量化,python)