Day 29 - 计算均线资料

本篇重点

  • 在SQLite的Table中,新增栏位
  • 透过pandas.DataFrame.rolling计算均线
  • 回写资料至SQLite中

在SQLite的Table中,新增栏位

由於之前建立的日K线资料中,并没有均线的相关栏位,所以必须要手动增加栏位。若要在现有的Table中增加栏位,可以使用DB Browser for SQLite。
开启资料库後,请先选择所要调整的Table,再按「Modify Table」
https://ithelp.ithome.com.tw/upload/images/20211013/201408274vPkGCTZPt.png
接着按「Add」按钮,输入栏位名称并选择栏位类型
https://ithelp.ithome.com.tw/upload/images/20211013/20140827H7ViPGBoD0.png
这里我新增「MA5」、「MA20」、「MA5_diff」、「MA20_diff」这4个栏位,并将栏位类型设为「REAL」,用来储存下面要计算的均线结果,完成後按下「OK」
https://ithelp.ithome.com.tw/upload/images/20211013/20140827CZxzsUcVaO.png
因为这里只是调整Table的结构,并没实际写入资料,所以完成後直接关闭程序即可。

透过pandas.DataFrame.rolling计算均线

接着计算均线资料,我们可以透过DataFrame.rolling
pandas.DataFrame.rolling来计算
程序范例如下:

df['MA5'] = df['Close'].rolling(window=5).mean().round(2) #依照收盘价计算均线,并取至小数点後2位
df['MA20'] = df['Close'].rolling(window=20).mean().round(2)
df['MA5_diff'] = df['MA5'].diff() #计算MA5差异
df['MA20_diff'] = df['MA20'].diff()

在第一行中,我们将Close收盘价的资料抓出来执行rolling,而rolling的window参数,就是看你要计算的均线而定;例如要计算MA5(5根K线收盘价的平均价格),window就设为5,MA5资料计算完後,再回存至df['MA5']中。
下面的df['MA5_diff'],就是依照df['MA5']中的资料去做差异计算,也就是与前一笔MA5的价格差异,之所以增加这个栏位,是为了方便之後判断均线方向(向上或向下)使用。

计算均线资料的程序,也可以跟上一篇产生其它周期K线的程序一起执行并写入

回写资料至SQLite中

下面就以日K线资料为例,读取K线资料、计算均线资料并更新至Table中。

import pandas as pd
import sqlite3
# 更新资料用的SQL语法
UPDATE_SQL = '''UPDATE stocks_1day_kbars
                SET MA5 = ?,
                    MA20 = ?,
                    MA5_diff = ?,
                    MA20_diff = ?
                WHERE Code = ? AND ts = ?'''
conn = sqlite3.connect('D:/shioaji.db') #建立资料库连线
# conn = sqlite3.connect('C:/shioaji.db') #建立资料库连线
cursor = conn.cursor()

# 传入股票代码,产生MA均线及差异
def generate_ma_of_day_kbar(stock_code):
    print(f'calc MA for stock:{stock_code}')
    # 仅取出ts跟Close栏位资料,并将ts栏位设为DataFrame的Index
    df = pd.read_sql(f'SELECT ts, Close FROM stocks_1day_kbars WHERE Code = {stock_code}', 
        conn, index_col='ts')
    #依照收盘价计算MA5,并取至小数点後2位
    df['MA5'] = df['Close'].rolling(window=5).mean().round(2)
    df['MA20'] = df['Close'].rolling(window=20).mean().round(2)
    df['MA5_diff'] = df['MA5'].diff() #计算MA5差异
    df['MA20_diff'] = df['MA20'].diff()
    # 历遍df中的资料,并update至table中
    for index, row in df.iterrows():
        cursor.execute(UPDATE_SQL, (row['MA5'], row['MA20'], row['MA5_diff'], 
            row['MA20_diff'], stock_code, index))
        conn.commit()

codes = cursor.execute('SELECT DISTINCT code FROM stocks_1day_kbars').fetchall()
for code in codes:
    generate_ma_of_day_kbar(code[0])

conn.close() #关闭资料库连线

因为计算均线只需要用Close的价格去做计算,所以在read_sql只有取ts跟Close这两个栏位,并且将index_col设定为ts栏位。请注意这里并没有做parse_dates,第一是因为做parse_dates後在下面执行update动作时会出现type错误;另一个原因是rolling是以row为单位做计算,不像是resample是需要使用datetime做为计算单位。
计算完成後,再使用for loop的方式将计算的结果回写回去资料库。另一个要注意的地方是,在一开始抓所有股票的Code时,是先用fetchall将所有的资料先存入codes中,因为在同一个conn中只能有一个cursor,所以必须要先这麽做,後面的cursor在执行update时才不会有问题。


<<:  [30] 参赛心得

>>:  Day 29 Rails soft delete - paranoia

Smalltalk 语言和你 SAY HELLO!!

第二十九天 各位点进来的朋友,你们好阿 小的不才只能做这个系列的文章,但还是希望分享给点进来的朋友,...

[第22天]理财达人Mx. Ada-MACD 指标

前言 本文说明MACD技术指标。 MACD 指标 MACD指标(Moving Average Con...

Day 29 - 使用 CDK 创建 WordPress

前几天做了很多 AWS 服务使用 CDK 部署的介绍,今天我想来介绍一个满多人都有机会用到的 Blo...

python3的环境安装

我使用的版本是python3.8.6,示范安装用的目前(20210721)最新的版本 首先到官网下载...

Day20: EventEmitter

EventEmitter就是事件监听器,在Nodejs中这事件无所不在,都是基於程序中的对象会产生事...