• 半量化交易(二)


    • 一、摘要

          个人交易中的专业背景限制、资金成本限制、对股市的理解限制等等,使个人在进行量化交易时,可能出现程序推荐股票不是自己像买股票这种情况,由于投资者自身能力有限,不能全面的考虑可能出现的各种可能,所有在选择上可能存在异常的偏差。因此,本问将为个人投资者介绍另一种简单容易实现的方法,半量化交易。本文接下来也将对半量化股票的选股、指标建立、模型搭建、数据存储进行研究。

    • 二、基本框架介绍

    按照数据存储的方式不同,我们将数据划分为4个层次:

            ODS层:存储原始数据

            DW层:存储根据ODS层计算处理、晒选出来的数据

            DM层:存储DW 层中根据数据合并组合,形成的大宽表。

            APP层:直接可以拿来使用的数据

        

    三、具体实现

    1. ODS层:

    数据源为我们选择非常友好的tushare 数据。https://tushare.pro/register?reg=379880

    里面有非常多的数据,质量也非常好,非常推荐。

    在这里,我们主要选择两个方面的数据:1、日线行情数据 2、基础数据中的备用数据。

     

    具体实现:

    我们定义一个时间函数,用来对计算交易日期。并通过下面方法来获取最近一个交易日的日期。

    1. # 引入 datetime 模块
    2. import datetime
    3. def getYesterday(days):
    4. #输入距离今天几天
    5. today=datetime.date.today()
    6. #间隔天数
    7. interval_day=datetime.timedelta(days=days)
    8. #今天往前推
    9. yesterday=today-interval_day
    10. date_time = str(yesterday).replace('-','')
    11. return date_time
    12. def compute_time():
    13. # 今天
    14. now_day = getYesterday(0)
    15. #一个月前
    16. month_day = getYesterday(30)
    17. #昨2年前
    18. history_day = getYesterday(365*2)
    19. return now_day,month_day,history_day
    20. #获取交易列表
    21. trade_time=pro.trade_cal(exchange='', is_open=1,start_date=month_day, end_date=now_day)
    22. #获取最近的交易日期
    23. trade_time = trade_time['cal_date'].tail(1).values[0]

            数据的获取方法也非常简单,先读取数据库表中数据的交易日(记得去重),判断最近一个交易日是否在数据库中,如果有就不导入,如果无就进行数据获取。这样数据就获取出来了。

     

    1. #基础表数据存入数据库
    2. def bak_basic_to_sql(trade_time):
    3. #查询数据库中已经存在的基础表,避免重复插入
    4. all_time = connect_sql("select DISTINCT trade_time from `ods_bak_basic` ")
    5. #将所有时间转换为列表,循环
    6. if all_time['trade_time'].values.tolist()==[]: #判断是否为空
    7. print("数据库表 ods_bak_basic 数据为空 ,可导入")
    8. #获取最近交易日的基础信息
    9. bak_basic_data = pro.bak_basic(trade_date=trade_time)
    10. #对表数据进行重新命名
    11. bak_basic_data = bak_basic_data.rename(columns={'trade_date': 'trade_time','close':'close_price'})
    12. #数据插入数据库中
    13. inset_into_sql(bak_basic_data,'ods_bak_basic')
    14. print('ods_bak_basic {} 日数据插入成功'.format(trade_time))
    15. else:
    16. if trade_time in all_time['trade_time'].values.tolist():
    17. print("数据库表 ods_bak_basic 存在 {} 日期数据,不可导入".format(trade_time))
    18. else:
    19. print("数据库表 ods_bak_basic 不存在 {} 该日期数据,可导入".format(trade_time))
    20. #获取最近交易日的基础信息
    21. bak_basic_data = pro.bak_basic(trade_date=trade_time)
    22. #对表数据进行重新命名
    23. bak_basic_data = bak_basic_data.rename(columns={'trade_date': 'trade_time','close':'close_price'})
    24. #数据插入数据库中
    25. inset_into_sql(bak_basic_data,'ods_bak_basic')
    26. print('ods_bak_basic {} 日数据插入成功'.format(trade_time))
    27. return bak_basic_data

    2、DW 层 

     DW层里面存储行业数据,计算行业的平均(用数据透视方法就可以算了)市盈率、市净率、毛利润、同比收入等指标,每日计算一次,存储到数据库中。这里计算时需要注意一下,去除异常值。

     

    1. #将数据交易日、行业、市盈率、市净率、收入同比、毛利率、净利润等指标统计数据存入数据库中
    2. def industry_avg_inset_sql(bak_basic_data,trade_time):
    3. #查询数据库中已经存在的基础表,避免重复插入
    4. all_time = connect_sql("select DISTINCT trade_time from `dw_industry_avg_info` ")
    5. #将所有时间转换为列表,循环
    6. if all_time['trade_time'].values.tolist()==[]:
    7. print("数据库表 dw_industry_avg_info 为空,可导入")
    8. #d对数据进行处理
    9. industry_avg_info = industry_avg_compute(bak_basic_data)
    10. inset_into_sql(industry_avg_info,'dw_industry_avg_info')
    11. print('dw_industry_avg_info {} 日数据插入成功'.format(trade_time))
    12. else:
    13. if trade_time in all_time['trade_time'].values.tolist():
    14. print("数据库表 dw_industry_avg_info 存在 {} 日期数据,不可导入".format(trade_time))
    15. else:
    16. print("数据库表 dw_industry_avg_info 不存在 {} 该日期数据,可导入".format(trade_time))
    17. #d对数据进行处理
    18. industry_avg_info = industry_avg_compute(bak_basic_data)
    19. #数据插入数据库中
    20. inset_into_sql(industry_avg_info,'dw_industry_avg_info')
    21. print('dw_industry_avg_info {} 日数据插入成功'.format(trade_time))

    3、DM层

    DM层存储两个方面的数据。

    1. 结合行业平均等指标,筛选出来的优质股票信息。
    2. 根据优质股票信息,筛选出具有突破形态和“碗口战法”形态的股票信息。

    获取数据时候需要注意一下请求频率,很容易超时。我解决的办法时将股票列表存储到一个list里面,每次pop一个数据,成功则过,失败了,将请求失败的股票append回去股票列表继续请求。这样可以重复请求,和请求失败导致程序中停问题。

     

    1. #将筛选出来的优质股票信息存储到数据库中
    2. def quality_stock_to_sql(trade_time):
    3. #查询数据库中已经存在的基础表,避免重复插入
    4. all_time = connect_sql("select DISTINCT trade_time from `dm_quality_stock` ")
    5. #将所有时间转换为列表,循环
    6. if all_time['trade_time'].values.tolist()==[]:
    7. print("数据库表 dm_quality_stock 为空,可导入")
    8. #对数据进行处理
    9. dm_quality_stock = quality_stock_deal(trade_time)
    10. inset_into_sql(dm_quality_stock,'dm_quality_stock')
    11. print('dm_quality_stock {} 日数据插入成功'.format(trade_time))
    12. else:
    13. if trade_time in all_time['trade_time'].values.tolist():
    14. print("数据库表 dm_quality_stock 存在 {} 日期数据,不可导入".format(trade_time))
    15. else:
    16. print("数据库表 dm_quality_stock 不存在 {} 该日期数据,可导入".format(trade_time))
    17. #d对数据进行处理
    18. dm_quality_stock = quality_stock_deal(trade_time)
    19. #数据插入数据库中
    20. inset_into_sql(dm_quality_stock,'dm_quality_stock')
    21. print('dm_quality_stock {} 日数据插入成功'.format(trade_time))

    4、APP层

            该层存储的是目标股票状态。更具波浪理论,我们选择使用中线理论,对股票一段时间内的波段进行计算,推算出股票的目前状态,所处的历史位置,以及计算股票的回调区间、利润区间。

     

    1. def app_buy_list_to_sql(trade_time):
    2. #查询数据库中已经存在的基础表,避免重复插入
    3. all_time = connect_sql("select DISTINCT trade_time from `app_buy_list` ")
    4. #将所有时间转换为列表,循环
    5. if all_time['trade_time'].values.tolist()==[]:
    6. print("数据库表 app_buy_list 为空,可导入")
    7. #对数据进行处理
    8. app_buy_list_sql_deal(trade_time)
    9. else:
    10. if trade_time in all_time['trade_time'].values.tolist():
    11. print("数据库表 app_buy_list 存在 {} 日期数据,不可导入".format(trade_time))
    12. else:
    13. print("数据库表 app_buy_list 不存在 {} 该日期数据,可导入".format(trade_time))
    14. #d对数据进行处理
    15. app_buy_list_sql_deal(trade_time)

    四、实践一下

    我们采取保守策略,所有只筛选“可建仓区域的股票” 。具体效果还是可以的。

    好了,大概就这样,后面慢慢更新。

     

     

            

  • 相关阅读:
    React高阶组件详解
    范数-空间范数
    LLFormer 论文阅读笔记
    Java并发编程学习十:线程协作
    leetcode:279.完全平方数
    pandas连接oracle数据库并拉取表中数据到dataframe中、筛选当前时间(sysdate)到一天之前的所有数据(筛选一天范围数据)
    测试用例常见的7种设计方法
    linux 多台机器修改时间同步
    记一次调试YOLOv5+DeepSort车辆跟踪项目的经过
    Prometheus+grafana监控--初探
  • 原文地址:https://blog.csdn.net/weixin_42013825/article/details/126710277