栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 云计算 > 云平台

python计算沪深300成分股的MACD指标值--数据来源于tushare大数据社区

云平台 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python计算沪深300成分股的MACD指标值--数据来源于tushare大数据社区

文章目录
  • 前言
    • 项目主要步骤
    • 数据来源
    • 计算结果的准确性:(与choice比较)
  • 一、环境配置
  • 二、项目步骤
    • 1. 定义计算MACD指标的函数
    • 2. 定义格式转换与数据处理的函数
    • 3. main函数
  • 三、踩的坑&经验小结
    • 1. 关于 使用其他复权类型数据来计算
    • 2. 关于 空值的处理办法
    • 3. 关于 dfToSQL()
    • 4. 关于数据库:
    • 5. dataframe按时间排列的顺序


前言

今天分享本人写论文时做的一个小项目,花了好几天时间写的(论文最后竟然还没用到勞)

本文项目依据沪深300指数的300只成分股所有历史日线数据,计算出其全部历史MACD指标值,计算结果存为本地csv文件或存入数据库,以备后续使用。

指标值包括:EMA(12),EMA(26),DIF, DEA ,MACD;
示例为价格前复权,有需要的朋友可以自行改动为其他复权类型,要修改的地方文内有提示。

项目主要步骤
  • 从本地csv文件 list_hushen300.csv 获取股票列表
  • 从tushare拿到300只股票的数据,分别存入mysql,
  • 从mysql提取,计算指标值,最后再存入mysql。

本文还提供了:将拿到的tushare日线数据、计算出的指标值存为本地csv文件的函数。

数据来源

数据来源是tushare社区,在此感谢社区为广大学生提供的免费优质服务,我个人使用体验很好,也推荐大家从这里拿数据。

计算结果的准确性:(与choice比较)

(任选一只进行对比)
计算结果:

choice:


一、环境配置

IDE:pycharm
数据库:mysql, navicat
计算结果检查:choice金融终端

数据来源:tushare(需满足积分条件)

使用到的python库:

import tushare as ts

import pymysql as mdb
import numpy as np
import pandas as pd
import time
import datetime
import copy
import sqlalchemy
from sqlalchemy import create_engine
import sys
二、项目步骤 1. 定义计算MACD指标的函数

代码如下:

def ema(data, period=0, column='close', name='ema'):
    for i in range(len(data)):
        if i == 0:
            data.loc[i, name] = data.loc[i, column]
        else:
            data.loc[i, name] = (2*data.loc[i, column]+(period-1)*data.loc[i-1, name])/(period+1)
            
    return data

def macd(data, period_long=26, period_short=12, period_signal=9, column='close'):
    data = ema(data, period_long, column, 'ema'+str(period_long))
    data = ema(data, period_short, column, 'ema'+str(period_short))
    data['macd_dif'] = data['ema'+str(period_short)] - data['ema'+str(period_long)]
    data = ema(data, period_signal, 'macd_dif', 'macd_dea')
    data['macd_macd'] = 2 * (data['macd_dif'] - data['macd_dea'])
    
    return data
2. 定义格式转换与数据处理的函数
def getAStockDaily(ts_code, adj):

    """
    本函数实现从通用行情接口获取单只股票的所有历史日线数据,价格前复权,返回dataframe类型的data
    本函数须和dfToCsv一起用
    """
    if adj == "qfq":
        data = ts.pro_bar(ts_code=ts_code, adj='qfq', start_date='', end_date='')  # 不需要用format()
    if adj == "hfq":
        data = ts.pro_bar(ts_code=ts_code, adj='hfq', start_date='', end_date='')
    if adj == "None":
        data = ts.pro_bar(ts_code=ts_code, adj='None', start_date='', end_date='')
        
    return data
def dfToSQL(ts_code, df, sqlEngine):

    """
    本函数将dataframe存入mysql
    """
    df = df.loc[:, ["ts_code", "trade_date", "close"]]
    df = df.fillna(0.0, inplace=True)
    df.to_sql(name=ts_code.lower(), con=sqlEngine, index=False, if_exists='replace')  # 在函数内将ts_code转为小写再作表名
    
    return 0
def dfmacdToCsv(ts_code,df, file):
    """
    本函数专门将计算得出的macd的dateframe存到本地csv文件中。具有专用性

    """
    df.to_csv(file + "{}.csv".format(ts_code),
                columns=["ts_code", "trade_date", "close", "ema26", "ema12", "macd_dif", "macd_dea", "macd_macd"],
                encoding='utf_8_sig')
                # 未设置参数na_rep=0.0
def dfToCsv(ts_code, df, file):

    """
    本函数专门实现将从tushare通用行情接口获取的dataframe以csv存储到本地file文件中。具有专用性
    本函数必须和getAStockDaily一起用;
    """
    df.to_csv(file + "{}.csv".format(ts_code),
                columns=["ts_code", "trade_date", "open", "low", "high", "close"],
                encoding='utf_8_sig',
                na_rep=0.0)
    return 0
3. main函数
file_localCsvQfq = "data/qfq/"
file_macd = "data/stockmacd/"

""" 取沪深300列表 存入list """
list_hushen300 = pd.read_csv("../data/list_hushen300.csv")
rowNum = len(list_hushen300.index)
list300 = list(list_hushen300.iloc[1:rowNum,2])
print(list300)

""" 计算沪深300的MACD,然后存到数据库 """
''' 读取沪深300列表 ,存入list'''
list_hushen300 = pd.read_csv("data/list_hushen300.csv")
rowNum = len(list_hushen300.index)
list300 = list(list_hushen300.iloc[0:rowNum, 2])  # 应该是iloc[0:rowNum,2]),详细原因见dataframe用法

''' 建立数据库连接 '''
conn = mdb.connect(host="localhost", port=3306, user='root', passwd='123456', db='stockdate_qfq', charset='utf8')
engine = create_engine("mysql+mysqldb://username:password@localhost:3306/stockdate_qfq?charset=utf8")
engine2 = create_engine("mysql+mysqldb://username:password@localhost:3306/stockmacd?charset=utf8")
cursor = conn.cursor() # 游标其实没有用到

''' 循环执行 一直到计算macd后存到MySQL'''
#使用两层循环来控制节奏
for i in range(10):
    print("第"+str(i)+"批执行中,共10批")  # 打算用三次
    # list_period = list300[10*i:10*i+10]  # 第一次
    # list_period = list300[10*i+100:10*i+110] # 第二次
    list_period = list300[10*i+200:10*i+210]  # 第三次

    for ts_code in list_period:
        # 访问tushare接口获取dateframe:
        data =getAStockDaily(ts_code, "qfq")

        ''' 转为本地csv: '''
        dfToCsv(ts_code, data, file_localCsvQfq)

        ''' dateframe转为SQL'''
        # df_toSQL()前的准备工作:
        data = data.loc[:, ["ts_code", "trade_date", "close"]]
        data.fillna(0.0, inplace=True)
        # 转为SQL:
        get_StocksDataFunc.dfToSQL(ts_code, data, engine)

        '''计算MACD值'''
        sql1 = "SELECT ts_code, trade_date,`close` FROM `{}` where ts_code='{}' order by trade_date asc".format(ts_code, ts_code)

        df = pd.read_sql(sql1, conn)
        df_macd = df[['ts_code', 'trade_date', 'close']]
        df = macd(df_macd, 26, 12, 9, 'close')
        # print(df_macd)

        ''' 将计算的MACD值存入本地CSV '''
        dfmacdToCsv(ts_code, df_macd, file_macd)
        ''' 将计算的MACD值存入SQL'''
        dfToSQL(ts_code, df_macd, engine2)

        '''     等待10s   '''
        print("{}已执行完毕,10s后继续执行".format(ts_code))
        time.sleep(5)
    time.sleep(20)
    

三、踩的坑&经验小结

这里对文章进行总结:

1. 关于 使用其他复权类型数据来计算

在使用getgetAStockDaily()函数时传入所需的复权类型并调整相应文件夹命名即可

2. 关于 空值的处理办法

产生空值的原因:tushare获取的数据中,部分股票较早年份的数据是没有的

影响:导致macd指标值计算有小的偏差(时间越早,影响越小),但在可接受的范围内;由于传回的日线数据dataframe中缺失数据标记是NaN,这导致计算前必须把NaN转为0.0,

处理办法:
dfToSQL()中对data使用dataframe的函数fillna(0.0, inplace=True)

dfToCsv()中,添加to_csv()函数的参数 na_rep=0.0, 将所有空值NaN转为0

3. 关于 dfToSQL()

使用df=df.loc[:, [“ts_code”, “trade_date”, “close”]] 来选择要保存的字段,字段的类型自动完成(也可以选择在函数外部来完成这一任务);

使用fillna() 将NaN值转化为0.0 , 类型是默认的,暂时不需要关心(如果不使用参数来实现转化,可以用SQL语句);

dfToSQL()中为什么有name=ts_code.lower() ?
存入数据库后数据表的表名会变为(显示为)小写,同时在做select时不区分大小写也都可以,但df格式使engine对表的大小写敏感,所以用df.to_sql(file_basename.lower()…) 将tushare传回的name无论大小写都转为小写再作表名

dfToSQL()中控制字段类型与长度等时,可以用to_sql()的dtype参数,但十分不推荐,因为看着就不好写,哈哈,感兴趣的同学可以尝试一下;

4. 关于数据库:

为什么建了两个数据库的engine ?
如果存入mysql与取出mysql中数据用了同一个engine 会报错,因为赶时间,我就建了两个来用,没有做其他测试;

5. dataframe按时间排列的顺序

从tushare基础日线接口与通用行情接口取到的数据的顺序都是:2022-1998 新到旧,但是本文的计算方法需要从旧到新开始计算,需要调整,本文采取了sql的方法来解决,感觉很好用:做select时 用一下order by trade_date asc


文章到这里就结束了,仓促写就,希望能帮到大家。本人第一篇博文,还希望大家给点个赞哈哈

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/895572.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号