Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nelson-Siegel and Svensson Bond curve fitting #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions NS SS bond curve.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
"""
Created on Mon Nov 12 10:12:45 2018

@author: Shinhyunjin
"""

"""
Topic: Nelson-Siegel Curve Smoothing Technique
Sources: Generating a Yield Curve with Nelson-Seigel Method in Excel -> https://www.youtube.com/watch?v=GsZRJmDcDbY
Data fitting using fmin -> http://glowingpython.blogspot.it/2011/05/curve-fitting-using-fmin.html

Comment: Refer to the above video for an explanation of the method. Also see https://github.com/MaximumBeings/public/blob/master/NSSandNS.txt
for an MS Excel version of the NSS and NS method. Though the code works very
well, we noticed that the Excel version fitted our original data better because the solver in Excel is pretty powerful. Nonetheless,
this is a very good implementation of the NSS method. We try to fit the curve by minimizing the sum of squared errors using the
NS formula. It is an iterative method that tries to guess the values for the NS parameters so you need to try different initial
values. Feed the program with a set of initial values and observe the curve plot and change the parameters to get better fits. A good
starting set of initial values is array([0.01,0.01,0.01,1.00]) but can be changed to get a better fit.
"""



import pylab
from numpy import *
from scipy.optimize import fmin
import pandas as pd
import os
import numpy as np
import matplotlib.pyplot as plt


### Nelson - Siegel ###

pre1 = os.path.dirname(os.path.realpath('C:/Users/Shinhyunjin/Dropbox/hw1data.xlsx'))
fname1 = 'hw1data.xlsx'
path1 = os.path.join(pre1, fname1)
df1 = pd.read_excel(path1)
data = pd.DataFrame(df1)


#print ""
# parametric function, x is the independent variable
# and c are the parameters.
# it's a polynomial of degree 2
fp = lambda c, x: c[0]+(c[1]+c[2])*(c[3]/x)*(1-exp(-x/c[3])-c[2]*exp(-x/c[3]))

# error function to minimize
e = lambda p, x, y: ((fp(p,x)-y)**2).sum()


# generating data with noise

y = np.array(data['YTM']/100) #The periods for which data are available, skip the periods with empty rate
x = np.array(data['TAU']) #Available rates only

# fitting the data with fmin
p0 = array([0.01,0.01,0.01,1.00]) # initial parameter value
p = fmin(e, p0, args=(x,y))
c = p
j=[]

for h in x:
j.append(c[0]+(c[1]+c[2])*(c[3]/h)*(1-exp(-h/c[3])-c[2]*exp(-h/c[3])))


#print ""
print ('Initial Parameters: ', p0)
print ('Estimated Parameters: ', p)



#To display interpolated data.
h = x
rateTable = pd.DataFrame.from_items([('Period', h),('NS', j)])
print(rateTable.to_string())

#xx =
pylab.plot(x,y, 'b')
pylab.plot(x, fp(p,x), 'ro')
pylab.title('Nelson-Siegel')
pylab.show()



#### Svensson ####

# parametric function, x is the independent variable
# and c are the parameters.
# it's a polynomial of degree 2
fp2 = lambda c2, x: (c2[0])+ (c2[1]*((1- exp(-x/c2[4]))/(x/c2[4])))+ (c2[2]*((((1-exp(-x/c2[4]))/(x/c2[4])))- (exp(-x/c2[4]))))+ (c2[3]*((((1-exp(-x/c2[5]))/(x/c2[5])))- (exp(-x/c2[5]))))
real_p = array([0.02,0.01,0.01,0.01,1.00,1.00])

# error function to minimize
e2 = lambda p2, x, y: ((fp2(p2,x)-y)**2).sum()

# generating data with noise

# fitting the data with fmin
p02 = array([0.01,0.01,0.01,0.01,0.01,1.00,1.00]) # initial parameter value
p2 = fmin(e2, p02, args=(x,y))
c2 = p2
j2=[]
for h2 in x:
j2.append((c2[0])+ (c2[1]*((1- exp(-h2/c2[4]))/(h2/c2[4])))+ (c2[2]*((((1-exp(-h2/c2[4]))/(h2/c2[4])))- (exp(-h2/c2[4]))))+ (c2[3]*((((1-exp(-h2/c2[5]))/(h2/c2[5])))- (exp(-h2/c2[5])))))

print ('Initial Parameters: ', p02)

print ('Estimated Parameters: ', p2)


#To display interpolated data.

h2 = x
rateTable = pd.DataFrame.from_items([('Period', h2),('NSS', j2)])
print(rateTable.to_string())


#xx = array([1,2,5,10,25,30])
plt.title('Result')
plt.grid(True)
plt.plot(x, y, 'g')
plt.plot(x, fp2(p2,x), '--', label = 'SS')
plt.plot(x, fp2(p2,x), 'bo')
plt.plot(x, fp(p,x), 'ro')
plt.plot(x, fp(p,x), ':', label = 'NS')
plt.legend(loc=0)
plt.xlabel('Mat')
plt.ylabel('YTM')

plt.show()

244 changes: 244 additions & 0 deletions sswtioil.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
date,close,volume
2018-11-09,21860,38677
2018-11-08,22235,13358
2018-11-07,22240,7751
2018-11-06,22625,26615
2018-11-05,22615,10842
2018-11-02,22950,12808
2018-11-01,23370,6178
2018-10-31,23895,10443
2018-10-30,24180,7659
2018-10-29,24235,5681
2018-10-26,23985,8381
2018-10-25,23915,3319
2018-10-24,23985,30060
2018-10-23,24875,2859
2018-10-22,25055,3311
2018-10-19,24840,6769
2018-10-18,25115,7725
2018-10-17,25920,3739
2018-10-16,25725,9848
2018-10-15,25820,2893
2018-10-12,25790,6459
2018-10-11,25915,8100
2018-10-10,26880,4190
2018-10-08,26560,19906
2018-10-05,26910,5151
2018-10-04,27395,25589
2018-10-02,27260,28117
2018-10-01,26430,13509
2018-09-28,25975,2115
2018-09-27,26030,38746
2018-09-21,25320,1977
2018-09-20,25605,19900
2018-09-19,25055,5205
2018-09-18,24625,2965
2018-09-17,24740,2189
2018-09-14,24650,3961
2018-09-13,25065,14313
2018-09-12,25040,9086
2018-09-11,24265,1571
2018-09-10,24495,1035
2018-09-07,24390,1391
2018-09-06,24600,3038
2018-09-05,24785,3732
2018-09-04,25215,2212
2018-09-03,25005,2401
2018-08-31,25180,13915
2018-08-30,25005,42834
2018-08-29,24575,61957
2018-08-28,24630,4604
2018-08-27,24585,17955
2018-08-24,24530,12493
2018-08-23,24350,14580
2018-08-22,23720,4000
2018-08-21,23555,9907
2018-08-20,23375,543
2018-08-17,23275,5454
2018-08-16,23165,35758
2018-08-14,24000,9871
2018-08-13,24035,27421
2018-08-10,23625,16041
2018-08-09,23815,24546
2018-08-08,24565,2391
2018-08-07,24590,1668
2018-08-06,24390,26440
2018-08-03,24490,2027
2018-08-02,24095,4039
2018-08-01,24280,5034
2018-07-31,24760,26428
2018-07-30,24520,1124
2018-07-27,24665,1766
2018-07-26,24645,2762
2018-07-25,24430,6838
2018-07-24,24070,23609
2018-07-23,24190,2353
2018-07-20,24270,15085
2018-07-19,24020,4506
2018-07-18,23735,23613
2018-07-17,23785,5200
2018-07-16,24615,4096
2018-07-13,24650,6027
2018-07-12,24735,10228
2018-07-11,25600,9351
2018-07-10,25795,2815
2018-07-09,25760,2351
2018-07-06,25475,5964
2018-07-05,25680,8114
2018-07-04,25960,19263
2018-07-03,26035,5424
2018-07-02,25525,27808
2018-06-29,25505,19344
2018-06-28,25235,6776
2018-06-27,24595,14079
2018-06-26,23765,7281
2018-06-25,23775,9001
2018-06-22,23050,1696
2018-06-21,22755,1670
2018-06-20,22830,2120
2018-06-19,22660,2353
2018-06-18,22305,6302
2018-06-15,23220,1451
2018-06-14,23090,682
2018-06-12,23010,621
2018-06-11,22795,1134
2018-06-08,22840,7277
2018-06-07,22595,3759
2018-06-05,22565,3629
2018-06-04,22820,1678
2018-06-01,23250,2010
2018-05-31,23645,3313
2018-05-30,23130,1806
2018-05-29,23120,3887
2018-05-28,23100,8572
2018-05-25,24470,3888
2018-05-24,24855,2566
2018-05-23,25005,6238
2018-05-21,24950,11257
2018-05-18,24895,11549
2018-05-17,24870,5268
2018-05-16,24690,5601
2018-05-15,24565,6343
2018-05-14,24435,6537
2018-05-11,24720,8108
2018-05-10,24885,8937
2018-05-09,24345,7149
2018-05-08,24285,6686
2018-05-04,23720,962
2018-05-03,23485,2803
2018-05-02,23435,2796
2018-04-30,23535,1647
2018-04-27,23565,1430
2018-04-26,23670,2115
2018-04-25,23480,5683
2018-04-24,24000,2118
2018-04-23,23660,1547
2018-04-20,23660,4875
2018-04-19,23830,2664
2018-04-18,23275,1393
2018-04-17,23080,2418
2018-04-16,23145,3024
2018-04-13,23160,6079
2018-04-12,23180,11824
2018-04-11,22570,33607
2018-04-10,22215,3054
2018-04-09,21600,15288
2018-04-06,21850,355
2018-04-05,22035,522
2018-04-04,21880,27127
2018-04-03,21850,3569
2018-04-02,22575,703
2018-03-30,22390,497
2018-03-29,22375,2782
2018-03-28,22360,1300
2018-03-27,22720,7760
2018-03-26,22675,845
2018-03-23,22520,1114
2018-03-22,22525,16781
2018-03-21,21960,5399
2018-03-20,21635,1099
2018-03-19,21445,11645
2018-03-16,21180,1390
2018-03-15,21095,3923
2018-03-14,21010,3437
2018-03-13,21220,937
2018-03-12,21375,4300
2018-03-09,20835,2573
2018-03-08,21155,1377
2018-03-07,21445,823
2018-03-06,21620,1857
2018-03-05,21250,944
2018-03-02,21065,13615
2018-02-28,21660,1602
2018-02-27,22015,1321
2018-02-26,22000,1772
2018-02-23,21630,3356
2018-02-22,21065,1132
2018-02-21,21100,2858
2018-02-20,21440,1009
2018-02-19,21470,17845
2018-02-14,20425,1613
2018-02-13,20555,2965
2018-02-12,20610,1933
2018-02-09,20880,14094
2018-02-08,21265,6084
2018-02-07,21935,5776
2018-02-06,21850,10332
2018-02-05,22380,2315
2018-02-02,22745,4872
2018-02-01,22320,2122
2018-01-31,22005,4318
2018-01-30,22315,9906
2018-01-29,22825,6765
2018-01-26,22510,2785
2018-01-25,22835,6897
2018-01-24,22190,2394
2018-01-23,22030,3597
2018-01-22,21800,2579
2018-01-19,21720,4515
2018-01-18,22030,3831
2018-01-17,21930,9339
2018-01-16,22175,8404
2018-01-15,22185,4435
2018-01-12,21820,3494
2018-01-11,21845,4932
2018-01-10,21850,9899
2018-01-09,21385,2203
2018-01-08,21180,3327
2018-01-05,21320,1647
2018-01-04,21380,16966
2018-01-03,20770,7894
2018-01-02,20895,3411
2017-12-28,20535,3463
2017-12-27,20515,9791
2017-12-26,20155,4842
2017-12-22,20030,4635
2017-12-21,19995,7034
2017-12-20,19885,1499
2017-12-19,19765,673
2017-12-18,19830,5575
2017-12-15,19720,3386
2017-12-14,19555,6769
2017-12-13,19855,1442
2017-12-12,20135,2307
2017-12-11,19700,5892
2017-12-08,19520,2279
2017-12-07,19325,15604
2017-12-06,19775,1261
2017-12-05,19790,3119
2017-12-04,19960,559
2017-12-01,19865,5407
2017-11-30,19805,21065
2017-11-29,19840,41557
2017-11-28,19880,1899
2017-11-27,20190,23006
2017-11-24,20160,3308
2017-11-23,19955,6844
2017-11-22,19905,8028
2017-11-21,19475,1062
2017-11-20,19580,2896
2017-11-17,19145,807
2017-11-16,19145,428
2017-11-15,19060,6791
2017-11-14,19565,3999
2017-11-13,19625,6933
Binary file added sswtioil.xlsx
Binary file not shown.