WHCSRL 技术网

python可视化小程序-实际利率与黄金价格走势图

目录

一、黄金价格与美元实际利率

二、最终结果

三、代码

1.import

2.代码

2.1 Tkinter 经典写法

2.2 creatWidget()函数与控件事件绑定

2.3 generateImage()函数:pands+matplotlib

四、完整代码

一、黄金价格与美元实际利率

        在《黄金价格与实际利率的关系》的文章中,作者指出,“实际利率是唯一与黄金价格相关的指标”,但并不是直线相关。只有实际利率转为负的时候,黄金价格才会大幅上涨。

        而实际利率、名义利率与通货膨胀率有该关系:实际利率=名义利率-通货膨胀率

        通货膨胀率使用美国十年年平准通胀率10-Year Breakeven Inflation Rate (T10YIE):10-Year Breakeven Inflation Rate | FRED | St. Louis Fed

        名义利率使用美国十年期国债收益率 Market Yield on U.S. Treasury Securities at 10-Year Constant Maturity (DGS10):https://fred.stlouisfed.org/series/DGS10

        黄金价格使用MT4软件的XAUUSD日线数据

        所需文件已上传至博客资源中(正在审核):https://download.csdn.net/download/zsllsz2022/35932952

二、最终结果

         选择DGS10、T10YIE、Xau文件后,并设置保存位置,然后点击生成图片,会在左侧显示示意图,并在指定文件夹内生成PNG格式的图片。

三、代码

1.import

  1. from tkinter import *
  2. from tkinter import messagebox
  3. from tkinter.filedialog import *
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. import pandas as pd
  7. import matplotlib.ticker as ticker
  8. import mpl_toolkits.axisartist as AA
  9. from mpl_toolkits.axisartist.axislines import SubplotZero
  10. import pylab
  11. pylab.mpl.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
  12. plt.rcParams['axes.unicode_minus']=False #用于解决不能显示负号的问题

2.代码

2.1 Tkinter 经典写法

  1. from tkinter import *
  2. from tkinter import messagebox
  3. from tkinter.filedialog import *
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. import pandas as pd
  7. import matplotlib.ticker as ticker
  8. import mpl_toolkits.axisartist as AA
  9. from mpl_toolkits.axisartist.axislines import SubplotZero
  10. import pylab
  11. pylab.mpl.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
  12. plt.rcParams['axes.unicode_minus']=False #用于解决不能显示负号的问题
  13. class Application(Frame):
  14. def __init__(self,master=None):
  15. super().__init__(master)
  16. self.master = master
  17. self.pack() #使用pack布局管理器
  18. self.config(width=1100, height=500) #加入控件后修改此参数即可知道含义
  19. self.creatWidget()
  20. #用于控制按钮使用顺序,若某个Flag为0,表示该Button操作未完成
  21. self.selectFileDGS10Flag = 0
  22. self.selectFileT10YIEFlag = 0
  23. self.selectFileXauFlag = 0
  24. self.SavePathFlag = 0
  25. def creatWidget(self):
  26. pass
  27. if __name__ == '__main__':
  28. root = Tk()
  29. root.title("实际利率与黄金价格走势图") #窗口名称
  30. root.geometry("1100x500+200+50") #主窗口位置与大小/此处含义为宽度1100,高度500,+200表示距左边屏幕距离,+50表示距离上边屏幕距离
  31. root.resizable(0,0) #不可伸缩大小,个人习惯使用固定窗口大小,然后使用pack布局设置好绝对位置
  32. app = Application(master=root)
  33. root.mainloop() #进入事件循环

2.2 creatWidget()函数与控件事件绑定

  1. def creatWidget(self):
  2. #text,command,bg参数与place方法里的x,y参数,见效果图即可
  3. #或者手动修改后查看异同
  4. #控件-图片示意图
  5. self.imageShow = Text(self,width=130,height=35)
  6. self.imageShow.place(x=15,y=25)
  7. #控件-上传文件按钮
  8. btnSelectFileDGS10 = Button(self,text="选择DGS10文件",command=self.selectFileDGS10,bg="blue")
  9. btnSelectFileDGS10.place(x=950,y=30)
  10. btnSelectFileT10YIE = Button(self, text="选择T10YIE文件", command=self.selectFileT10YIE, bg="blue")
  11. btnSelectFileT10YIE.place(x=950, y=80)
  12. btnSelectFileXau = Button(self, text="选择Xau文件", command=self.selectFileXau, bg="blue")
  13. btnSelectFileXau.place(x=959, y=130)
  14. #控件-设置存储位置按钮
  15. btnSavePath = Button(self, text="设置保存位置", command=self.SavePath, bg="green")
  16. btnSavePath.place(x=959, y=180)
  17. #控件-生成图片按钮
  18. btn = Button(self,text="生成图片", command=self.generateImage, bg="green")
  19. btn.place(x=969, y=230)
  20. def generateImage(self):
  21. #若未完成上传文件,则弹出Error窗口
  22. #此处只有当三个Flag均为1时,才可以继续往下执行
  23. if(self.selectFileDGS10Flag == 0 or self.selectFileT10YIEFlag == 0 or self.selectFileXauFlag == 0):
  24. messagebox.showinfo("Error","请先上传文件")
  25. return
  26. #若未设置图片存储路径,则弹出Error窗口
  27. if(self.SavePathFlag == 0):
  28. messagebox.showinfo("Error","请先设置保存路径")
  29. return
  30. #其余功能见下文
  31. pass
  32. #使用askopenfilename获取文件绝对路径
  33. #使用askdirectory获取文件夹绝对路径
  34. #当成功完成读取操作后将Flag设置为1
  35. def selectFileDGS10(self):
  36. self.pathDGS10 = askopenfilename(title="上传文件")
  37. if len(self.pathDGS10) != 0:
  38. self.selectFileDGS10Flag = 1
  39. def selectFileT10YIE(self):
  40. self.pathT10YIE = askopenfilename(title="上传文件")
  41. if len(self.pathT10YIE) != 0:
  42. self.selectFileT10YIEFlag = 1
  43. def selectFileXau(self):
  44. self.pathXau = askopenfilename(title="上传文件")
  45. if len(self.pathXau) != 0:
  46. self.selectFileXauFlag = 1
  47. def SavePath(self):
  48. self.SavePath = askdirectory(title="设置存储位置")
  49. if len(self.SavePath) != 0:
  50. self.SavePathFlag = 1

2.3 generateImage()函数:pands+matplotlib

  1. def generateImage(self):
  2. #若未完成上传文件,则弹出Error窗口
  3. #此处只有当三个Flag均为1时,才可以继续往下执行
  4. if(self.selectFileDGS10Flag == 0 or self.selectFileT10YIEFlag == 0 or self.selectFileXauFlag == 0):
  5. messagebox.showinfo("Error","请先上传文件")
  6. return
  7. #若未设置图片存储路径,则弹出Error窗口
  8. if(self.SavePathFlag == 0):
  9. messagebox.showinfo("Error","请先设置保存路径")
  10. return
  11. #pd.read_csv读取文件,文件路径即为askdirectory函数读取结果
  12. #数据从2019年7月19日开始切片,前提使用parse_dates=True将时间解析为时间对象
  13. #na_values将特定字符串识别成Nan
  14. #index_col设置df索引
  15. self.dfDGS10 = pd.read_csv(self.pathDGS10, index_col="DATE", parse_dates=True, na_values=["."])["2019-7-19":]
  16. self.dfT10YIE = pd.read_csv(self.pathT10YIE, index_col="DATE", parse_dates=True, na_values=["."])["2019-7-19":]
  17. self.srAu = pd.read_csv(self.pathXau, header=None, names=["DATE", "open", "high", "low", "close", "v"],
  18. parse_dates=True)["close"]["2019-7-19":]
  19. #重新构造一个DataFrame
  20. #realRate为真实利率,即名义利率-通货膨胀率
  21. self.realRate = pd.DataFrame({"realRate": (self.dfDGS10["DGS10"] - self.dfT10YIE["T10YIE"]), "DGS10": self.dfDGS10["DGS10"],
  22. "T10YIE": self.dfT10YIE["T10YIE"], "au": self.srAu})
  23. #dropna-how:筛选方式-‘any’,表示该行/列只要有一个以上的空值,就删除该行/列;‘all’,表示该行/列全部都为空值,就删除该行/列。
  24. realRate = self.realRate.dropna(how="any")
  25. fig, ax = plt.subplots(figsize=(100, 50))
  26. plt.title("实际利率与黄金价格走势图", fontsize=140)
  27. #设置右边的坐标轴
  28. ax2 = ax.twinx()
  29. ax2.tick_params(labelsize=100) #设置刻度大小
  30. ax2.yaxis.set_major_locator(ticker.MultipleLocator(50))#设置黄金价格刻度间隔
  31. ax2.set_ylabel("黄金价格/$",size=120)#设置label名称与大小
  32. #设置坐标轴
  33. ax.tick_params(labelsize=100)
  34. ax.xaxis.set_major_locator(ticker.MultipleLocator(100))
  35. ax.set_ylabel("利率/%%",size=120)
  36. #画图-各参数具体含义参照效果图即可
  37. ax.plot(realRate.index, realRate["DGS10"], "-.g", label="美国十年期国债收益率/%%", linewidth=10)
  38. ax.plot(realRate.index, realRate["T10YIE"], "-.b", label="10-Year Breakeven Inflation Rate/%%", linewidth=10)
  39. ax.plot(realRate.index, realRate["realRate"], "-.r", label="实际利率/%%", linewidth=20)
  40. #使用ax的label代替ax2的label,或可将ax2的legend加入到ax的legend中
  41. ax.plot([], [], "-.y", label="黄金价格/$", linewidth=20)
  42. ax2.plot(realRate.index, realRate["au"], "-.y", label="黄金价格", linewidth=20)
  43. #legeng大小与位置,upper left即为左上角
  44. ax.legend(fontsize=100,loc="upper left")
  45. #栅格grid
  46. ax.grid(linestyle=":", color="b", linewidth=5)
  47. self.imagePathPng = self.SavePath + "/result.png"
  48. plt.savefig(self.imagePathPng,dpi=10,bbox_inches='tight')
  49. #将保存到指定路径的图片重新读取并插入到Text控件中
  50. self.photo = PhotoImage(file=self.imagePathPng)
  51. self.imageShow.image_create(1.0,image=self.photo)

四、完整代码

  1. from tkinter import *
  2. from tkinter import messagebox
  3. from tkinter.filedialog import *
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. import pandas as pd
  7. import matplotlib.ticker as ticker
  8. import mpl_toolkits.axisartist as AA
  9. from mpl_toolkits.axisartist.axislines import SubplotZero
  10. import pylab
  11. pylab.mpl.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
  12. plt.rcParams['axes.unicode_minus']=False #用于解决不能显示负号的问题
  13. class Application(Frame):
  14. def __init__(self,master=None):
  15. super().__init__(master)
  16. self.master = master
  17. self.pack() #使用pack布局管理器
  18. self.config(width=1100, height=500) #加入控件后修改此参数即可知道含义
  19. self.creatWidget()
  20. #用于控制按钮使用顺序,若某个Flag为0,表示该Button操作未完成
  21. self.selectFileDGS10Flag = 0
  22. self.selectFileT10YIEFlag = 0
  23. self.selectFileXauFlag = 0
  24. self.SavePathFlag = 0
  25. def creatWidget(self):
  26. #text,command,bg参数与place方法里的x,y参数,见效果图即可
  27. #或者手动修改后查看异同
  28. #控件-图片示意图
  29. self.imageShow = Text(self,width=130,height=35)
  30. self.imageShow.place(x=15,y=25)
  31. #控件-上传文件按钮
  32. btnSelectFileDGS10 = Button(self,text="选择DGS10文件",command=self.selectFileDGS10,bg="blue")
  33. btnSelectFileDGS10.place(x=950,y=30)
  34. btnSelectFileT10YIE = Button(self, text="选择T10YIE文件", command=self.selectFileT10YIE, bg="blue")
  35. btnSelectFileT10YIE.place(x=950, y=80)
  36. btnSelectFileXau = Button(self, text="选择Xau文件", command=self.selectFileXau, bg="blue")
  37. btnSelectFileXau.place(x=959, y=130)
  38. #控件-设置存储位置按钮
  39. btnSavePath = Button(self, text="设置保存位置", command=self.SavePath, bg="green")
  40. btnSavePath.place(x=959, y=180)
  41. #控件-生成图片按钮
  42. btn = Button(self,text="生成图片", command=self.generateImage, bg="green")
  43. btn.place(x=969, y=230)
  44. def generateImage(self):
  45. #若未完成上传文件,则弹出Error窗口
  46. #此处只有当三个Flag均为1时,才可以继续往下执行
  47. if(self.selectFileDGS10Flag == 0 or self.selectFileT10YIEFlag == 0 or self.selectFileXauFlag == 0):
  48. messagebox.showinfo("Error","请先上传文件")
  49. return
  50. #若未设置图片存储路径,则弹出Error窗口
  51. if(self.SavePathFlag == 0):
  52. messagebox.showinfo("Error","请先设置保存路径")
  53. return
  54. #pd.read_csv读取文件,文件路径即为askdirectory函数读取结果
  55. #数据从2019年7月19日开始切片,前提使用parse_dates=True将时间解析为时间对象
  56. #na_values将特定字符串识别成Nan
  57. #index_col设置df索引
  58. self.dfDGS10 = pd.read_csv(self.pathDGS10, index_col="DATE", parse_dates=True, na_values=["."])["2019-7-19":]
  59. self.dfT10YIE = pd.read_csv(self.pathT10YIE, index_col="DATE", parse_dates=True, na_values=["."])["2019-7-19":]
  60. self.srAu = pd.read_csv(self.pathXau, header=None, names=["DATE", "open", "high", "low", "close", "v"],
  61. parse_dates=True)["close"]["2019-7-19":]
  62. #重新构造一个DataFrame
  63. #realRate为真实利率,即名义利率-通货膨胀率
  64. self.realRate = pd.DataFrame({"realRate": (self.dfDGS10["DGS10"] - self.dfT10YIE["T10YIE"]), "DGS10": self.dfDGS10["DGS10"],
  65. "T10YIE": self.dfT10YIE["T10YIE"], "au": self.srAu})
  66. #dropna-how:筛选方式-‘any’,表示该行/列只要有一个以上的空值,就删除该行/列;‘all’,表示该行/列全部都为空值,就删除该行/列。
  67. realRate = self.realRate.dropna(how="any")
  68. fig, ax = plt.subplots(figsize=(100, 50))
  69. plt.title("实际利率与黄金价格走势图", fontsize=140)
  70. #设置右边的坐标轴
  71. ax2 = ax.twinx()
  72. ax2.tick_params(labelsize=100) #设置刻度大小
  73. ax2.yaxis.set_major_locator(ticker.MultipleLocator(50))#设置黄金价格刻度间隔
  74. ax2.set_ylabel("黄金价格/$",size=120)#设置label名称与大小
  75. #设置坐标轴
  76. ax.tick_params(labelsize=100)
  77. ax.xaxis.set_major_locator(ticker.MultipleLocator(100))
  78. ax.set_ylabel("利率/%%",size=120)
  79. #画图-各参数具体含义参照效果图即可
  80. ax.plot(realRate.index, realRate["DGS10"], "-.g", label="美国十年期国债收益率/%%", linewidth=10)
  81. ax.plot(realRate.index, realRate["T10YIE"], "-.b", label="10-Year Breakeven Inflation Rate/%%", linewidth=10)
  82. ax.plot(realRate.index, realRate["realRate"], "-.r", label="实际利率/%%", linewidth=20)
  83. #使用ax的label代替ax2的label,或可将ax2的legend加入到ax的legend中
  84. ax.plot([], [], "-.y", label="黄金价格/$", linewidth=20)
  85. ax2.plot(realRate.index, realRate["au"], "-.y", label="黄金价格", linewidth=20)
  86. #legeng大小与位置,upper left即为左上角
  87. ax.legend(fontsize=100,loc="upper left")
  88. #栅格grid
  89. ax.grid(linestyle=":", color="b", linewidth=5)
  90. self.imagePathPng = self.SavePath + "/result.png"
  91. plt.savefig(self.imagePathPng,dpi=10,bbox_inches='tight')
  92. #将保存到指定路径的图片重新读取并插入到Text控件中
  93. self.photo = PhotoImage(file=self.imagePathPng)
  94. self.imageShow.image_create(1.0,image=self.photo)
  95. #使用askopenfilename获取文件绝对路径
  96. #使用askdirectory获取文件夹绝对路径
  97. #当成功完成读取操作后将Flag设置为1
  98. def selectFileDGS10(self):
  99. self.pathDGS10 = askopenfilename(title="上传文件")
  100. if len(self.pathDGS10) != 0:
  101. self.selectFileDGS10Flag = 1
  102. def selectFileT10YIE(self):
  103. self.pathT10YIE = askopenfilename(title="上传文件")
  104. if len(self.pathT10YIE) != 0:
  105. self.selectFileT10YIEFlag = 1
  106. def selectFileXau(self):
  107. self.pathXau = askopenfilename(title="上传文件")
  108. if len(self.pathXau) != 0:
  109. self.selectFileXauFlag = 1
  110. def SavePath(self):
  111. self.SavePath = askdirectory(title="设置存储位置")
  112. if len(self.SavePath) != 0:
  113. self.SavePathFlag = 1
  114. if __name__ == '__main__':
  115. root = Tk()
  116. root.title("实际利率与黄金价格走势图") #窗口名称
  117. root.geometry("1100x500+200+50") #主窗口位置与大小/此处含义为宽度1100,高度500,+200表示距左边屏幕距离,+50表示距离上边屏幕距离
  118. root.resizable(0,0) #不可伸缩大小,个人习惯使用固定窗口大小,然后使用pack布局设置好绝对位置
  119. app = Application(master=root)
  120. root.mainloop() #进入事件循环

推荐阅读