C13-2 通过文件操作对GAFATA股票可视化的经历

看到学习群中有战友自行开始研究pandas等相关库的数据分析应用,自愧不如,得抓紧脚步,只能在其基础上自己试试文件操作该如何实现。
1、实现环境python3;需要的包:os,pandas_datareader中的data,matplotlib,pandas;
2、pandas_datareader库可用于从不同财经数据平台读取需要的数据,数据全面,包含全球主要股市。我们选择雅虎财经来获取数据。将其读取的数据存储在本地,因为需要翻墙所以存储于本地方便代码调试,防止网络不稳定重复链接增加链接中断的风险。先看看其中的属性和方法都有哪些:


dir()获取属性.png

表示看不懂,具体参数使用见链接

  https://www.jianshu.com/p/ed947ada9331?utm_campaign=haruki&utm_content=note&utm_medium=reader_share&utm_source=weixin

3、将其可按照json格式存储为csv文件,但是默认会将日期列剔除,(补充:看了官方文档才知道,并不是把日期剔除人是默认按照列的名字为第一关键字columns,索引——日期为第二关键字进行的数据存储,如果要把每一天的数据一一对应,需要orient关键字指定为index,并且默认存储日期为时间戳的格式),不利于可视化;


json格式的csv文件.png
  pd.read_json()      

读取文件默认是按照日期索引读取,但读取出的文件并不包括日期;文件的每一列相当于一个带关键字的列表;可通过.key或['key']方式直接调用;具体操作可见C12-3。在这里不建议用json格式读取和存储。
4、将其按照csv格式存储;


csv格式存为真正的csv文件.png
  pd.read_csv()      

读取出的是标准csv格式文件,但需要对日期做额外的处理;

  dateparse1 = lambda dates: pd.datetime.strptime(dates, '%Y-%m-%d')      

需要注意的是python3默认就是用utf-8方式编码,读取时对日期这样的字节格式并不需要再去定义编码方式,也就是说直接去掉python2中要用到的encoding='utf-8'就好;否则会引发“UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte”,这样的错误。

将日期作为索引去读取文件时,读取的数据会自动忽略日期这一关键字,相当于被覆盖;并且读取为日期格式时,以ns(纳秒)为默认转换方式。


日期为索引读取文件.png

因为我们需要得出每只股票的年增长率,所以需要很方便的得到第一个日期的收盘价和最后一个日期的收盘价,然后算出年增长率。

  def c_ratio(d_close):
"""
analyse the incresing ratio of a stock
:param d_close:
:return: a num
"""
o_price = d_close.Close[0]
c_price = d_close.Close[-1]
# 跟上述方式效果相同
# o_price = d_close['Close'][0]
# c_price = d_close['Close'][-1]
# 计算数据,通过round方法四舍五入,取小数点后四位数,在换算为百分比
ratio = '%.2f%%' % (round(((c_price - o_price) / o_price), ndigits=4) * 100)

return ratio       

需要注意的是,按照指定索引去读取的数据结构,每一列相当于列表,可通过[-1]的方式轻松找到最后一个数;如果不指定日期为索引,pandas默认会为数据建立相应的索引,值得注意的是并不会对每列数据按照索引进行深加工将其转变为Series,而是ndarray。如此将不能很方便的找到最后一个数据用于计算(如果用的话);因为按csv格式读取是按行读取,如果不事先看数据,不知道最后一行到底是多少。


不指定索引的数据.png

但通过指定索引,如果用plt.plot(data)的方式将不能自动按照日期来成图,而是按照默认索引;如果要用上述方式成图需指定日期列,会发现日期列被覆盖,将索引重新赋给日期字典,还需要对每一行都用apply方法建立关联。所以二者是一对矛盾,还未研究透。如果用别的列来建立索引,仍然不能当做Series来看待,求增长率时将不能用[0]、[-1]的方式轻松找到最后一个数。


Volume为索引的Close数据.png

所以最简便的办法就是指定日期为索引,直接使用指定数据列去绘图的方式来可视化,也就是df['key].plot(自定义设置)(补充:看文档之后,原来这种成图方式是pandas自带的成图模式,可直接用索引成图,并非pyplot中的方式),不再需要指定横坐标——日期;

  d_g['Close'].plot(label="Google" + '^' + str(c_ratio(d_g)))     
最终结果.png

pandas不能直接用文件格式不匹配的方式读取相应文件,会出错,但csv和json可以通过运算方式转换;

最终结果是这样:


可视化结果.png

代码如下:

  # !/usr/bin/env python
  # -*- encoding: utf-8 -*-

  """
  Attempt to make a graph compare with some stocks
  """

  import os
  import pandas as pd
  from pandas_datareader import data
  import matplotlib.pyplot as plt

  # 对应股票名称和对应代码
  dic = {'谷歌': 'GOOG', '亚马逊': 'AMZN', '脸书': 'FB',
          '阿里巴巴': 'BABA', '腾讯': '0700.hk', '苹果': 'AAPL', }

  # Set the date
  start_date = '2017-1-1'
  end_date = '2018-1-1'

  # Attempt to check the files, if it does'n exit,try to get it.
  if (os.path.exists('./google_to.csv') and os.path.exists('./Amazon_to.csv') and      
      os.path.exists('./FB_to.csv') and os.path.exists('./ali_to.csv') and
      os.path.exists('./apple_to.csv') and os.path.exists('./tencent_to.csv')
      ):
      dateparse1 = lambda dates: pd.datetime.strptime(dates, '%Y-%m-%d')      

      d_g = pd.read_csv('./google_to.csv',skiprows=0, index_col='Date',      
                        date_parser=dateparse1, parse_dates=True,
                        )
      d_am = pd.read_csv('./Amazon_to.csv', skiprows=0, index_col='Date',      
                         date_parser=dateparse1, parse_dates=True,
                         )
      d_f = pd.read_csv('./FB_to.csv', skiprows=0, index_col='Date',      
                         date_parser=dateparse1, parse_dates=True,
                        )
      d_a = pd.read_csv('./apple_to.csv', skiprows=0, index_col='Date',      
                        date_parser=dateparse1, parse_dates=True,
                        )
      d_ten = pd.read_csv('./tencent_to.csv', skiprows=0, index_col='Date',      
                          date_parser=dateparse1, parse_dates=True,
                          )
      d_baba = pd.read_csv('./ali_to.csv', skiprows=0, index_col='Date',
                           date_parser=dateparse1, parse_dates=True,
                          )
  else:
      d_g = data.get_data_yahoo(dic['谷歌'], start_date, end_date)
      try:
          with open('./google_to.csv', 'w') as f:
              f.write(d_g.to_csv())
      except IOError:
          print ("Please check your code,dedicate space.")
      else:
          d_g.head()      #文件操作后会释放变量,这一行在执行时并不显示

      d_am = data.get_data_yahoo(dic['亚马逊'], start_date, end_date)
      try:
          with open('./Amazon_to.csv', 'w') as f:
              f.write(d_am.to_csv())
      except IOError:
          print ("Please check your code,dedicate space.")
      else:
          pass

      d_f = data.get_data_yahoo(dic['脸书'], start_date, end_date)
      try:
          with open('./FB_to.csv', 'w') as f:
              f.write(d_f.to_csv())
      except IOError:
          print ("Please check your code,dedicate space.")
      else:
          pass

      d_a = data.get_data_yahoo(dic['苹果'], start_date, end_date)
      try:
          with open('./apple_to.csv', 'w') as f:
              f.write(d_a.to_csv())
      except IOError:
          print ("Please check your code,dedicate space.")
      else:
          pass

      d_ten = data.get_data_yahoo(dic['腾讯'], start_date, end_date)
      try:
          with open('./tencent_to.csv', 'w') as f:
              f.write(d_ten.to_csv())
      except IOError:
          print ("Please check your code,dedicate space.")
      else:
          pass

      d_baba = data.get_data_yahoo(dic['阿里巴巴'], start_date, end_date)
      try:
          with open('./ali_to.csv', 'w') as f:
              f.write(d_baba.to_csv())
      except IOError:
          print ("Please check your code,dedicate space.")
      else:
          pass


  def c_ratio(d_close):
      """
      analyse the incresing ratio of a stock
      :param d_close:
      :return: a num
      """
      o_price = d_close.Close[0]      
      c_price = d_close.Close[-1]      

      # o_price = d_close['Close'][0]      
      # c_price = d_close['Close'][-1]      

      ratio = '%.2f%%' % (round(((c_price - o_price) / o_price), ndigits=4) * 100)      

      return ratio

  # print(c_ratio(d_g))      # 测试代码用
  
 # Set the font to support Chinese
  plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']      
  plt.rcParams['axes.unicode_minus'] = False

  # Let's make grapha
  fig = plt.figure(dpi=128, figsize=(10, 6))
  # d_g['date'] = d_g.index
  # plt.plot(d_g['date'], d_g['Close'], color='r',
  #          label='Google'+ '^' + str(c_ratio(d_g)))
  d_g['Close'].plot(label="Google" + '^' + str(c_ratio(d_g)))
  d_am['Close'].plot(label='Amazon' + '^' + str(c_ratio(d_am)))      
  d_f['Close'].plot(label='Facebook' + '^' + str(c_ratio(d_f)))      
  d_a['Close'].plot(label='Apple' + '^' + str(c_ratio(d_a)))
  d_ten['Close'].plot(label='Tencent' + '^' + str(c_ratio(d_ten)))      
  d_baba['Close'].plot(label='Alibaba' + '^' + str(c_ratio(d_baba)))      

  plt.title('2017GAFATA组合股价年增长趋势', fontsize=20)
  plt.xlabel('日  期', fontsize=16)
  plt.ylabel('收盘价格', fontsize=16)
  plt.tick_params(axis='both', labelsize=12, which='major')
  plt.grid(True)
  plt.legend(loc=2)

  plt.show()
  # plt.savefig('GAFATA.png', bbox='tight')      

编写代码过程中的不足:
1、对pandas还是不熟,需要看文档系统学习,对不同格式数据操作和优劣要有系统认知;
2、对matplotlib还是不熟,图层设置总是想不起该是哪些方法,还需要多练习;
3、文件操作要考虑很多因素,所以需要经常锻炼用try方法来写代码;如果有比较有效的内建函数可以判断,就直接用函数;
4、对python的错误类型了解不深入,还需加强;
5、利用单个股票数据首先验证想法,再去实现全部会是个不错的选择;
6、为实现某一功能的代码块编写代码注释是需要养成的习惯;
7、因为有时候偶要用python2,见C12-5,重写了一份matplotlibrc文件内容是TkAGG模式,python3中不太支持plot,移动图层会出现编码错误的警告,所以还是需要删除该文件,使用3默认的API。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342