使用Tushare的股票数据与Echarts可视化结合
tushare ID=399224
由于最近学习了些前端可视化知识,并且想结合到一些实际案例当中,于是乎想做个股市看板,用Tushare与Echarts相结合,首先绘制一张K线图,因为看板的制作工作量也挺大,所以分为多节笔记来做,第一步就首先画某只股票的K线。
至于如何从Tushare导出想要的数据,我自己就将Tushare上的API接口集成了一下,写了一个工具包。接下来就直接引入包就好啦。
如果没有账号那可以注册一个,注册后可免费获取基础数据。
注册链接在这:
https://tushare.pro/register?reg=399224
import stock as st#自定义工具包---此工具包会在文章结尾给出
df=st.Basics_stock('600010').get_day()#读取包钢股份这支股票
既然使用到了Echarts那就要多做点别的东西让图片好看点(至少不会看起来这么空)。
我拿到股票的收盘价后,用一元多次方程来拟合这个收盘价,然后再找出其极值点,接着在K线图中标记出来。
下面直接贴代码:
from scipy import signal
import numpy as np
import pandas as pd
def chack_date(seq_date):
yearstop=[]
stop_time=[]
for i in range(0,seq_date.shape[0]):
# print(i)
iyear=seq_date.index[i].year
imonth=seq_date.index[i].month
iday=seq_date.index[i].day
tol_day = 0
for i in range(1, imonth):
# tol_day+=lis[i]
if i in [1, 3, 5, 7, 8, 10, 12]:
tol_day += 31
elif i == 2:
tol_day += 28
if ((iyear % 4 == 0 and iyear % 100 != 0) or iyear % 400 == 0):
tol_day += 1
else:
tol_day += 30
tol_day += iday
stop_time.append(tol_day)
for i in range(0,len(stop_time)):
if i!=len(stop_time)-1:
if stop_time[i]<stop_time[i+1]:
yearstop.append(i)
return [0]+yearstop+[seq_date.shape[0]]
stop_time=chack_date(df)
因为自开盘以来的序列较长,所以我们把序列按年份截取,分别拟合
接着就是用一元多次方程拟合,使序列平滑再把极值点标记出来。
上代码:
cut_point=[]
for i in range(0,len(stop_time)):
seq=np.array(df['close'])
if i!=len(stop_time)-1:
y=seq[stop_time[i]:stop_time[i+1]]
x=np.arange(0,len(y))
z1=np.polyfit(x,y,12)
p1=np.poly1d(z1)
yvals=p1(x)
num_peak_3 = signal.find_peaks(yvals, distance=10) #distance表极大值点的距离至少大于等于10个水平单位
peak_ind = signal.argrelextrema(yvals,np.greater)[0] #极大值点,改为np.less即可得到极小值点
max_point=signal.argrelextrema(yvals,np.greater)[0]
min_point=signal.argrelextrema(yvals,np.less)[0]
for point in max_point:
cut_point.append(stop_time[i]+point)
for point in min_point:
cut_point.append(stop_time[i]+point)
print(cut_point)
df['point'] = None
df.iloc[cut_point,-1]=1
df=df.fillna(0)
然后我们就拿到了我们所需要的所有数据了,接下来导出数据,然后就是交给echarts了。
dist_data={
'open':list(df['open']),
'close':list(df['close']),
"lowest":list(df['low']),
"highest":list(df['high']),
}
data=pd.DataFrame(dist_data)
date=list(str(i).split(' ')[0] for i in df.index)
date.reverse()
base_data=[list(data.iloc[i,:]) for i in range(0,data.shape[0])]
base_data.reverse()
point=list(df['point'])
point.reverse()
js_stop_point=[]
json_data={"date":date,'data':base_data,'point':point}
import json
b = json.dumps(json_data)
f2 = open('data.js', 'w')
# print(type('b'))
f2.write('var data='+b+';')
f2.close()
我们得到了一个有数据的js文件。接下来是见证奇迹的时刻
还是直接上代码,这次是js文件的编写,以上内容我都是放在同一个文件夹下执行的。
JavaScript还需要导入jquery这个包。
(
function(){
var chartDom = document.getElementById('main');
var myChart = echarts.init(chartDom);
var option;
const upColor = '#ec0000';
const upBorderColor = '#8A0000';
const downColor = '#00da3c';
const downBorderColor = '#008F28';
// Each item: open,close,lowest,highest
// const data0 = splitData(data.data);
extremum_point=[]
for(let index=0;index<data.point.length;index++){
if(data.point[index]==1){
var person ={
name:'Mark',
coord:[data.date[index],data.data[index][0]],
value:data.data[index][0],
};
extremum_point.push(person)
}
}
extremum_point.push([{
name: 'highest value',
type: 'max',
valueDim: 'highest'
},
{
name: 'lowest value',
type: 'min',
valueDim: 'lowest'
},
{
name: 'average value on close',
type: 'average',
valueDim: 'close'
}]);
function calculateMA(dayCount) {
var result = [];
for (var i = 0, len = data.data.length; i < len; i++) {
if (i < dayCount) {
result.push('-');
continue;
}
var sum = 0;
for (var j = 0; j < dayCount; j++) {
sum += +data.data[i - j][1];
}
result.push(sum / dayCount);
}
return result;
}
option = {
title: {
text: '包钢股份',
left: 0
},
// tooltip: {
// trigger: 'axis',
// axisPointer: {
// show: true
// }
// },
legend: {
data: ['日K', 'MA5', 'MA10', 'MA20', 'MA30']
},
grid: {
left: '10%',
right: '10%',
bottom: '15%'
},
xAxis: {
type: 'category',
data: data.date,
boundaryGap: false,
axisLine: { onZero: false },
splitLine: { show: false },
min: 'dataMin',
max: 'dataMax'
},
yAxis: {
scale: true,
splitArea: {
show: true
}
},
dataZoom: [
{
type: 'inside',
start: 95,
end: 100
},
{
show: true,
type: 'slider',
top: '90%',
start: 95,
end: 100
}
],
series: [
{
name: '日K',
type: 'candlestick',
data: data.data,
itemStyle: {
color: upColor,
color0: downColor,
borderColor: upBorderColor,
borderColor0: downBorderColor
},
markPoint: {
label: {
formatter: function (param) {
return param != null ? param.value.toFixed(2) + '' : '';
}
},
data: extremum_point,
tooltip: {
formatter: function (param) {
return param.name + '<br>' + (param.data.coord || '');
}
}
},
markLine: {
symbol: ['none', 'none'],
data: [
[
{
name: 'from lowest to highest',
type: 'min',
valueDim: 'lowest',
symbol: 'circle',
symbolSize: 10,
label: {
show: false
},
emphasis: {
label: {
show: false
}
}
},
{
type: 'max',
valueDim: 'highest',
symbol: 'circle',
symbolSize: 10,
label: {
show: false
},
emphasis: {
label: {
show: false
}
}
}
],
{
name: 'min line on close',
type: 'min',
valueDim: 'close'
},
{
name: 'max line on close',
type: 'max',
valueDim: 'close'
},
extremum_point
]
}
},
{
name: 'MA5',
type: 'line',
data: calculateMA(5),
smooth: true,
lineStyle: {
opacity: 0.5
}
},
{
name: 'MA10',
type: 'line',
data: calculateMA(10),
smooth: true,
lineStyle: {
opacity: 0.5
}
},
{
name: 'MA20',
type: 'line',
data: calculateMA(20),
smooth: true,
lineStyle: {
opacity: 0.5
}
},
{
name: 'MA30',
type: 'line',
data: calculateMA(30),
smooth: true,
lineStyle: {
opacity: 0.5
}
}
]
};
option && myChart.setOption(option);
})();
打开对应的html文件,我们就能看到K线图了
得益于前端交互的特性,我们可以拖拽观察不同窗口期的K线
做了这么久就做好看板的第一张图了,接下来还会结合机器学习对股市做相应的分析并把结果可视化,后续持续更新当中。下面贴上stock这个小工具包:
import tushare as ts
import pandas as pd
import numpy as np
token=""
pro = ts.pro_api(token)
class Basics_stock:
def __init__(self, number):
self.number = number
def get_ts_code(self):
if_stock=[]
data = pd.DataFrame()
data = pro.query('stock_basic', exchange='', list_status='L', fields='ts_code,symbol,name,industry')
if_stock=data[data["symbol"]==str(self.number)]
train_data = np.array(if_stock) #先将数据框转换为数组
train_data_list = train_data.tolist()
return train_data_list[0]
def date_transform(self,date_list):
final_date=[]
for i in date_list:
final_date.append(i[0:4]+"-"+i[4:6]+"-"+i[6:])
return final_date;
def get_index(self,start="",end=""):
data=pd.DataFrame()
if (self.number).find(".")!=-1:
data= pro.index_daily(ts_code=self.number, start_date=start, end_date=end)
else:
print("代码错误!")
return 0;
data.loc[:,('trade_date')]=Basics_stock(self.number).date_transform(data["trade_date"])
data.index=pd.to_datetime(data.trade_date,format='%Y-%m-%d')
data.drop('trade_date',axis = 1,inplace = True)
return data;
def get_day(self,start="",end="",fields=[]):
ts_code=(Basics_stock(self.number).get_ts_code())[0]
df = pro.daily(ts_code=ts_code,start_date=start, end_date=end, fields=",".join(fields))
#ts_code|trade_date|open|high|low|close|pre_close|change|pct_chg|vol|amount
df.loc[:,('trade_date')]=Basics_stock(self.number).date_transform(df["trade_date"])
df.index=pd.to_datetime(df.trade_date,format='%Y-%m-%d')
df.drop('trade_date',axis = 1,inplace = True)
return df
def get_weekly(self,start="",end=""):
ts_code=(Basics_stock(self.number).get_ts_code())[0]
df = pro.weekly(ts_code=ts_code,start_date=start, end_date=end)
#ts_code|trade_date|open|high|low|close|pre_close|change|pct_chg|vol|amount
df.loc[:,('trade_date')]=Basics_stock(self.number).date_transform(df["trade_date"])
df.index=pd.to_datetime(df.trade_date,format='%Y-%m-%d')
df.drop('trade_date',axis = 1,inplace = True)
return df
# df = pro.monthly(ts_code='000001.SZ', start_date='20180101', end_date='20181101', fields='ts_code,trade_date,open,high,low,close,vol,amount')
def get_monthly(self,start="",end=""):
ts_code=(Basics_stock(self.number).get_ts_code())[0]
df = pro.monthly(ts_code=ts_code,start_date=start, end_date=end)
#ts_code|trade_date|open|high|low|close|pre_close|change|pct_chg|vol|amount
df.loc[:,('trade_date')]=Basics_stock(self.number).date_transform(df["trade_date"])
df.index=pd.to_datetime(df.trade_date,format='%Y-%m-%d')
df.drop('trade_date',axis = 1,inplace = True)
return df
End===========================================
做完收工