iT邦幫忙

0

詢問使用python製作MACD指標線出現錯誤訊息

  • 分享至 

  • xImage

請問在使用深智數位這本書的範例時出現問題
目前是使用spyder(python3.9),不曉得是不是python版本的問題
目的是要繪製出MACD指標線
程式碼如下:

# !/usr/bin/env python
# coding=utf-8
import pandas as pd
import matplotlib.pyplot as plt 
import pymysql
import sys
# 第一個參數是資料,第二個參數是周期
def calEMA(df, term): 
    for i in range(len(df)):
        if i==0:    # 第一天
            df.ix[i,'EMA']=df.ix[i,'close']
        if i>0:
            df.ix[i,'EMA']=(term-1)/(term+1)*df.ix[i-1,'EMA']+2/(term+1)*df.ix[i,'close']
    EMAList=list(df['EMA'])
    return EMAList
# 定義計算MACD的方法 
def calMACD(df, shortTerm=12, longTerm=26, DIFTerm=9):
    shortEMA = calEMA(df, shortTerm)
    longEMA = calEMA(df, longTerm)
    df['DIF'] = pd.Series(shortEMA) - pd.Series(longEMA)
    for i in range(len(df)):
        if i==0:    # 第一天
            df.ix[i,'DEA'] = df.ix[i,'DIF']     # ix可以透過標簽名和索引來取得資料
        if i>0:  
            df.ix[i,'DEA'] = (DIFTerm-1)/(DIFTerm+1)*df.ix[i-1,'DEA'] + 2/(DIFTerm+1)*df.ix[i,'DIF']  
    df['MACD'] = 2*(df['DIF'] - df['DEA'])
    return df[['date','DIF','DEA','MACD']]
    # return df
try:
    # 開啟資料庫連線
    db = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="pythonstock")
except:
    print('Error when Connecting to DB.')   
    sys.exit()  
cursor = db.cursor()
cursor.execute("select * from stock_600895")
cols = cursor.description   # 傳回列名
heads = []
# 依次把每個cols元素中的第一個值放入col陣列
for index in cols:
    heads.append(index[0])
result = cursor.fetchall()
df = pd.DataFrame(list(result))
df.columns=heads
print(calMACD(df, 12, 26, 9))   # 輸出結果      
stockDataFrame = calMACD(df, 12, 26, 9)
# 開始繪圖
plt.figure()
stockDataFrame['DEA'].plot(color="red",label='DEA')
stockDataFrame['DIF'].plot(color="blue",label='DIF')
plt.legend(loc='best')      # 繪制圖例
# 設定MACD柱狀圖
for index, row in stockDataFrame.iterrows():
    if(row['MACD'] >0):     # 大於0則用紅色
        plt.bar(row['date'], row['MACD'],width=0.5, color='red')        
    else:                   # 小於等於0則用綠色 
        plt.bar(row['date'], row['MACD'],width=0.5, color='green')
# 設定x軸座標的標簽和旋轉角度
major_index=stockDataFrame.index[stockDataFrame.index%10==0]
major_xtics=stockDataFrame['date'][stockDataFrame.index%10==0]
plt.xticks(major_index,major_xtics)
plt.setp(plt.gca().get_xticklabels(), rotation=30) 
# 帶網格線,且設定了網格型態
plt.grid(linestyle='-.') 
plt.title("600895張江高科的MACD圖")
plt.rcParams['axes.unicode_minus'] = False 
plt.rcParams['font.sans-serif']=['SimHei']
plt.show()

出現錯誤訊息為:
https://ithelp.ithome.com.tw/upload/images/20231002/20163814GccflZ1oWn.png

上面的程式碼資料來自於下方的"把爬取到的資料存入資料表"程式:
我是用navicat連結到資料庫的

# !/usr/bin/env python
# coding=utf-8
import pymysql
import sys
import tushare as ts
import pandas as pd
import pandas_datareader

try:
    # 開啟資料庫連線
    db = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="pythonstock")
except:
    print('Error when Connecting to DB.')   
    sys.exit()
cursor = db.cursor()
# 從網站爬取資料,並插入到對應的資料表中
def insertStockData(code,startDate,endDate):
    try:
        filename='D:\\stockData\ch8\\'+code+startDate+endDate+'.csv'
        stock = pandas_datareader.get_data_yahoo(code+'.ss',startDate,endDate)
        if(len(stock)<1):
            stock= pandas_datareader.get_data_yahoo(code+'.sz',startDate,endDate)
        # 移除最後一行,因為get_data_yahoo會多取一天的股票交易資料
        stock.drop(stock.index[len(stock)-1],inplace=True)        # 在本機留份csv
        print('Current handle:' + code)
        stock.to_csv(filename)
        df = pd.read_csv(filename,encoding='gbk')
        cnt=0
        while cnt<=len(df)-1:
            date=df.iloc[cnt]['Date']
            open=df.iloc[cnt]['Open']
            close=df.iloc[cnt]['Close']
            high=df.iloc[cnt]['High']
            low=df.iloc[cnt]['Low']
            vol=df.iloc[cnt]['Volume']
            tableName='stock_'+code
            values = [date,float(open),float(close),float(high),float(low),int(vol)]
            insertSql='insert into '+tableName+' (date,open,close,high,low,vol) values (%s,%s,%s,%s,%s,%s)'
            cursor.execute(insertSql, values)
            cnt=cnt+1
        db.commit()   
    except Exception as e:
        print('Error when inserting the data of:' + code)
        print(repr(e))
        db.rollback()
startDate='2018-08-01'
endDate='2019-05-31'
stockList=['600460']
for code in stockList:
    insertStockData(code,startDate,endDate)     
'''            
stockList=ts.get_stock_basics()  # 透過tushare接口取得股票程式碼
for code in stockList.index:
    insertStockData(code,startDate,endDate)            
'''
cursor.close()
db.close()

錯誤訊息為:https://ithelp.ithome.com.tw/upload/images/20231004/20163814rG4aEOwvzE.png
另外我是用navicat連結到資料庫的
https://ithelp.ithome.com.tw/upload/images/20231004/20163814K63X8B5wbs.png
目前還處於python初學階段,再請各位協助解決,謝謝。

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
sam0407
iT邦大師 1 級 ‧ 2023-10-03 10:22:11

您看的書名是什麼?我最近也都在學習相關的知識,有空可以私訊交流~~

錯誤訊息一開頭就顯示是44行出問題,44行是df.columns=heads
最後一行錯誤訊息是:ValueError: Length mismatch: Expected axis has 0 elements, new values have 6 elements
表示在更改DataFrame的欄位名稱時,heads裡的元素個數與DataFrame欄位數量對不上

所以先請您在44行前加兩行:

print(heads)
print(result)

確認您從資料庫中有正確的讀出股票資料

samwnkyat iT邦新手 5 級 ‧ 2023-10-04 13:18:58 檢舉

你好~
印出heads和result結果如下:
['date', 'open', 'close', 'high', 'low', 'vol']
()
結果沒讀到資料,原來是上一個程式碼沒有從網站爬取到資料,應該是網站更新了?!
我再更新一下發問內容,您再協助檢查是不是這樣

sam0407 iT邦大師 1 級 ‧ 2023-10-05 12:00:45 檢舉

我覺得應該要先確認下面這個函數能不能正確的抓到資料,因為現在網站改版速度太快,您去Yahoo網站爬資料出問題的機會比較大
pandas_datareader.get_data_yahoo

我要發表回答

立即登入回答