年化收益率拟合函数
作者:互联网
所谓“拟合”,指的是在已有一组实验数据的前提下,研究这组数据有怎样的函数关系——最终结果是从这一组看似漫无规律的数据点中“找出”能用数学表达式表示的规律。
一个典型的数据拟合过程包括以下几个步骤:
1、有一组实验/实测数据;
2、根据数据,猜测其有怎样的发展规律(例如总趋势是指数增长还是对数下降?),并写出一个含有待定系数的数学表达式;
3、利用函数算出待定系数的数值,即得到拟合的规律
根据给定数据集的对应关系可以推出较为相近的拟合函数,对拟合函数y,给出一系列x值:0, 0.25, 0.5, 0.75, ....,输出各自的y值来预测年化收益率。
首先我们可以先分析出年化收益率是一个类似于y=-exp(ax+b)+c的指数函数,a<0、c为最大年化收益率是一个常数。如果有一堆数据集已知x、y和c的值我们就可以预测出a和b的值了。定义一个参数M,使M=ax+b转化为一元回归;定义一个参数N,使exp(M)=c-y=N,根据数据集可以求出c-y的值N。M=ax+b=lnN 根据数据集的值求出a和b,假定常数c为0.15或0.2来进行计算。
实际值与函数的拟合程度:
给定的数据集如下:
以Term为时间x和Yield为年化收益率y对数据集来进行拟合,当最大年化收益率c为15%时,经计算后得到y=-exp(-0.05903 x - 3.193)+15%;当c为20%时,经计算后得到y=-exp(-0.02488 x - 2.397)+20%
导入我们需要的库:
import pandas as pd import matplotlib.pyplot as plt import numpy as np import math import sys#实现从程序外部向程序传递参数。 import xlrd import os
读取表中的数据集并进行计算:
# InputPath=sys.argv[1]#输入路径 # OutputPath=sys.argv[2]#输出路径 # filePath = InputPath#处理的文件为在输入路径中读取的文件 filePath = os.path.join(os.getcwd(),'input.xlsx') # print(filePath) df = pd.read_excel(filePath) data = xlrd.open_workbook(filePath) Data_sheet = data.sheets()[0] x = Data_sheet.col_values(1) y = Data_sheet.col_values(2) del x[0] del y[0] print(x) print(y)
c = 0.15
N = [c-i for i in y]
N_new = []
for i in N:
N_new.append(math.log(i,math.e))
a_b = np.polyfit(x, N_new, 1)
exp = np.poly1d(a_b)
print (a_b )#[-0.05903062 -3.19302381]
print (exp )#-0.05903 x - 3.193
最终输出a和b的值,a=-0.05903 、b=- 3.193,y=-exp(-0.05903 x - 3.193)+15%,每半年计息,预测出了未来10年内的年化收益率:
项目中有涉及趋势预测的工作,整理了以下几种拟合方法:
线性拟合使用math:
import math def linefit(x , y): N = float(len(x)) sx,sy,sxx,syy,sxy=0,0,0,0,0 for i in range(0,int(N)): sx += x[i] sy += y[i] sxx += x[i]*x[i] syy += y[i]*y[i] sxy += x[i]*y[i] a = (sy*sx/N -sxy)/( sx*sx/N -sxx) #点斜式:y-y0=a(x-x0) (x0,y0)是直线通过已知点的坐标 b = (sy - a*sx)/N #b = y-ax r = abs(sy*sx/N-sxy)/math.sqrt((sxx-sx*sx/N)*(syy-sy*sy/N))#r为次方 return a,b,r if __name__ == '__main__': X=[ 1 ,2 ,3 ,4 ,5 ,6] Y=[ 2.5 ,3.51 ,4.45 ,5.52 ,6.47 ,7.51] a,b,r=linefit(X,Y) print("X=",X) print("Y=",Y) print("拟合结果: y = %10.5f x + %10.5f , r=%10.5f" % (a,b,r) )#%10.5f占位宽度10,保留5位小数的浮点数
线性拟合使用numpy:
import numpy as np X=[ 1 ,2 ,3 ,4 ,5 ,6] Y=[ 2.5 ,3.51 ,4.45 ,5.52 ,6.47 ,7.51] z1 = np.polyfit(X, Y, 1) #一次多项式拟合,相当于线性拟合 p1 = np.poly1d(z1) print (z1 ) #[ 1. 1.49333333] print (p1 ) # 1 x + 1.493
二次多项式拟合:
import numpy def polyfit(x, y, degree): results = {} coeffs = numpy.polyfit(x, y, degree) results['polynomial'] = coeffs.tolist() # r-squared p = numpy.poly1d(coeffs) # fit values, and mean yhat = p(x) # or [p(z) for z in x] ybar = numpy.sum(y)/len(y) # or sum(y)/len(y) ssreg = numpy.sum((yhat-ybar)**2) # or sum([ (yihat - ybar)**2 for yihat in yhat]) sstot = numpy.sum((y - ybar)**2) # or sum([ (yi - ybar)**2 for yi in y]) results['determination'] = ssreg / sstot #准确率 return results x=[ 1 ,2 ,3 ,4 ,5 ,6] y=[ 2.5 ,3.51 ,4.45 ,5.52 ,6.47 ,7.2] z1 = polyfit(x, y, 2)#z1为返回的多项式向量,从最高次幂到最低次幂的系数,x为准备拟合的自变量,y为应变量,2为拟合的次数 print (z1)
对数函数拟合:
from scipy import log #as log print pcov import numpy from scipy import log from scipy.optimize import curve_fit def func(x, a, b): y = a * log(x) + b return y def polyfit(x, y, degree): results = {} #coeffs = numpy.polyfit(x, y, degree) popt, pcov = curve_fit(func, x, y) results['polynomial'] = popt # r-squared yhat = func(x ,popt[0] ,popt[1] ) # or [p(z) for z in x] ybar = numpy.sum(y)/len(y) # or sum(y)/len(y) ssreg = numpy.sum((yhat-ybar)**2) # or sum([ (yihat - ybar)**2 for yihat in yhat]) sstot = numpy.sum((y - ybar)**2) # or sum([ (yi - ybar)**2 for yi in y]) results['determination'] = ssreg / sstot return results x=[ 1 ,2 ,3 ,4 ,5 ,6] y=[ 2.5 ,3.51 ,4.45 ,5.52 ,6.47 ,7.51] z1 = polyfit(x, y, 2) print (z1)#{'polynomial': array([2.72873961, 2.00115611]), 'determination': 0.9339494757910027}
标签:函数,年化,sum,ybar,拟合,print,import,numpy 来源: https://www.cnblogs.com/Estate-47/p/10408138.html