使用Tushare的股票数据与Echarts可视化结合

使用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===========================================
做完收工

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值