股票因子扩展2(双神因子计算)——从零到实盘5

股票因子扩展2(双神因子计算)——从零到实盘5

前文记录了涨停因子的实现,本文记录双神因子的实现。

双神本质上就是间隔的两个涨停,网上也有人称之为双龙。

; 主要代码分析

新建源文件,命名为data_center_v4.py,全部内容见文末,v4主要涉及4个方面的改动:

新增计算移动因子函数

def shift_i(df, factor_list, i, fill_value=0, suffix='a'):

该函数用于计算移动因子,用于获取前i日或者后i日的因子,其中:

  • 参数df为待计算扩展因子的DataFrame
  • 参数factor_list为待移动的因子列表
  • 参数i为移动的步数
  • 参数fill_value为用于填充NA的值,默认为0
  • 参数suffix值为a(ago)时表示移动获得历史数据,用于计算指标;值为l(later)时表示获得未来数据,用于计算收益
  • 返回值为包含扩展因子的DataFrame
    shift_df = df[factor_list].shift(i, fill_value=fill_value)

选取需要shift的列构成新的DataFrame,进行shift操作。shift方法实现对数据进行按列移动,更多说明可参见链接。由于移动会产生空值,使用fill_value值对这些空值进行填充。

    shift_df.rename(columns={x: '{}_{}{}'.format(x, i, suffix) for x in factor_list}, inplace=True)

对新的DataFrame列进行重命名。例如,将涨停因子zt向下移动2步的得到数据的列名修改为zt_2a。

    df = pd.concat([df, shift_df], axis=1)

将重命名后的DataFrame合并到原始DataFrame中。

    return df

返回包含扩展因子的DataFrame。

例如,我们计算三美股份sh.603379在2021年9月6日至2021年9月17日10个交易日的因子情况,在计算完涨停因子后,调用下面的代码计算2天前涨停的情况:

print(shift_i(df, ['zt'], 2, fill_value=False))
           date   open   high    low  ...  pcfNcfTTM  isST     zt  zt_2a
593  2021-09-06  26.08  27.56  25.58  ... -59.964931     0  False  False
594  2021-09-07  28.12  30.26  27.01  ... -65.959245     0   True  False
595  2021-09-08  31.35  31.42  29.26  ... -65.719472     0  False  False
596  2021-09-09  30.10  30.50  28.85  ... -66.482385     0  False   True
597  2021-09-10  30.55  31.99  28.20  ... -67.572260     0  False  False
598  2021-09-13  31.58  33.38  30.49  ... -70.841885     0  False  False
599  2021-09-14  32.52  35.00  31.44  ... -71.822773     0  False  False
600  2021-09-15  33.02  36.25  32.10  ... -79.015949     0   True  False
601  2021-09-16  37.90  38.00  35.30  ... -77.381136     0  False  False
602  2021-09-17  35.51  39.05  35.51  ... -85.119250     0   True   True

[10 rows x 19 columns]

对照K线图:

股票因子扩展2(双神因子计算)——从零到实盘5

9月7日该股涨停,zt因子结果为True,9月9日的zt_2a因子结果为True,即从9号来看,2天前该股是涨停的,计算结果正确。检查后面的数据也是正确的。

新增计算范围移动因子函数

def shift_till_n(df, factor_list, n, fill_value=0, suffix='a'):

该函数用于计算范围移动因子,获取前/后n日内的相关因子,内部调用了shift_i,其中:

  • 参数df为待计算扩展因子的DataFrame
  • 参数factor_list为待移动的因子列表
  • 参数n为移动的步数范围
  • 参数fill_value用于填充NA的值,默认为0
  • 参数suffix值为a(ago)时表示移动获得历史数据,用于计算指标;值为l(later)时表示获得未来数据,用于计算收益
  • 返回值为包含扩展因子的DataFrame
    for i in range(n):
        df = shift_i(df, factor_list, i + 1, fill_value, suffix)
    return df

循环调用函数shift_i,计算得到范围移动因子。

新增计算双神因子函数

def ss(df, delta_days=30):

该函数用于计算双神因子,即间隔的两个涨停,其中:

  • 参数df为待计算扩展因子的DataFrame
  • 参数delta_days,两根涨停间隔的时间不能超过该值,否则不判定为双神,默认值为30
  • 返回值为包含扩展因子的DataFrame

若当日形成双神,则因子为True,否则为False。

    temp_df = shift_till_n(df, ['zt'], delta_days, fill_value=False)

移动涨停因子,求取近delta_days天内的涨停情况,保存在一个临时DataFrame中。

    col_list = ['zt_{}a'.format(x) for x in range(2, delta_days + 1)]

生成列表,用于后续检索第2天前至第delta_days天前是否有涨停出现。

    df['ss'] = temp_df[col_list].any(axis=1) & ~temp_df['zt_1a'] & temp_df['zt']

计算双神,需同时满足3个条件:
1、第2天前至第delta_days天前,至少有1个涨停
2、1天前不是涨停(否则就是连续涨停,不是间隔的涨停)
3、当天是涨停

    return df

返回包含双神因子的DataFrame。
以下是三美股份sh.603379在2021年9月6日至2021年9月17日10个交易日的因子计算情况:

           date   open   high    low  ...   pcfNcfTTM  isST     zt     ss
593  2021-09-06  26.08  27.56  25.58  ...  -59.964931     0  False  False
594  2021-09-07  28.12  30.26  27.01  ...  -65.959245     0   True   True
595  2021-09-08  31.35  31.42  29.26  ...  -65.719472     0  False  False
596  2021-09-09  30.10  30.50  28.85  ...  -66.482385     0  False  False
597  2021-09-10  30.55  31.99  28.20  ...  -67.572260     0  False  False
598  2021-09-13  31.58  33.38  30.49  ...  -70.841885     0  False  False
599  2021-09-14  32.52  35.00  31.44  ...  -71.822773     0  False  False
600  2021-09-15  33.02  36.25  32.10  ...  -79.015949     0   True   True
601  2021-09-16  37.90  38.00  35.30  ...  -77.381136     0  False  False
602  2021-09-17  35.51  39.05  35.51  ...  -85.119250     0   True   True

[10 rows x 19 columns]

对照上文中的K线图,9月7日双神是因为8月19日和9月7日都是涨停,9月15日双神是因为9月7日和9月15日都是涨停,9月17日双神是因为9月15日和9月17日都是涨停,计算结果正确。

修改计算扩展因子函数

def extend_factor(df):
    df = df.pipe(zt).pipe(ss, delta_days=30)
    return df

使用pipe计算扩展因子,这里依次计算涨停和双神因子。

小结

本文主要介绍了双神因子的计算,后续继续介绍策略所需的其他因子的实现方式。

到目前为止,创建的数据只是用于打印,未实现存储。因此只要确保程序能正常运行即可,不需要等待程序运行结束。等后续文章所有因子都介绍完成后,我们会进行多线程计算,并将结果保存到MySQL中。

data_center_v4.py的全部代码如下:

import baostock as bs
import datetime
import sys
import numpy as np
import pandas as pd

g_available_days_limit = 250

g_baostock_data_fields = 'date,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,peTTM,pbMRQ, psTTM,pcfNcfTTM,isST'

def get_stock_codes(date=None):
"""
    获取指定日期的A股代码列表

    若参数date为空,则返回最近1个交易日的A股代码列表
    若参数date不为空,且为交易日,则返回date当日的A股代码列表
    若参数date不为空,但不为交易日,则打印提示非交易日信息,程序退出

    :param date: 日期
    :return: A股代码的列表
"""

    bs.login()

    stock_df = bs.query_all_stock(date).get_data()

    if 0 == len(stock_df):

        if date is not None:
            print('当前选择日期为非交易日或尚无交易数据,请设置date为历史某交易日日期')
            sys.exit(0)

        delta = 1
        while 0 == len(stock_df):
            stock_df = bs.query_all_stock(datetime.date.today() - datetime.timedelta(days=delta)).get_data()
            delta += 1

    bs.logout()

    stock_df = stock_df[(stock_df['code'] >= 'sh.600000') & (stock_df['code'] < 'sz.399000')]

    return stock_df['code'].tolist()

def create_data(stock_codes, from_date='1990-12-19', to_date=datetime.date.today().strftime('%Y-%m-%d'),
                adjustflag='2'):
"""
    下载指定日期内,指定股票的日线数据,计算扩展因子

    :param stock_codes: 待下载数据的股票代码
    :param from_date: 日线开始日期
    :param to_date: 日线结束日期
    :param adjustflag: 复权选项 1:后复权  2:前复权  3:不复权  默认为前复权
    :return: None
"""

    for code in stock_codes:
        print('正在下载{}...'.format(code))

        bs.login()

        out_df = bs.query_history_k_data_plus(code, g_baostock_data_fields, start_date=from_date, end_date=to_date,
                                              frequency='d', adjustflag=adjustflag).get_data()

        bs.logout()

        if out_df.shape[0]:
            out_df = out_df[(out_df['volume'] != '0') & (out_df['volume'] != '')]

        if not out_df.shape[0]:
            continue

        out_df.drop_duplicates(['date'], inplace=True)

        if out_df.shape[0] < g_available_days_limit:
            continue

        convert_list = ['open', 'high', 'low', 'close', 'preclose', 'volume', 'amount', 'turn', 'pctChg']
        out_df[convert_list] = out_df[convert_list].astype(float)

        out_df.reset_index(drop=True, inplace=True)

        out_df = extend_factor(out_df)

        print(out_df)

def extend_factor(df):
"""
    计算扩展因子

    :param df: 待计算扩展因子的DataFrame
    :return: 包含扩展因子的DataFrame
"""

    df = df.pipe(zt).pipe(ss, delta_days=30)

    return df

def zt(df):
"""
    计算涨停因子

    若涨停,则因子为True,否则为False
    以当日收盘价较前一日收盘价上涨9.8%及以上作为涨停判断标准

    :param df: 待计算扩展因子的DataFrame
    :return: 包含扩展因子的DataFrame
"""

    df['zt'] = np.where((df['close'].values >= 1.098 * df['preclose'].values), True, False)

    return df

def shift_i(df, factor_list, i, fill_value=0, suffix='a'):
"""
    计算移动因子,用于获取前i日或者后i日的因子

    :param df: 待计算扩展因子的DataFrame
    :param factor_list: 待移动的因子列表
    :param i: 移动的步数
    :param fill_value: 用于填充NA的值,默认为0
    :param suffix: 值为a(ago)时表示移动获得历史数据,用于计算指标;值为l(later)时表示获得未来数据,用于计算收益
    :return: 包含扩展因子的DataFrame
"""

    shift_df = df[factor_list].shift(i, fill_value=fill_value)

    shift_df.rename(columns={x: '{}_{}{}'.format(x, i, suffix) for x in factor_list}, inplace=True)

    df = pd.concat([df, shift_df], axis=1)

    return df

def shift_till_n(df, factor_list, n, fill_value=0, suffix='a'):
"""
    计算范围移动因子

    用于获取前/后n日内的相关因子,内部调用了shift_i

    :param df: 待计算扩展因子的DataFrame
    :param factor_list: 待移动的因子列表
    :param n: 移动的步数范围
    :param fill_value: 用于填充NA的值,默认为0
    :param suffix: 值为a(ago)时表示移动获得历史数据,用于计算指标;值为l(later)时表示获得未来数据,用于计算收益
    :return: 包含扩展因子的DataFrame
"""

    for i in range(n):
        df = shift_i(df, factor_list, i + 1, fill_value, suffix)
    return df

def ss(df, delta_days=30):
"""
    计算双神因子,即间隔的两个涨停

    若当日形成双神,则因子为True,否则为False

    :param df: 待计算扩展因子的DataFrame
    :param delta_days: 两根涨停间隔的时间不能超过该值,否则不判定为双神,默认值为30
    :return: 包含扩展因子的DataFrame
"""

    temp_df = shift_till_n(df, ['zt'], delta_days, fill_value=False)

    col_list = ['zt_{}a'.format(x) for x in range(2, delta_days + 1)]

    df['ss'] = temp_df[col_list].any(axis=1) & ~temp_df['zt_1a'] & temp_df['zt']

    return df

if __name__ == '__main__':
    stock_codes = get_stock_codes()
    create_data(stock_codes)

博客内容只用于交流学习,不构成投资建议,盈亏自负!
个人博客:https://coderx.com.cn/(优先更新)
欢迎大家转发、留言。已建微信群用于学习交流,群1已满,群2已创建,感兴趣的读者请扫码加微信!

Original: https://blog.csdn.net/m0_46603114/article/details/121594845
Author: 码农甲V
Title: 股票因子扩展2(双神因子计算)——从零到实盘5

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/739385/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球