【掘金使用技巧1】合成长周期k线的函数

发布于: 雪球转发:0回复:0喜欢:0

用日线合成长周期k线

掘金API中的接口最长的周期是‘1d’的,如果想要合成频率为周、月甚至年的应该怎么办呢?为此,写了一个函数来实现日k线合成长周期k线,欢迎大家一起讨论,不足之处请多指教。

基本思路

用日线合成长周期的k线并不难,只需要确定好合成的周期以及需要的数据即可。

周期: 一般行情软件上提供年k、月k、周k,我也选择年、月、周再加一个季度频率。

数据: 开盘、收盘、最高、最低、成交额、成交量。

确定好周期和需要的数据以后,就可以开始写函数了。以周线为例,要想合成周线,主要有以下几步:

将日线按照日期以周为频率进行分组

计算开盘、收盘、最高、最低、成交额和成交量。

开盘 = 该周第一天的开盘价
收盘 = 该周最后一天的收盘价
最高 = 该周所有最高价的最大值
最低 = 该周所有最低价的最小值
成交额 = 该周全部成交额的总和
成交量 = 该周全部成交量的总和

确定好基本思路,就可以开始编写函数了。

该函数共需要4个参数,分别为:股票代码、开始日期、结束日期、合成频率。

这里面有个需要注意的点:输入的开始时间不一定是合成周期的第一天。

(比如合成周线,开始日期输入的是周三,如果直接按照周合成,那么第一个合成的周线就是残缺的,这就需要进行调整,把起始日期前推到该周期的第一天)

按时间分组用到pandas库里面的resample函数,该函数可以按照指定频率对数据进行分组计算,用法如下:

其中freq参数设置可参照下表:

函数代码

def compose_bar(symbol,start_time,end_time,frequency):
    '''symbol:标的,start_time:开始时间,end_time:结束时间,frequency:频率'''
    # 合成周线
    if frequency == 'W':
        # 判断开始日期是否为周一(默认周一 = 0,周二 = 1,所以对得出的week进行调整,加一)
        start_time = datetime.datetime.strptime(start_time,'%Y-%m-%d')
        week_start = start_time.weekday() + 1
        # 如果不是周一,则将开始时间调整到该周周一
        if week_start != 1:
            print('输入的开始日期为周{},调整到该周周一'.format(week_start))
            start_time = start_time - datetime.timedelta(days = week_start - 1)

    # 合成月线
    if frequency == 'M':
        # 判断开始日期是否为月初
        day_start_1th = int(start_time[8:10])
        # 如果不是1号,则转为当月1号
        if day_start_1th != 1 :
            start_time = datetime.datetime.strptime(start_time, '%Y-%m-%d')
            start_time = start_time - datetime.timedelta(days = day_start_1th - 1)
            print('开始日期为该月{}号,调整到当月1号',format(day_start_1th))


    # 合成季线
    if frequency == 'Q':
        # 直接开始日期设置为季度初
        month = int(start_time[5:7])   # 看开始时间月份
        year = int(start_time[0:4])     # 看开始时间年份
        if month in range(1,3):
            start_time = datetime.date(year,1,1)
        if month in range(4,6):
            start_time = datetime.date(year,4,1)
        if month in range(7,9):
            start_time = datetime.date(year,7,1)
        if month in range(10,12):
            start_time = datetime.date(year,9,1)

    # 合成年线
    if frequency == 'A':
        # 将开始时间调整为年初
        year_start = int(start_time[0:4])  # 看开始时间年份
        start_time = datetime.date(year_start,1,1)

    # 订阅历史数据(注意要复权到当前日期才能和新浪财经的数据对得上)
    data = history(symbol = symbol,frequency = '1d',start_time = start_time,end_time = end_time,fields = 'eob,open,close,high,low,amount,volume',df = True,
                   skip_suspended = True,fill_missing = None, adjust=ADJUST_PREV,adjust_end_time = datetime.datetime.today())
    # 修改日期格式并变成索引
    data.eob = data.eob.apply(lambda x :datetime.datetime.strptime(str(x).split(' ')[0],'%Y-%m-%d'))
    data.set_index(data['eob'],inplace = True)
    data.drop(columns = ['eob'],inplace = True)
    data_index = data.resample(frequency,label = 'right').last().index
    # 结果返回成dataframe格式
    data_k = pd.DataFrame({'open':data.resample(frequency,label = 'right').first()['open'],
                                'close': data.resample(frequency,label = 'right').last()['close'],
                                'high': data.resample(frequency,label = 'right').max()['high'],
                                'low': data.resample(frequency,label = 'right').min()['low'],
                                'amount': data.resample(frequency,label = 'right').sum()['amount'],
                                'volume': data.resample(frequency,label = 'right').sum()['volume'],
                                'frequency':frequency
                                })
    data_k.set_index(data_index,inplace = True)

    # 如果某周放假没有数据,则删除
    data_k.dropna(inplace = True)

    return data_k

# 测试一下
weekly_k = compose_bar('SHSE.600519','2019-01-05','2020-01-26','W')
monthly_k = compose_bar('SHSE.600519','2019-01-05','2020-01-30','M')
quarterly_k = compose_bar('SHSE.600519','2019-01-05','2020-01-30','Q')
yearly_k = compose_bar('SHSE.600519','2019-01-05','2020-01-30','A')

测试结果和新浪财经的数据相同,大功告成。

来源:掘金量化      原文链接:网页链接