使用Python畫(huà)股票的K線圖的方法步驟
導(dǎo)言
本文簡(jiǎn)單介紹了如何從網(wǎng)易財(cái)經(jīng)獲取某支股票的價(jià)格數(shù)據(jù),并根據(jù)價(jià)格數(shù)據(jù)畫(huà)出相應(yīng)的日K線圖。有助于新手了解并使用Python的相關(guān)功能。包括列表、自定義函數(shù)、for循環(huán)、if函數(shù)以及如何使用matplotlib進(jìn)行作圖等內(nèi)容。
第一步:從網(wǎng)易財(cái)經(jīng)獲取股票的價(jià)格數(shù)據(jù)
我一般是在網(wǎng)易財(cái)經(jīng)查看某支股票的價(jià)格和成交數(shù)據(jù),網(wǎng)易財(cái)經(jīng)可以查到任意滬深的股票,我們使用招商銀行的數(shù)據(jù)作為參考。
1、構(gòu)建爬蟲(chóng)獲取股票價(jià)格數(shù)據(jù)
這里不對(duì)Python做介紹了,如果需要了解什么是Python,可以自行百度或者訪問(wèn)Python官網(wǎng).
加載需要的模塊
代碼如下:
import re,urllib2,time,csv,datetime import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.finance as mpf import matplotlib.dates as mpd
其中urllib2是用來(lái)解析HTML內(nèi)容的包,主要是從url獲取網(wǎng)頁(yè)內(nèi)容;re是正則表達(dá)式包,本文會(huì)使用正則表達(dá)式來(lái)從抓取的網(wǎng)頁(yè)數(shù)據(jù)中獲取到有用的數(shù)據(jù);time和datetime是時(shí)間相關(guān)的包,主要用來(lái)設(shè)定要抓取的時(shí)間以及其它相關(guān)時(shí)間的處理;csv包是用來(lái)生成csv數(shù)據(jù)(該數(shù)據(jù)會(huì)被用于R來(lái)畫(huà)K線圖),其余的幾個(gè)包會(huì)在使用時(shí)單獨(dú)介紹,你也可以在需要的時(shí)候在程序頭部補(bǔ)充import。
設(shè)定時(shí)間相關(guān)
代碼如下:
t = time.localtime() # 獲取當(dāng)前的本地時(shí)間 year = range(t[0],1989,-1) # 設(shè)定年度范圍,從當(dāng)前年度至滬市開(kāi)市的年份倒序生成 season = range(4,0,-1) # 生成季度的數(shù)據(jù)列表,從4季度到1季度倒序生成
為什么要這么設(shè)定時(shí)間呢?仔細(xì)的查看網(wǎng)易股票數(shù)據(jù)的url,是按照年度和季度來(lái)構(gòu)成的,我們發(fā)現(xiàn)搜索數(shù)據(jù)也是用年度和季度來(lái)搜索的。

招商銀行2017年1季度數(shù)據(jù)
其url構(gòu)成如下:http://quotes.money.163.com/trade/lsjysj_600036.html?year=2017&season=1可見(jiàn)可拆為6個(gè)子字符串,分別是http://quotes.money.163.com/trade/lsjysj_、600036、.html?year=、2017、&season=、1。其中第2、4、6個(gè)子串可以參數(shù)化輸入獲取特定需求的數(shù)據(jù)。
定義獲取數(shù)據(jù)的函數(shù)
代碼如下:
def getData(url):
request = urllib2.Request(url)
response = urllib2.urlopen(request)
content = response.read()
pattern = re.compile('</thead[\s\S]*</tr> </table>')
ta = re.findall(pattern, str(content))
pattern1 = re.compile("<td class='cGreen'>")
pattern2 = re.compile("<td class='cRed'>")
pattern3 = re.compile(",")
tab1 = re.sub(pattern1,"<td>",str(ta))
tab2 = re.sub(pattern2,"<td>",str(tab1))
tab = re.sub(pattern3, "", str(tab2))
if len(tab) == 0:
data = []
else:
pattern3 = re.compile('<td>(.*?)</td>')
data = re.findall(pattern3, str(tab))
for d in data:
if d == '':
data.remove('')
return data
本段代碼定義個(gè)一個(gè)函數(shù)getDate(url),函數(shù)名為getData,參數(shù)為url。相當(dāng)于從該url獲取股票的交易數(shù)據(jù),顯然這個(gè)函數(shù)是定制的。
首先,我們用urllib2模塊的相關(guān)函數(shù)解析并獲取網(wǎng)頁(yè)的數(shù)據(jù)。第二步,使用re模塊的數(shù)據(jù)對(duì)抓取的網(wǎng)頁(yè)內(nèi)容進(jìn)行初步的處理,分為了三個(gè)過(guò)程
- 首先匹配"</thead[\s\S]*</tr> </table>"之間的內(nèi)容并返回,因?yàn)樵谶@之間的內(nèi)容包含了所有需要的數(shù)據(jù),這是一個(gè)簡(jiǎn)單的正則表達(dá)式,表示返回</thead和</tr> </table>兩個(gè)字符串之間的所有內(nèi)容
- 匹配<td class='cGreen'>、<td class='cRed'>并使用<td>替換,因?yàn)檫@兩個(gè)字符串會(huì)影響后續(xù)的匹配數(shù)據(jù),現(xiàn)行替換掉可以更方便的匹配到需要的數(shù)據(jù)
- 替換到千分位","號(hào),因?yàn)镻ython和R并不會(huì)識(shí)別有千分位號(hào)的數(shù)據(jù),所以我們要將數(shù)據(jù)轉(zhuǎn)換為非千分位的數(shù)據(jù)。
- tab是按照要求最后獲取的包含數(shù)據(jù)和文本的原始內(nèi)容
- 用if函數(shù)來(lái)獲取除文本的數(shù)據(jù),因?yàn)槿绻鹹ear和season超過(guò)了當(dāng)前的界限,會(huì)返回空的tab,所以我們?cè)谶@里進(jìn)行判斷,如果少了這個(gè)判斷,會(huì)報(bào)出index error。這個(gè)if函數(shù)表示了如果tab為空,data也是個(gè)空的列表,如果tab不為空,那么根據(jù)pattern3返回需要的數(shù)據(jù)至data列表
- 用一個(gè)for循環(huán)來(lái)遍歷data列表,刪除空白的內(nèi)容(其實(shí)這一步不需要,因?yàn)樵趇f中已經(jīng)剔除了空的內(nèi)容。
所以定義了以上的函數(shù)后,就可以使用該函數(shù)返回特定url的數(shù)據(jù)。
獲取某支股票的數(shù)據(jù)
代碼如下:
def get_stock_price(code):
url1 = "http://quotes.money.163.com/trade/lsjysj_"
url2 = ".html?year="
url3 = "&season="
urllist = []
for k in year:
for v in season:
urllist.append(url1+str(code)+url2+str(k)+url3+str(v))
price = []
for url in urllist:
price.extend(getData(url))
return price
自定義get_stock_price(code)函數(shù),code是指股票代碼,使用該函數(shù)可以返回該股票所有的歷史數(shù)據(jù)(OHLC以及其它)思路很簡(jiǎn)單:
- 根據(jù)code構(gòu)建其股票數(shù)據(jù)的頁(yè)面的url列表
- 使用getData(url)函數(shù)和for循環(huán),返回所有的歷史數(shù)據(jù)
最終返回的是price的數(shù)據(jù)列表
這樣,我們就可以使用該函數(shù)獲取某支股票的所有歷史數(shù)據(jù):
# get all histrocial data include all price and others price = get_stock_price(600036)
獲取招商銀行(600036)的所有歷史數(shù)據(jù)。
2、保存數(shù)據(jù)
保存為csv文件
代碼如下:
writer = csv.writer(file("stock.csv",'wb'))
writer.writerow(['Date','Open','High','Low','Close','Volume'])
pr = []
for i in range(0,len(price),11):
pr.extend([[price[i],price[i+1],price[i+2],price[i+3],price[i+4],price[i+8]]])
for prl in pr:
writer.writerow(prl)
我們使用csv模塊保存數(shù)據(jù)為csv文件,用于在R中讀取并作圖,我們查看在網(wǎng)易的數(shù)據(jù)展示可以發(fā)現(xiàn),總共11個(gè)字段,所有我們?cè)诿?1個(gè)切片中,返回時(shí)間、OHLC(開(kāi)盤(pán)價(jià)、最高價(jià)、最低價(jià)、收盤(pán)價(jià))和交易量的數(shù)據(jù)并保存為csv的文件格式。
處理保存數(shù)據(jù)到列表
代碼如下:
# get the number for date by date2num
def Date_no(strdate):
t = time.strptime(strdate, "%Y-%m-%d")
y,m,d = t[0:3]
d = datetime.date(y, m, d)
n = mpd.date2num(d)
return n
# get the price data
pr = []
for i in range(0,len(price),11):
pr.extend([[
Date_no(price[i])
,float(price[i+1])
,float(price[i+2])
,float(price[i+3])
,float(price[i+4])
,float(price[i+8])]]
)
這個(gè)程序片段是用來(lái)處理和保存數(shù)據(jù)用于在pyhton中做出K線圖。
定義函數(shù)將字符串的時(shí)間處理為matplotlib中作圖使用的數(shù)值(直接獲取的數(shù)據(jù)中時(shí)間是字符串)
返回返回時(shí)間、OHLC(開(kāi)盤(pán)價(jià)、最高價(jià)、最低價(jià)、收盤(pán)價(jià))和交易量的數(shù)據(jù)并存儲(chǔ)在pr這個(gè)列表里
第二步:做出K線圖
在R中作圖
代碼如下:
library(quantmod)
rm(list = ls())
setwd("~/GitHub/index/")
price <- as.xts(read.zoo("stock.csv",header=TRUE,sep=",",colClasses = c("Date", rep("numeric",5))))
n <- nrow(price)
m <- nrow(price)-100
#pdf(file = "k.pdf")
chartSeries(price[c(m:n)],theme = chartTheme("white"),up.col = "red",dn.col = "green",name = "600036",time.scale = 0.5,line.type = "l",bar.type = "ohlc",major.ticks='auto', minor.ticks=TRUE)
#dev.off()
做出的圖片效果如下:

R中可以使用quantmod包中的chartSeries函數(shù)畫(huà)出K線圖,具體的使用方法可以參考chartSeries參考文檔
在Python中使用matplotlib作圖
代碼如下:
quotes = pr[0:80] print(quotes) fig,ax = plt.subplots(figsize=(30,6)) fig.subplots_adjust(bottom=0.2) mpf.candlestick_ohlc(ax,quotes,width=0.4,colorup='r',colordown='g') plt.grid(False) ax.xaxis_date() ax.autoscale_view() plt.setp(plt.gca().get_xticklabels(), rotation=30) plt.show()
K線效果圖如下:

使用matplotlib的candlestick_ohlc的參考文檔,但是目前有一些問(wèn)題,比如會(huì)將非交易日期也置放在x軸,會(huì)到至K線出現(xiàn)斷裂,等待下一步的解決方法吧。
相關(guān)的代碼已經(jīng)同步到最大的同性交友網(wǎng)站我的Github上了,可以參考,其中stock.py是主要程序。
寫(xiě)在最后:因?yàn)槲矣薪?年沒(méi)使用過(guò)python了,所有代碼可能不太簡(jiǎn)練。我也旨在解決問(wèn)題,當(dāng)然解決問(wèn)題的方法千萬(wàn)種,比如這個(gè)例子,最直接的辦法就是使用網(wǎng)易的下載所有(或者特定時(shí)間段)的數(shù)據(jù)為csv格式,然后用Excel畫(huà)K線也可以的。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
利用Python實(shí)現(xiàn)智能合約的示例詳解
智能合約是一種由計(jì)算機(jī)程序編寫(xiě)的自動(dòng)化合約,它可以在沒(méi)有第三方干預(yù)的情況下執(zhí)行交易和契約條款。這篇文章主要介紹了如何利用Python實(shí)現(xiàn)智能合約,需要的可以參考一下2023-04-04
python3 BeautifulSoup模塊使用字典的方法抓取a標(biāo)簽內(nèi)的數(shù)據(jù)示例
這篇文章主要介紹了python3 BeautifulSoup模塊使用字典的方法抓取a標(biāo)簽內(nèi)的數(shù)據(jù),結(jié)合實(shí)例形式Fenix了python3 BeautifulSoup模塊進(jìn)行數(shù)據(jù)的抓取相關(guān)操作技巧,需要的朋友可以參考下2019-11-11
Python 正則表達(dá)式入門(mén)(初級(jí)篇)
本文主要為沒(méi)有使用正則表達(dá)式經(jīng)驗(yàn)的新手入門(mén)所寫(xiě)。由淺入深介紹了Python 正則表達(dá)式,有需要的朋友可以看下2016-12-12
python人工智能tensorflow函數(shù)tf.assign使用方法
這篇文章主要為大家介紹了python人工智能tensorflow函數(shù)tf.assign使用方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Python3內(nèi)置模塊之json編解碼方法小結(jié)【推薦】
這篇文章主要介紹了Python3內(nèi)置模塊之json編解碼方法小結(jié),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05
python淺析守護(hù)線程與非守護(hù)線程的區(qū)別與使用
守護(hù)線程,又稱(chēng)后臺(tái)線程,它是在后臺(tái)運(yùn)行的,如果所有前臺(tái)線程都死亡,那么后臺(tái)線程就會(huì)自動(dòng)死亡,本章我們來(lái)了解守護(hù)線程與非守護(hù)線程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-08-08
python中子類(lèi)繼承父類(lèi)的__init__方法實(shí)例
這篇文章主要給大家詳細(xì)介紹了python中子類(lèi)如何繼承父類(lèi)的__init__方法,文中給出了詳細(xì)的示例代碼,相信對(duì)大家的理解和學(xué)習(xí)具有一定參考價(jià)值,有需要的朋友們下面來(lái)跟著小編一起學(xué)習(xí)學(xué)習(xí)吧。2016-12-12
python實(shí)現(xiàn)的爬取電影下載鏈接功能示例
這篇文章主要介紹了python實(shí)現(xiàn)的爬取電影下載鏈接功能,涉及Python基于BeautifulSoup模塊的網(wǎng)頁(yè)信息爬取相關(guān)操作技巧,需要的朋友可以參考下2019-08-08

