年化收益率拟合函数

     所谓“拟合”,指的是在已有一组实验数据的前提下,研究这组数据有怎样的函数关系——最终结果是从这一组看似漫无规律的数据点中“找出”能用数学表达式表示的规律。

     一个典型的数据拟合过程包括以下几个步骤:

1、有一组实验/实测数据;

2、根据数据,猜测其有怎样的发展规律(例如总趋势是指数增长还是对数下降?),并写出一个含有待定系数的数学表达式;

3、利用函数算出待定系数的数值,即得到拟合的规律

根据给定数据集的对应关系可以推出较为相近的拟合函数,对拟合函数y,给出一系列x值:0, 1,2, 3....,输出各自的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.25,0.26、0.28来进行计算。

实际值与函数的拟合程度:

 

给定的数据集如下:

 

以Term为时间x和Yield为年化收益率y对数据集来进行拟合,当最大年化收益率c为25%时,经计算后得到y=-exp(-0.4593 * x - 1.588) + 0.25;当c为28%时,经计算后得到y=-exp(-0.1907 * x - 1.8)+0.28%

导入我们需要的库:

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')
df = pd.read_excel(filePath)
# print(df)
#获取x、y值
data = xlrd.open_workbook(filePath)
Data_sheet = data.sheets()[0]
x = Data_sheet.col_values(0)
y = Data_sheet.col_values(1)
del x[0]
del y[0]
# print(x)
# print(y)

#计算出参数a和b的值
c = 0.25
N = [c-i for i in y]
# print ( N)
Y = []#把e为底的指数函数转化成一次函数
for i in N:
    Y.append(math.log(i,math.e))
a_b = np.polyfit(x, Y, 1)
exp = np.poly1d(a_b)
print (a_b )#[-0.45925528 -1.58806035]
print (exp)#-0.4593 x - 1.588
a=a_b.tolist()[0]
b=a_b.tolist()[1]
print(a)
print(b)

#绘图看数据集与拟合函数的拟合程度
Y1=[]
Y2=[]
Y3=[]

for i in x:
    sy1=-math.exp(-0.4593 * i - 1.588) + 0.25#当C取0.25的函数
    sy2 = -math.exp(-0.1907*i - 1.8)+0.28#当C取0.28的函数
    sy3 = -math.exp(-0.2848 * i - 1.84) + 0.26#当C取0.3的函数

    Y1.append(sy1)
    Y2.append(sy2)
    Y3.append(sy3)

# print(Y1)
plt.plot(x,y,'o')#原始数据集
plt.plot(x,Y1,'y',label=' y1=-exp(-0.4593 * x - 1.588) + 0.25',color='y', linewidth=2)#拟合函数计算出的数据集
plt.plot(x,Y2,'y',label='y2=-exp(-0.1907 * x - 1.8)+0.28',color='g', linewidth=2)
plt.plot(x,Y3,'y',label='y3= -exp(-0.2848 * x - 1.84) + 0.26',color='r', linewidth=2)

plt.legend(loc='lower right')
plt.grid(True)
plt.show()

 #拟合函数取数据集
def f(exp):
    return -np.exp(exp)+ c
x= np.arange(0,10.5,1)
exp=exp(x)
# print(x)
# print(f(exp))
error = f(exp)-y
print(abs(error))

#求SSE误差平方和
SSE = np.sum(error**2)
print(SSE)

# 输出表格
df = pd.DataFrame({'Parameter':['a','b','SSE'],"Value":[a,b,SSE]})
df.to_excel(OutputPath,sheet_name='OutPut')

print(df)

 

项目中有涉及趋势预测的工作,整理了以下几种拟合方法:

线性拟合使用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}

 

 

 

转载于:https://www.cnblogs.com/Estate-47/p/10408138.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值