股票量化研究基础——借助Tushare库制作自己的MACD数据库

Tushare使用

首先去Tushare社区注册自己的账号并获取token

平台支持包和http协议获取,但本文中使用接口pro_bar是集成接口,SDK层面有逻辑判断,暂时无法使用HTTP调用。

在python环境下安装tushare

pip install tushare

调用Api接口例子:

import tushare as ts
ts.set_token('your token') # 只需要在第一次或者token失效后调用,完成调取tushare数据凭证的设置,正常情况下不需要重复设置。
df = pro.trade_cal(exchange='', start_date='20180901', end_date='20181001', fields='exchange,cal_date,is_open,pretrade_date', is_open='0')

结果:

    exchange  cal_date    is_open pretrade_date
0          SSE       20180901        0      20180831
1          SSE       20180902        0      20180831
2          SSE       20180908        0      20180907
3          SSE       20180909        0      20180907
4          SSE       20180915        0      20180914
5          SSE       20180916        0      20180914
6          SSE       20180922        0      20180921
7          SSE       20180923        0      20180921
8          SSE       20180924        0      20180921
9          SSE       20180929        0      20180928
10         SSE       20180930        0      20180928
11         SSE       20181001        0      20180928
MACD及算法介绍

MACD,又称为指数平滑移动平均线,从双指数移动平均线发展而来,由快的指数移动平均线(EMA12)减去慢的指数移动平均线(EMA26)得到快线DIFF;再用DIFF的9日指数平滑移动得到慢线DEA;再用 2×(快线DIFF-加权移动均线DEA)得到MACD。

当MACD从负数转向正数,是买的信号。当MACD从正数转向负数,是卖的信号。

当MACD以大角度变化,表示快的移动平均线和慢的移动平均线的差距非常迅速的拉开,代表了一个市场大趋势的转变。

计算公式:

EMA(12)= 前一日EMA(12)×11/13+今日收盘价×2/13
EMA(26)= 前一日EMA(26)×25/27+今日收盘价×2/27
DIFF=今日EMA(12)- 今日EMA(26)
DEA(MACD)= 前一日DEA×8/10+今日DIF×2/10
BAR=2×(DIFF-DEA)

根据公式可知MACD相关参数为迭代结果,而股票发售第一日的参数如下

DIFF=0,DEA=0,BAR(MACD)=0

第二日参数如下

EMA(12)=前一日收盘价(即第一日收盘价)+(今日收盘价 - 前一日收盘价)×2/13
EMA(26)=前一日收盘价(即第一日收盘价)+(今日收盘价 - 前一日收盘价)×2/27
DIFF=EMA(12)-EMA(26)
DEA(9)=0(即前一日DEA(9))+今日DIFF×2/10
BAR=2×(DIFF-DEA)

第三日及之后的参数可由标准计算公式算得

这样,我们就可以利用tushare库获取股票历史信息,并根据公式进行计算。

考虑到A股股票众多,需要统一处理,这里的思路是:stock_basic接口获取所有上市状态的股票代码并保存下来 -> 根据获取到的股票代码集合获取每个股票的历史信息并进行公式计算,将结果保存 -> 每日收盘后只需获取当日收盘价计算更新数据库即可。


附上每日更新数据库所用py代码,包括均价计算部分,并附2021.3.30当日数据库文件

import tushare as ts
import datetime
import time
import re
import csv
import requests
import math
import pandas

def get_daily(ts_code='', trade_date='', start_date='', end_date=''):
    for _ in range(3):
        try:
            if trade_date:
                df = ts.pro_api().daily(ts_code=ts_code, trade_date=trade_date)
            else:
                df = ts.pro_api().daily(ts_code=ts_code, start_date=start_date, end_date=end_date)
        except():
            time.sleep(1)
        else:
            return df


def upload_data_daily():  # 此函数为当天收盘后的更新数据库操作 读取文件,并在此基础上更新数据 {股票代码,交易日期,当天收盘价
    # ,MA{5, 10, 20, 30, 60, 120, 250},Price{5, 10, 20, 30, 60, 120, 250},MACD{EMA12,EMA26}}
    arr = [{}]
    nowa = datetime.datetime.now()
    delta = datetime.timedelta(days=1000)
    n_days = nowa - delta
    n_days = n_days.strftime('%Y%m%d')
    nowa = nowa.strftime('%Y%m%d')
    nowa = str(nowa)
    n_days = str(n_days)
    with open('C:\\data.csv', newline='') as f:
        reader = csv.reader(f)
        for row in reader:
            if row[0] != 'ts_code':
                i = row[0]
                pri_1 = pri_5 = pri_10 = pri_20 = pri_30 = pri_60 = pri_120 = pri_250 = 0.0
                df = get_daily(ts_code=i, start_date=n_days, end_date=nowa).close
                now_date = get_daily(ts_code=i, start_date=n_days, end_date=nowa).trade_date
                if len(df) >= 1:
                    pri_1 = float(df[0])
                if len(df) >= 5:
                    for j in range(5):
                        pri_5 = pri_5 + float(df[j])
                if len(df) >= 10:
                    for j in range(10):
                        pri_10 = pri_10 + float(df[j])
                if len(df) >= 20:
                    for j in range(20):
                        pri_20 = pri_20 + float(df[j])
                if len(df) >= 30:
                    for j in range(30):
                        pri_30 = pri_30 + float(df[j])
                if len(df) >= 60:
                    for j in range(60):
                        pri_60 = pri_60 + float(df[j])
                if len(df) >= 120:
                    for j in range(120):
                        pri_120 = pri_120 + float(df[j])
                if len(df) >= 250:
                    for j in range(250):
                        pri_250 = pri_250 + float(df[j])
                pri_5 /= 5
                pri_10 /= 10
                pri_20 /= 20
                pri_30 /= 30
                pri_60 /= 60
                pri_120 /= 120
                pri_250 /= 250
                y_EMA_12 = row[14]
                y_EMA_26 = row[15]
                y_DEA = row[13]
                EMA_12 = float(y_EMA_12) * 11.0 / 13 + pri_1 * 2.0 / 13
                EMA_26 = float(y_EMA_26) * 25.0 / 27 + pri_1 * 2.0 / 27
                DIFF = EMA_12 - EMA_26
                DEA = float(y_DEA) * 4.0 / 5 + DIFF / 5.0
                BAR = 2 * (DIFF - DEA)
                arr.append({"ts_code": i, "now_date": now_date[0], "list_date": row[2]
                    , "pri_1": str(pri_1), "pri_5": str(pri_5), "pri_10": str(pri_10)
                    , "pri_20": str(pri_20), "pri_30": str(pri_30), "pri_60": str(pri_60)
                    , "pri_120": str(pri_120), "pri_250": str(pri_250), "DIFF": DIFF
                    , "DEA": DEA, "BAR": BAR, "EMA_12": EMA_12
                    , "EMA_26": EMA_26})
                time.sleep(0.1)
    with open("C:\\data.csv", 'w', newline='') as k:
        fieldnames = ["ts_code", "now_date", "list_date", "pri_1", "pri_5", "pri_10", "pri_20", "pri_30", "pri_60"
                      , "pri_120", "pri_250", "DIFF", "DEA", "BAR", "EMA_12", "EMA_26"]
        writer = csv.DictWriter(k, fieldnames=fieldnames)
        writer.writeheader()
        for i in range(3041):
            writer.writerow(arr[i])


if __name__ == '__main__':
    upload_data_daily()
    print('Done.')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Time404NOTF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值