# KVLCC2 eddy damping $\sigma$

# Purpose
The ikeda eddy damping seems to be sensitive to section coefficient $\sigma$ which is showen in this notebook.

# Methodology
Make a variation of $\sigma$ for the mid section of KVLCC2

# Setup

```python
# %load imports.py
"""
These is the standard setup for the notebooks.
"""

%matplotlib inline
%load_ext autoreload
%autoreload 2

from jupyterthemes import jtplot
jtplot.style(theme='onedork', context='notebook', ticks=True, grid=False)

import pandas as pd
pd.options.display.max_rows = 999
pd.options.display.max_columns = 999
pd.set_option("display.max_columns", None)
import numpy as np
import os
import matplotlib.pyplot as plt
from collections import OrderedDict
#plt.style.use('paper')

#import data
import copy
from mdldb.run import Run

from sklearn.pipeline import Pipeline
from rolldecayestimators.transformers import CutTransformer, LowpassFilterDerivatorTransformer, ScaleFactorTransformer, OffsetTransformer
from rolldecayestimators.direct_estimator_cubic import EstimatorQuadraticB, EstimatorCubic
from rolldecayestimators.ikeda_estimator import IkedaQuadraticEstimator
import rolldecayestimators.equations as equations
import rolldecayestimators.lambdas as lambdas
from rolldecayestimators.substitute_dynamic_symbols import lambdify
import rolldecayestimators.symbols as symbols
import sympy as sp

from sympy.physics.vector.printing import vpprint, vlatex
from IPython.display import display, Math, Latex

from sklearn.metrics import r2_score
from src.data import database
from mdldb import tables
import shipflowmotionshelpers.shipflowmotionshelpers as helpers
import shipflowmotionshelpers.preprocess as preprocess

```

    Duplicate key in file WindowsPath('C:/Users/maa/.matplotlib/stylelib/paper.mplstyle'), line 461 ('figure.figsize   : 5, 3   ## figure size in inches')
    Duplicate key in file WindowsPath('C:/Users/maa/.matplotlib/stylelib/paper.mplstyle'), line 462 ('figure.dpi       : 100        ## figure dots per inch')

```python
import joblib
from src.helpers import get_ikeda, calculate_ikeda, get_estimator_variation, get_data_variation
from rolldecayestimators import fit_on_amplitudes
from copy import deepcopy
from rolldecayestimators.ikeda import Ikeda, IkedaR, IkedaCarlJohan, IkedaBarge, IkedaBeSimplified
import rolldecayestimators.ikeda_speed
import scipy
import rolldecayestimators.ikeda_speed
```

## Load MDL results

```python
db = database.get_db()

sql = """
SELECT * from run
INNER JOIN loading_conditions
ON (run.loading_condition_id = loading_conditions.id)
INNER JOIN models
ON (run.model_number = models.model_number)
INNER JOIN ships
ON (run.ship_name = ships.name)
WHERE run.model_number='M5057-01-A' and run.test_type='roll decay' and run.project_number=40178362;
"""
df_rolldecays = pd.read_sql(sql=sql, con=db.engine)
df_rolldecays['rho']=1000
df_rolldecays['g']=9.81
df_rolldecays=df_rolldecays.loc[:,~df_rolldecays.columns.duplicated()]
df_rolldecays.set_index('id', inplace=True)

df_rolldecays['ship_speed'].fillna(0, inplace=True)
df_rolldecays['R'] = 2.4 # Bilge keel radius measured on geometry (full scale)

df_rolldecays=df_rolldecays.loc[[21338,21340,]].copy()
```

```python
run = df_rolldecays.iloc[0]
```

```python
scale_factor = run.scale_factor
beam = np.array([run.beam/scale_factor])
draught = np.array([run.TA/scale_factor])
sigma = 0.99
S_s = sigma*beam*draught

a, a_1, a_3, sigma_s, H = rolldecayestimators.ikeda_speed.calculate_sectional_lewis(B_s=beam, T_s=draught, S_s=S_s)

lewis = pd.Series()

lewis['a']=float(a)
lewis['a_1']=a_1[0]
lewis['a_3']=a_3[0]
lewis['sigma']=sigma_s[0]
lewis['H0']=H[0]
lewis['Ts']=draught[0]
lewis['Bs']=beam[0]
lewis['R_b']=2.4/scale_factor

```

    c:\dev\prediction-of-roll-damping-using-fully-nonlinear-potential-flow-and-ikedas-method\venv\lib\site-packages\ipykernel_launcher.py:9: DeprecationWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
      if __name__ == '__main__':

```python
N = 10000
df_frame = pd.DataFrame(data = np.tile(lewis,(N,1)), columns=lewis.index)
df_frame['sigma'] = np.linspace(0.6,1,N)
#df_frame = df_frame.astype(float)
```

```python
phi_a = np.deg2rad(10)
w = 2.4621496310208086
OG = 0.032352941176470584

df_frame['B_E0_s'] = rolldecayestimators.ikeda_speed.eddy_sections(bwl=df_frame.Bs, a_1=df_frame.a_1, a_3=df_frame.a_3, sigma=df_frame.sigma, H0=df_frame.H0, Ts=df_frame.Ts,
                                                  OG=OG,
                                                  R=df_frame.R_b,
                                                  wE=w,
                                                  fi_a=phi_a)
df_frame.set_index('sigma', inplace=True)
```

```python
fig,ax=plt.subplots()
df_frame.plot(y='B_E0_s', ax=ax)

ax.set_xlabel(r'$\sigma$ $[-]$')
ax.set_ylabel(r'$\frac{\hat{B_{E}}}{L_{pp}}$')
ax.set_ylim(0,2)
x = 0.99
y = 0.785
ax.annotate('Limit',xy=(x,y), xytext=(0.94,0.85*y), arrowprops=dict(facecolor='black', shrink=0.05))
ax.get_legend().set_visible(False)

# location for the zoomed portion
sub_axes = fig.add_axes([.25, .55, .40, .30])
df_frame.loc[0.985:0.994].plot(y='B_E0_s', ax=sub_axes)
sub_axes.annotate('Limit',xy=(x,y), xytext=(0.99,0.79), arrowprops=dict(facecolor='black', shrink=0.05))
sub_axes.set_xlabel(r'$\sigma$ $[-]$')
sub_axes.get_legend().set_visible(False)
```


```python
import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid')
plt.style.use("fivethirtyeight")
%matplotlib inline

# For reading stock data from yahoo
from pandas_datareader.data import DataReader

# For time stamps
from datetime import datetime
```

```python
tech_list = ['AAPL', 'GOOG', 'MSFT', 'AMZN']

# Set up End and Start times for data grab
end = datetime.now()
start = datetime(end.year - 1, end.month, end.day)

#For loop for grabing yahoo finance data and setting as a dataframe
for stock in tech_list:
    # Set DataFrame as the Stock Ticker
    globals()[stock] = DataReader(stock, 'yahoo', start, end)
```

```python
company_list = [AAPL, GOOG, MSFT, AMZN]
company_name = ["APPLE", "GOOGLE", "MICROSOFT", "AMAZON"]

for company, com_name in zip(company_list, company_name):
    company["company_name"] = com_name

df = pd.concat(company_list, axis=0)
df.tail(10)
```

      High
      Low
      Open
      Close
      Volume
      Adj Close
      company_name

      Date

      2021-05-17
      3292.750000
      3234.590088
      3245.929932
      3270.389893
      3723900.0
      3270.389893
      AMAZON

      2021-05-18
      3312.000000
      3230.370117
      3292.580078
      3232.280029
      2828400.0
      3232.280029
      AMAZON

      2021-05-19
      3234.750000
      3184.000000
      3195.000000
      3231.800049
      2679700.0
      3231.800049
      AMAZON

      2021-05-20
      3259.679932
      3236.179932
      3244.399902
      3247.679932
      2633200.0
      3247.679932
      AMAZON

      2021-05-21
      3256.689941
      3197.010010
      3250.000000
      3203.080078
      4097800.0
      3203.080078
      AMAZON

      2021-05-24
      3257.949951
      3210.500000
      3215.500000
      3244.989990
      2422800.0
      3244.989990
      AMAZON

      2021-05-25
      3279.820068
      3213.760010
      3266.669922
      3259.050049
      3261100.0
      3259.050049
      AMAZON

      2021-05-26
      3295.729980
      3258.510010
      3274.590088
      3265.159912
      2384000.0
      3265.159912
      AMAZON

      2021-05-27
      3260.360107
      3230.040039
      3256.000000
      3230.110107
      2561200.0
      3230.110107
      AMAZON

      2021-05-28
      3247.989990
      3219.699951
      3242.000000
      3223.070068
      2329800.0
      3223.070068
      AMAZON

```python
plt.figure(figsize=(15, 6))
plt.subplots_adjust(top=1.25, bottom=1.2)

for i, company in enumerate(company_list, 1):
    plt.subplot(2, 2, i)
    company['Adj Close'].plot()
    plt.ylabel('Adj Close')
    plt.xlabel(None)
    plt.title(f"Closing Price of {tech_list[i - 1]}")

plt.tight_layout()
```

```python
end_date = datetime(2021,1,1)
cut_date = datetime(2020,1,1)
frac_missing = 0.3
df = DataReader('AAPL', data_source='yahoo', start='2012-01-01', end=end_date)
df
```

      High
      Low
      Open
      Close
      Volume
      Adj Close

      Date

      2012-01-03
      14.732143
      14.607143
      14.621429
      14.686786
      302220800.0
      12.629209

      2012-01-04
      14.810000
      14.617143
      14.642857
      14.765714
      260022000.0
      12.697079

      2012-01-05
      14.948214
      14.738214
      14.819643
      14.929643
      271269600.0
      12.838044

      2012-01-06
      15.098214
      14.972143
      14.991786
      15.085714
      318292800.0
      12.972249

      2012-01-09
      15.276786
      15.048214
      15.196429
      15.061786
      394024400.0
      12.951672

      ...
      ...
      ...
      ...
      ...
      ...
      ...

      2020-12-24
      133.460007
      131.100006
      131.320007
      131.970001
      54930100.0
      131.549637

      2020-12-28
      137.339996
      133.509995
      133.990005
      136.690002
      124486200.0
      136.254608

      2020-12-29
      138.789993
      134.339996
      138.050003
      134.869995
      121047300.0
      134.440399

      2020-12-30
      135.990005
      133.399994
      135.580002
      133.720001
      96452100.0
      133.294067

      2020-12-31
      134.740005
      131.720001
      134.080002
      132.690002
      99116600.0
      132.267349

2265 rows × 6 columns

```python
def delete_10(col):

    return col

df_missing = df.copy().apply(delete_10, axis=0)
```

```python
df.isnull().sum()
```

    High         0
    Low          0
    Open         0
    Close        0
    Volume       0
    Adj Close    0
    dtype: int64

```python
plt.figure(figsize=(16,6))
plt.title('Close Price History')
plt.plot(df['Close'], 'o', markersize = 0.5)
plt.xlabel('Date', fontsize=18)
plt.ylabel('Close Price USD ($)', fontsize=18)
plt.show()
```

```python
plt.figure(figsize=(16,6))
plt.title('Close Price History')
plt.plot(df_missing['Close'], 'o', markersize = 0.5)
plt.xlabel('Date', fontsize=18)
plt.ylabel('Close Price USD ($)', fontsize=18)
plt.show()
```

```python
# Select the variable of interest
df_closed = df['Close']

# Define the X and Y vectors
x = np.arange(0,df_closed.shape[0],1)
y = df_closed.tolist()

# Plot
plt.figure(figsize = (16,6))
plt.plot(x,y, 'ok', markersize = 0.5)
```

```python
def stock(variable):

    index = np.floor(variable)
    difference = int((round(variable - index,1)*100))

    values = np.linspace(y[index],y[index+1],100)

    value = values[difference]

    return value
```

```python
x_normalized = np.linspace(-1,1, len(x))
x_normalized
```

    array([-1.        , -0.99911661, -0.99823322, ...,  0.99823322,
            0.99911661,  1.        ])

```python
df_missing['Close']
```

    Date
    2012-01-03     14.686786
    2012-01-04     14.765714
    2012-01-05     14.929643
    2012-01-06     15.085714
    2012-01-09     15.061786
                     ...
    2020-12-24    131.970001
    2020-12-28    136.690002
    2020-12-29    134.869995
    2020-12-30    133.720001
    2020-12-31    132.690002
    Name: Close, Length: 2265, dtype: float64

```python
tointclose=df_missing['Close']
tointclose

```

    Date
    2012-01-03     14.686786
    2012-01-04     14.765714
    2012-01-05     14.929643
    2012-01-06     15.085714
    2012-01-09     15.061786
                     ...
    2020-12-24    131.970001
    2020-12-28    136.690002
    2020-12-29    134.869995
    2020-12-30    133.720001
    2020-12-31    132.690002
    Name: Close, Length: 2265, dtype: float64

```python
import pandas as pd
import sympy as sym
import numpy
import matplotlib.pyplot as plt
from pylab import mpl
import numpy as np
import pandas as pd
import math

class Interpolation:

    def __init__(self, data : pd.DataFrame):

        self.data = data
        self.x = np.arange(0,self.data.shape[0],1)
        self.y = self.data.tolist()
        self.xx=x.tolist()

        k=len(y)
        i=0
        self.lista_x=[]
        self.lista_y=[]
        while (i<k):
          if pd.isna(self.y[i]):
            self.lista_y.append(self.y.pop(i))
            self.lista_x.append(self.xx.pop(i))
            k=len(self.y)
            i=0
          else:
            i+=1

    def newton_interpolation(self,X,Y,x):
      sum=Y[0]
      temp=np.zeros((len(X),len(X)))
          # Asignar la primera línea
      for i in range(0,len(X)):
          temp[i,0]=Y[i]
      temp_sum=1.0
      for i in range(1,len(X)):
                  #x polinomio
          temp_sum=temp_sum*(x-X[i-1])
                  # Calcular diferencia de medias
          for j in range(i,len(X)):
              temp[j,i]=(temp[j,i-1]-temp[j-1,i-1])/(X[j]-X[j-i])
          sum+=temp_sum*temp[i,i]
      return sum

    def lagrange_interpolation(self,xi,fi):
          n = len(xi)
          x = sym.Symbol('x')
          polinomio = 0
          divisorL = np.zeros(n, dtype = float)
          for i in range(0,n,1):

              # Termino de Lagrange
              numerador = 1
              denominador = 1
              for j  in range(0,n,1):
                  if (j!=i):
                      numerador = numerador*(x-xi[j])
                      denominador = denominador*(xi[i]-xi[j])
              terminoLi = numerador/denominador

              polinomio = polinomio + terminoLi*fi[i]
              divisorL[i] = denominador

          # simplifica el polinomio
          polisimple = polinomio.expand()

          # para evaluación numérica
          px = sym.lambdify(x,polisimple)

          # Puntos para la gráfica
          muestras = 101
          a = np.min(xi)
          b = np.max(xi)
          pxi = np.linspace(a,b,muestras)
          pfi = px(pxi)

          return polisimple
```

```python
obj_interpolar=Interpolation(tointclose)
```

```python
funcion=obj_interpolar.lagrange_interpolation(obj_interpolar.xx[1:5],obj_interpolar.y[1:5])
```

```python
min_pol = 3
max_pol = 6

interval = []

intervals = []

def cut_interval(interval):

    first_interval = interval[:min_pol+1]
    second_interval = []

    done = False
    for x in interval[min_pol+1:]:
        if x != first_interval[-1] + 1 and not done:
            first_interval.append(x)
        else:
            second_interval.append(x)
            done = True

    return first_interval, second_interval

for i, x in enumerate(obj_interpolar.xx):

    # Llenar la lista hasta su maximo
    if len(interval) == max_pol:
        intervals.append(interval)
        interval = []

    # Si el intervalo esta vacio
    elif interval == []:

        # Verificar si lista de intervalos esta vacia
        if intervals != []:

            if x != intervals[-1][-1] + 1:
                first_interval, second_interval = cut_interval(intervals[-1])
                intervals[-1] = first_interval
                interval = second_interval

                if len(interval) < max_pol:
                    interval.append(x)
                else:
                    intervals.append(interval)
                    interval = [x]

            # Se puede agregar con tranquilidad, no hay discontinuidades
            else:
                interval.append(x)
        # Si esta vacia simplemente adicione elementos al intervalo actual
        # ya que esta construyendo el primer interbalo
        else:
            interval.append(x)

    # Si no esta vacio y no ha alzanzado el maximo adicionar hasta llegar a su
    # maximo
    else:
        interval.append(x)

print(intervals)

interval_tuples = [(interval[0], interval[-1]) for interval in intervals]
interval_tuples

cont = 0
last = -1
malos = 0
algo_pasa = []
for i, inter in enumerate(interval_tuples):
    print(inter)
    if obj_interpolar.xx.index(inter[1])-obj_interpolar.xx.index(inter[0]) > max_pol:
        cont += 1

    if last != inter[0]-1:
        print('ALGO PASA')
        algo_pasa.append(i)
        malos +=1

    last = inter[1]

print(cont)
print(malos)
print(algo_pasa)

# replacements = []

# for i in algo_pasa:
#     first_interval = intervals[i-1]
#     second_interval = intervals[i]

#     joint = first_interval + second_interval

#     new_intervals = []
#     new_interval = []
#     for i, x in enumerate(joint):
#         if len(new_interval) >= min_pol:
#             if new_intervals == []:
#                 if x == new_interval[-1] + 1:
#                     new_intervals.append(new_interval)
#                     new_interval = []
#                 else:
#                     new_interval.append(x)
#             else:
#                 if x == new_interval[-1]+1:
#                     new_intervals.append(new_interval)
#                     new_interval = []
#                 else:
#                     new_interval.append(x)
#         else:
#             new_interval.append(x)

#         if i == len(joint)-1:
#             new_intervals.append(new_interval)

#     replacements.extend(new_intervals)

# replacements
```

    [[0, 1, 2, 3], [4, 5, 7, 8], [9, 10, 12, 13], [14, 15, 17, 18], [19, 20, 22, 23], [24, 25, 27, 28], [29, 30, 32, 33], [34, 35, 37, 38], [39, 40, 42, 43], [44, 45, 47, 48], [49, 50, 52, 53], [54, 55, 57, 58], [59, 60, 62, 63], [64, 65, 67, 68], [69, 70, 72, 73], [74, 75, 77, 78], [79, 80, 82, 83], [84, 85, 87, 88], [89, 90, 92, 93], [94, 95, 97, 98], [99, 100, 102, 103], [104, 105, 107, 108], [109, 110, 112, 113], [114, 115, 117, 118], [119, 120, 122, 123], [124, 125, 127, 128], [129, 130, 132, 133], [134, 135, 137, 138], [139, 140, 142, 143], [144, 145, 147, 148], [149, 150, 152, 153], [154, 155, 157, 158], [159, 160, 162, 163], [164, 165, 167, 168], [169, 170, 172, 173], [174, 175, 177, 178], [179, 180, 182, 183], [184, 185, 187, 188], [189, 190, 192, 193], [194, 195, 197, 198], [199, 200, 202, 203], [204, 205, 207, 208], [209, 210, 212, 213], [214, 215, 217, 218], [219, 220, 222, 223], [224, 225, 227, 228], [229, 230, 232, 233], [234, 235, 237, 238], [239, 240, 242, 243], [244, 245, 247, 248], [249, 250, 252, 253], [254, 255, 257, 258], [259, 260, 262, 263], [264, 265, 267, 268], [269, 270, 272, 273], [274, 275, 277, 278], [279, 280, 282, 283], [284, 285, 287, 288], [289, 290, 292, 293], [294, 295, 297, 298], [299, 300, 302, 303], [304, 305, 307, 308], [309, 310, 312, 313], [314, 315, 317, 318], [319, 320, 322, 323], [324, 325, 327, 328], [329, 330, 332, 333], [334, 335, 337, 338], [339, 340, 342, 343], [344, 345, 347, 348], [349, 350, 352, 353], [354, 355, 357, 358], [359, 360, 362, 363], [364, 365, 367, 368], [369, 370, 372, 373], [374, 375, 377, 378], [379, 380, 382, 383], [384, 385, 387, 388], [389, 390, 392, 393], [394, 395, 397, 398], [399, 400, 402, 403], [404, 405, 407, 408], [409, 410, 412, 413], [414, 415, 417, 418], [419, 420, 422, 423], [424, 425, 427, 428], [429, 430, 432, 433], [434, 435, 437, 438], [439, 440, 442, 443], [444, 445, 447, 448], [449, 450, 452, 453], [454, 455, 457, 458], [459, 460, 462, 463], [464, 465, 467, 468], [469, 470, 472, 473], [474, 475, 477, 478], [479, 480, 482, 483], [484, 485, 487, 488], [489, 490, 492, 493], [494, 495, 497, 498], [499, 500, 502, 503], [504, 505, 507, 508], [509, 510, 512, 513], [514, 515, 517, 518], [519, 520, 522, 523], [524, 525, 527, 528], [529, 530, 532, 533], [534, 535, 537, 538], [539, 540, 542, 543], [544, 545, 547, 548], [549, 550, 552, 553], [554, 555, 557, 558], [559, 560, 562, 563], [564, 565, 567, 568], [569, 570, 572, 573], [574, 575, 577, 578], [579, 580, 582, 583], [584, 585, 587, 588], [589, 590, 592, 593], [594, 595, 597, 598], [599, 600, 602, 603], [604, 605, 607, 608], [609, 610, 612, 613], [614, 615, 617, 618], [619, 620, 622, 623], [624, 625, 627, 628], [629, 630, 632, 633], [634, 635, 637, 638], [639, 640, 642, 643], [644, 645, 647, 648], [649, 650, 652, 653], [654, 655, 657, 658], [659, 660, 662, 663], [664, 665, 667, 668], [669, 670, 672, 673], [674, 675, 677, 678], [679, 680, 682, 683], [684, 685, 687, 688], [689, 690, 692, 693], [694, 695, 697, 698], [699, 700, 702, 703], [704, 705, 707, 708], [709, 710, 712, 713], [714, 715, 717, 718], [719, 720, 722, 723], [724, 725, 727, 728], [729, 730, 732, 733], [734, 735, 737, 738], [739, 740, 742, 743], [744, 745, 747, 748], [749, 750, 752, 753], [754, 755, 757, 758], [759, 760, 762, 763], [764, 765, 767, 768], [769, 770, 772, 773], [774, 775, 777, 778], [779, 780, 782, 783], [784, 785, 787, 788], [789, 790, 792, 793], [794, 795, 797, 798], [799, 800, 802, 803], [804, 805, 807, 808], [809, 810, 812, 813], [814, 815, 817, 818], [819, 820, 822, 823], [824, 825, 827, 828], [829, 830, 832, 833], [834, 835, 837, 838], [839, 840, 842, 843], [844, 845, 847, 848], [849, 850, 852, 853], [854, 855, 857, 858], [859, 860, 862, 863], [864, 865, 867, 868], [869, 870, 872, 873], [874, 875, 877, 878], [879, 880, 882, 883], [884, 885, 887, 888], [889, 890, 892, 893], [894, 895, 897, 898], [899, 900, 902, 903], [904, 905, 907, 908], [909, 910, 912, 913], [914, 915, 917, 918], [919, 920, 922, 923], [924, 925, 927, 928], [929, 930, 932, 933], [934, 935, 937, 938], [939, 940, 942, 943], [944, 945, 947, 948], [949, 950, 952, 953], [954, 955, 957, 958], [959, 960, 962, 963], [964, 965, 967, 968], [969, 970, 972, 973], [974, 975, 977, 978], [979, 980, 982, 983], [984, 985, 987, 988], [989, 990, 992, 993], [994, 995, 997, 998], [999, 1000, 1002, 1003], [1004, 1005, 1007, 1008], [1009, 1010, 1012, 1013], [1014, 1015, 1017, 1018], [1019, 1020, 1022, 1023], [1024, 1025, 1027, 1028], [1029, 1030, 1032, 1033], [1034, 1035, 1037, 1038], [1039, 1040, 1042, 1043], [1044, 1045, 1047, 1048], [1049, 1050, 1052, 1053], [1054, 1055, 1057, 1058], [1059, 1060, 1062, 1063], [1064, 1065, 1067, 1068], [1069, 1070, 1072, 1073], [1074, 1075, 1077, 1078], [1079, 1080, 1082, 1083], [1084, 1085, 1087, 1088], [1089, 1090, 1092, 1093], [1094, 1095, 1097, 1098], [1099, 1100, 1102, 1103], [1104, 1105, 1107, 1108], [1109, 1110, 1112, 1113], [1114, 1115, 1117, 1118], [1119, 1120, 1122, 1123], [1124, 1125, 1127, 1128], [1129, 1130, 1132, 1133], [1134, 1135, 1137, 1138], [1139, 1140, 1142, 1143], [1144, 1145, 1147, 1148], [1149, 1150, 1152, 1153], [1154, 1155, 1157, 1158], [1159, 1160, 1162, 1163], [1164, 1165, 1167, 1168], [1169, 1170, 1172, 1173], [1174, 1175, 1177, 1178], [1179, 1180, 1182, 1183], [1184, 1185, 1187, 1188], [1189, 1190, 1192, 1193], [1194, 1195, 1197, 1198], [1199, 1200, 1202, 1203], [1204, 1205, 1207, 1208], [1209, 1210, 1212, 1213], [1214, 1215, 1217, 1218], [1219, 1220, 1222, 1223], [1224, 1225, 1227, 1228], [1229, 1230, 1232, 1233], [1234, 1235, 1237, 1238], [1239, 1240, 1242, 1243], [1244, 1245, 1247, 1248], [1249, 1250, 1252, 1253], [1254, 1255, 1257, 1258], [1259, 1260, 1262, 1263], [1264, 1265, 1267, 1268], [1269, 1270, 1272, 1273], [1274, 1275, 1277, 1278], [1279, 1280, 1282, 1283], [1284, 1285, 1287, 1288], [1289, 1290, 1292, 1293], [1294, 1295, 1297, 1298], [1299, 1300, 1302, 1303], [1304, 1305, 1307, 1308], [1309, 1310, 1312, 1313], [1314, 1315, 1317, 1318], [1319, 1320, 1322, 1323], [1324, 1325, 1327, 1328], [1329, 1330, 1332, 1333], [1334, 1335, 1337, 1338], [1339, 1340, 1342, 1343], [1344, 1345, 1347, 1348], [1349, 1350, 1352, 1353], [1354, 1355, 1357, 1358], [1359, 1360, 1362, 1363], [1364, 1365, 1367, 1368], [1369, 1370, 1372, 1373], [1374, 1375, 1377, 1378], [1379, 1380, 1382, 1383], [1384, 1385, 1387, 1388], [1389, 1390, 1392, 1393], [1394, 1395, 1397, 1398], [1399, 1400, 1402, 1403], [1404, 1405, 1407, 1408], [1409, 1410, 1412, 1413], [1414, 1415, 1417, 1418], [1419, 1420, 1422, 1423], [1424, 1425, 1427, 1428], [1429, 1430, 1432, 1433], [1434, 1435, 1437, 1438], [1439, 1440, 1442, 1443], [1444, 1445, 1447, 1448], [1449, 1450, 1452, 1453], [1454, 1455, 1457, 1458], [1459, 1460, 1462, 1463], [1464, 1465, 1467, 1468], [1469, 1470, 1472, 1473], [1474, 1475, 1477, 1478], [1479, 1480, 1482, 1483], [1484, 1485, 1487, 1488], [1489, 1490, 1492, 1493], [1494, 1495, 1497, 1498], [1499, 1500, 1502, 1503], [1504, 1505, 1507, 1508], [1509, 1510, 1512, 1513], [1514, 1515, 1517, 1518], [1519, 1520, 1522, 1523], [1524, 1525, 1527, 1528], [1529, 1530, 1532, 1533], [1534, 1535, 1537, 1538], [1539, 1540, 1542, 1543], [1544, 1545, 1547, 1548], [1549, 1550, 1552, 1553], [1554, 1555, 1557, 1558], [1559, 1560, 1562, 1563], [1564, 1565, 1567, 1568], [1569, 1570, 1572, 1573], [1574, 1575, 1577, 1578], [1579, 1580, 1582, 1583], [1584, 1585, 1587, 1588], [1589, 1590, 1592, 1593], [1594, 1595, 1597, 1598], [1599, 1600, 1602, 1603], [1604, 1605, 1607, 1608], [1609, 1610, 1612, 1613], [1614, 1615, 1617, 1618], [1619, 1620, 1622, 1623], [1624, 1625, 1627, 1628], [1629, 1630, 1632, 1633], [1634, 1635, 1637, 1638], [1639, 1640, 1642, 1643], [1644, 1645, 1647, 1648], [1649, 1650, 1652, 1653], [1654, 1655, 1657, 1658], [1659, 1660, 1662, 1663], [1664, 1665, 1667, 1668], [1669, 1670, 1672, 1673], [1674, 1675, 1677, 1678], [1679, 1680, 1682, 1683], [1684, 1685, 1687, 1688], [1689, 1690, 1692, 1693], [1694, 1695, 1697, 1698], [1699, 1700, 1702, 1703], [1704, 1705, 1707, 1708], [1709, 1710, 1712, 1713], [1714, 1715, 1717, 1718], [1719, 1720, 1722, 1723], [1724, 1725, 1727, 1728], [1729, 1730, 1732, 1733], [1734, 1735, 1737, 1738], [1739, 1740, 1742, 1743], [1744, 1745, 1747, 1748], [1749, 1750, 1752, 1753], [1754, 1755, 1757, 1758], [1759, 1760, 1762, 1763], [1764, 1765, 1767, 1768], [1769, 1770, 1772, 1773], [1774, 1775, 1777, 1778], [1779, 1780, 1782, 1783], [1784, 1785, 1787, 1788], [1789, 1790, 1792, 1793], [1794, 1795, 1797, 1798], [1799, 1800, 1802, 1803], [1804, 1805, 1807, 1808], [1809, 1810, 1812, 1813], [1814, 1815, 1817, 1818], [1819, 1820, 1822, 1823], [1824, 1825, 1827, 1828], [1829, 1830, 1832, 1833], [1834, 1835, 1837, 1838], [1839, 1840, 1842, 1843], [1844, 1845, 1847, 1848], [1849, 1850, 1852, 1853], [1854, 1855, 1857, 1858], [1859, 1860, 1862, 1863], [1864, 1865, 1867, 1868], [1869, 1870, 1872, 1873], [1874, 1875, 1877, 1878], [1879, 1880, 1882, 1883], [1884, 1885, 1887, 1888], [1889, 1890, 1892, 1893], [1894, 1895, 1897, 1898], [1899, 1900, 1902, 1903], [1904, 1905, 1907, 1908], [1909, 1910, 1912, 1913], [1914, 1915, 1917, 1918], [1919, 1920, 1922, 1923], [1924, 1925, 1927, 1928], [1929, 1930, 1932, 1933], [1934, 1935, 1937, 1938], [1939, 1940, 1942, 1943], [1944, 1945, 1947, 1948], [1949, 1950, 1952, 1953], [1954, 1955, 1957, 1958], [1959, 1960, 1962, 1963], [1964, 1965, 1967, 1968], [1969, 1970, 1972, 1973], [1974, 1975, 1977, 1978], [1979, 1980, 1982, 1983], [1984, 1985, 1987, 1988], [1989, 1990, 1992, 1993], [1994, 1995, 1997, 1998], [1999, 2000, 2002, 2003], [2004, 2005, 2007, 2008], [2009, 2010, 2012, 2013], [2014, 2015, 2017, 2018], [2019, 2020, 2022, 2023], [2024, 2025, 2027, 2028], [2029, 2030, 2032, 2033], [2034, 2035, 2037, 2038], [2039, 2040, 2042, 2043], [2044, 2045, 2047, 2048], [2049, 2050, 2052, 2053], [2054, 2055, 2057, 2058], [2059, 2060, 2062, 2063], [2064, 2065, 2067, 2068], [2069, 2070, 2072, 2073], [2074, 2075, 2077, 2078], [2079, 2080, 2082, 2083], [2084, 2085, 2087, 2088], [2089, 2090, 2092, 2093], [2094, 2095, 2097, 2098], [2099, 2100, 2102, 2103], [2104, 2105, 2107, 2108], [2109, 2110, 2112, 2113], [2114, 2115, 2117, 2118], [2119, 2120, 2122, 2123], [2124, 2125, 2127, 2128], [2129, 2130, 2132, 2133], [2134, 2135, 2137, 2138], [2139, 2140, 2142, 2143], [2144, 2145, 2147, 2148], [2149, 2150, 2152, 2153], [2154, 2155, 2157, 2158], [2159, 2160, 2162, 2163], [2164, 2165, 2167, 2168], [2169, 2170, 2172, 2173], [2174, 2175, 2177, 2178], [2179, 2180, 2182, 2183], [2184, 2185, 2187, 2188], [2189, 2190, 2192, 2193], [2194, 2195, 2197, 2198], [2199, 2200, 2202, 2203], [2204, 2205, 2207, 2208], [2209, 2210, 2212, 2213], [2214, 2215, 2217, 2218], [2219, 2220, 2222, 2223], [2224, 2225, 2227, 2228], [2229, 2230, 2232, 2233], [2234, 2235, 2237, 2238], [2239, 2240, 2242, 2243], [2244, 2245, 2247, 2248], [2249, 2250, 2252, 2253], [2254, 2255, 2257, 2258]]
    (0, 3)
    (4, 8)
    (9, 13)
    (14, 18)
    (19, 23)
    (24, 28)
    (29, 33)
    (34, 38)
    (39, 43)
    (44, 48)
    (49, 53)
    (54, 58)
    (59, 63)
    (64, 68)
    (69, 73)
    (74, 78)
    (79, 83)
    (84, 88)
    (89, 93)
    (94, 98)
    (99, 103)
    (104, 108)
    (109, 113)
    (114, 118)
    (119, 123)
    (124, 128)
    (129, 133)
    (134, 138)
    (139, 143)
    (144, 148)
    (149, 153)
    (154, 158)
    (159, 163)
    (164, 168)
    (169, 173)
    (174, 178)
    (179, 183)
    (184, 188)
    (189, 193)
    (194, 198)
    (199, 203)
    (204, 208)
    (209, 213)
    (214, 218)
    (219, 223)
    (224, 228)
    (229, 233)
    (234, 238)
    (239, 243)
    (244, 248)
    (249, 253)
    (254, 258)
    (259, 263)
    (264, 268)
    (269, 273)
    (274, 278)
    (279, 283)
    (284, 288)
    (289, 293)
    (294, 298)
    (299, 303)
    (304, 308)
    (309, 313)
    (314, 318)
    (319, 323)
    (324, 328)
    (329, 333)
    (334, 338)
    (339, 343)
    (344, 348)
    (349, 353)
    (354, 358)
    (359, 363)
    (364, 368)
    (369, 373)
    (374, 378)
    (379, 383)
    (384, 388)
    (389, 393)
    (394, 398)
    (399, 403)
    (404, 408)
    (409, 413)
    (414, 418)
    (419, 423)
    (424, 428)
    (429, 433)
    (434, 438)
    (439, 443)
    (444, 448)
    (449, 453)
    (454, 458)
    (459, 463)
    (464, 468)
    (469, 473)
    (474, 478)
    (479, 483)
    (484, 488)
    (489, 493)
    (494, 498)
    (499, 503)
    (504, 508)
    (509, 513)
    (514, 518)
    (519, 523)
    (524, 528)
    (529, 533)
    (534, 538)
    (539, 543)
    (544, 548)
    (549, 553)
    (554, 558)
    (559, 563)
    (564, 568)
    (569, 573)
    (574, 578)
    (579, 583)
    (584, 588)
    (589, 593)
    (594, 598)
    (599, 603)
    (604, 608)
    (609, 613)
    (614, 618)
    (619, 623)
    (624, 628)
    (629, 633)
    (634, 638)
    (639, 643)
    (644, 648)
    (649, 653)
    (654, 658)
    (659, 663)
    (664, 668)
    (669, 673)
    (674, 678)
    (679, 683)
    (684, 688)
    (689, 693)
    (694, 698)
    (699, 703)
    (704, 708)
    (709, 713)
    (714, 718)
    (719, 723)
    (724, 728)
    (729, 733)
    (734, 738)
    (739, 743)
    (744, 748)
    (749, 753)
    (754, 758)
    (759, 763)
    (764, 768)
    (769, 773)
    (774, 778)
    (779, 783)
    (784, 788)
    (789, 793)
    (794, 798)
    (799, 803)
    (804, 808)
    (809, 813)
    (814, 818)
    (819, 823)
    (824, 828)
    (829, 833)
    (834, 838)
    (839, 843)
    (844, 848)
    (849, 853)
    (854, 858)
    (859, 863)
    (864, 868)
    (869, 873)
    (874, 878)
    (879, 883)
    (884, 888)
    (889, 893)
    (894, 898)
    (899, 903)
    (904, 908)
    (909, 913)
    (914, 918)
    (919, 923)
    (924, 928)
    (929, 933)
    (934, 938)
    (939, 943)
    (944, 948)
    (949, 953)
    (954, 958)
    (959, 963)
    (964, 968)
    (969, 973)
    (974, 978)
    (979, 983)
    (984, 988)
    (989, 993)
    (994, 998)
    (999, 1003)
    (1004, 1008)
    (1009, 1013)
    (1014, 1018)
    (1019, 1023)
    (1024, 1028)
    (1029, 1033)
    (1034, 1038)
    (1039, 1043)
    (1044, 1048)
    (1049, 1053)
    (1054, 1058)
    (1059, 1063)
    (1064, 1068)
    (1069, 1073)
    (1074, 1078)
    (1079, 1083)
    (1084, 1088)
    (1089, 1093)
    (1094, 1098)
    (1099, 1103)
    (1104, 1108)
    (1109, 1113)
    (1114, 1118)
    (1119, 1123)
    (1124, 1128)
    (1129, 1133)
    (1134, 1138)
    (1139, 1143)
    (1144, 1148)
    (1149, 1153)
    (1154, 1158)
    (1159, 1163)
    (1164, 1168)
    (1169, 1173)
    (1174, 1178)
    (1179, 1183)
    (1184, 1188)
    (1189, 1193)
    (1194, 1198)
    (1199, 1203)
    (1204, 1208)
    (1209, 1213)
    (1214, 1218)
    (1219, 1223)
    (1224, 1228)
    (1229, 1233)
    (1234, 1238)
    (1239, 1243)
    (1244, 1248)
    (1249, 1253)
    (1254, 1258)
    (1259, 1263)
    (1264, 1268)
    (1269, 1273)
    (1274, 1278)
    (1279, 1283)
    (1284, 1288)
    (1289, 1293)
    (1294, 1298)
    (1299, 1303)
    (1304, 1308)
    (1309, 1313)
    (1314, 1318)
    (1319, 1323)
    (1324, 1328)
    (1329, 1333)
    (1334, 1338)
    (1339, 1343)
    (1344, 1348)
    (1349, 1353)
    (1354, 1358)
    (1359, 1363)
    (1364, 1368)
    (1369, 1373)
    (1374, 1378)
    (1379, 1383)
    (1384, 1388)
    (1389, 1393)
    (1394, 1398)
    (1399, 1403)
    (1404, 1408)
    (1409, 1413)
    (1414, 1418)
    (1419, 1423)
    (1424, 1428)
    (1429, 1433)
    (1434, 1438)
    (1439, 1443)
    (1444, 1448)
    (1449, 1453)
    (1454, 1458)
    (1459, 1463)
    (1464, 1468)
    (1469, 1473)
    (1474, 1478)
    (1479, 1483)
    (1484, 1488)
    (1489, 1493)
    (1494, 1498)
    (1499, 1503)
    (1504, 1508)
    (1509, 1513)
    (1514, 1518)
    (1519, 1523)
    (1524, 1528)
    (1529, 1533)
    (1534, 1538)
    (1539, 1543)
    (1544, 1548)
    (1549, 1553)
    (1554, 1558)
    (1559, 1563)
    (1564, 1568)
    (1569, 1573)
    (1574, 1578)
    (1579, 1583)
    (1584, 1588)
    (1589, 1593)
    (1594, 1598)
    (1599, 1603)
    (1604, 1608)
    (1609, 1613)
    (1614, 1618)
    (1619, 1623)
    (1624, 1628)
    (1629, 1633)
    (1634, 1638)
    (1639, 1643)
    (1644, 1648)
    (1649, 1653)
    (1654, 1658)
    (1659, 1663)
    (1664, 1668)
    (1669, 1673)
    (1674, 1678)
    (1679, 1683)
    (1684, 1688)
    (1689, 1693)
    (1694, 1698)
    (1699, 1703)
    (1704, 1708)
    (1709, 1713)
    (1714, 1718)
    (1719, 1723)
    (1724, 1728)
    (1729, 1733)
    (1734, 1738)
    (1739, 1743)
    (1744, 1748)
    (1749, 1753)
    (1754, 1758)
    (1759, 1763)
    (1764, 1768)
    (1769, 1773)
    (1774, 1778)
    (1779, 1783)
    (1784, 1788)
    (1789, 1793)
    (1794, 1798)
    (1799, 1803)
    (1804, 1808)
    (1809, 1813)
    (1814, 1818)
    (1819, 1823)
    (1824, 1828)
    (1829, 1833)
    (1834, 1838)
    (1839, 1843)
    (1844, 1848)
    (1849, 1853)
    (1854, 1858)
    (1859, 1863)
    (1864, 1868)
    (1869, 1873)
    (1874, 1878)
    (1879, 1883)
    (1884, 1888)
    (1889, 1893)
    (1894, 1898)
    (1899, 1903)
    (1904, 1908)
    (1909, 1913)
    (1914, 1918)
    (1919, 1923)
    (1924, 1928)
    (1929, 1933)
    (1934, 1938)
    (1939, 1943)
    (1944, 1948)
    (1949, 1953)
    (1954, 1958)
    (1959, 1963)
    (1964, 1968)
    (1969, 1973)
    (1974, 1978)
    (1979, 1983)
    (1984, 1988)
    (1989, 1993)
    (1994, 1998)
    (1999, 2003)
    (2004, 2008)
    (2009, 2013)
    (2014, 2018)
    (2019, 2023)
    (2024, 2028)
    (2029, 2033)
    (2034, 2038)
    (2039, 2043)
    (2044, 2048)
    (2049, 2053)
    (2054, 2058)
    (2059, 2063)
    (2064, 2068)
    (2069, 2073)
    (2074, 2078)
    (2079, 2083)
    (2084, 2088)
    (2089, 2093)
    (2094, 2098)
    (2099, 2103)
    (2104, 2108)
    (2109, 2113)
    (2114, 2118)
    (2119, 2123)
    (2124, 2128)
    (2129, 2133)
    (2134, 2138)
    (2139, 2143)
    (2144, 2148)
    (2149, 2153)
    (2154, 2158)
    (2159, 2163)
    (2164, 2168)
    (2169, 2173)
    (2174, 2178)
    (2179, 2183)
    (2184, 2188)
    (2189, 2193)
    (2194, 2198)
    (2199, 2203)
    (2204, 2208)
    (2209, 2213)
    (2214, 2218)
    (2219, 2223)
    (2224, 2228)
    (2229, 2233)
    (2234, 2238)
    (2239, 2243)
    (2244, 2248)
    (2249, 2253)
    (2254, 2258)
    0
    0
    []

```python
x_interpolate = []
y_interpolate = []

intervals = interval_tuples

l=sym.Symbol('x')
cont = 0
for inter in intervals:
    print(inter)
    beg = obj_interpolar.xx.index(inter[0])
    end = obj_interpolar.xx.index(inter[1])

    datos_interpolar_x = obj_interpolar.xx[beg:end+1]
    datos_interpolar_y = obj_interpolar.y[beg:end+1]
    funcion = obj_interpolar.lagrange_interpolation(datos_interpolar_x,datos_interpolar_y)

    for x in np.arange(datos_interpolar_x[0],datos_interpolar_x[-1]+1, 0.5):
        # print(x)
        cont += 1
        x_interpolate.append(x)
        y = funcion.subs(l,x)
        y_interpolate.append(y)

print(cont)
```

    (0, 3)
    (4, 8)
    (9, 13)
    (14, 18)
    (19, 23)
    (24, 28)
    (29, 33)
    (34, 38)
    (39, 43)
    (44, 48)
    (49, 53)
    (54, 58)
    (59, 63)
    (64, 68)
    (69, 73)
    (74, 78)
    (79, 83)
    (84, 88)
    (89, 93)
    (94, 98)
    (99, 103)
    (104, 108)
    (109, 113)
    (114, 118)
    (119, 123)
    (124, 128)
    (129, 133)
    (134, 138)
    (139, 143)
    (144, 148)
    (149, 153)
    (154, 158)
    (159, 163)
    (164, 168)
    (169, 173)
    (174, 178)
    (179, 183)
    (184, 188)
    (189, 193)
    (194, 198)
    (199, 203)
    (204, 208)
    (209, 213)
    (214, 218)
    (219, 223)
    (224, 228)
    (229, 233)
    (234, 238)
    (239, 243)
    (244, 248)
    (249, 253)
    (254, 258)
    (259, 263)
    (264, 268)
    (269, 273)
    (274, 278)
    (279, 283)
    (284, 288)
    (289, 293)
    (294, 298)
    (299, 303)
    (304, 308)
    (309, 313)
    (314, 318)
    (319, 323)
    (324, 328)
    (329, 333)
    (334, 338)
    (339, 343)
    (344, 348)
    (349, 353)
    (354, 358)
    (359, 363)
    (364, 368)
    (369, 373)
    (374, 378)
    (379, 383)
    (384, 388)
    (389, 393)
    (394, 398)
    (399, 403)
    (404, 408)
    (409, 413)
    (414, 418)
    (419, 423)
    (424, 428)
    (429, 433)
    (434, 438)
    (439, 443)
    (444, 448)
    (449, 453)
    (454, 458)
    (459, 463)
    (464, 468)
    (469, 473)
    (474, 478)
    (479, 483)
    (484, 488)
    (489, 493)
    (494, 498)
    (499, 503)
    (504, 508)
    (509, 513)
    (514, 518)
    (519, 523)
    (524, 528)
    (529, 533)
    (534, 538)
    (539, 543)
    (544, 548)
    (549, 553)
    (554, 558)
    (559, 563)
    (564, 568)
    (569, 573)
    (574, 578)
    (579, 583)
    (584, 588)
    (589, 593)
    (594, 598)
    (599, 603)
    (604, 608)
    (609, 613)
    (614, 618)
    (619, 623)
    (624, 628)
    (629, 633)
    (634, 638)
    (639, 643)
    (644, 648)
    (649, 653)
    (654, 658)
    (659, 663)
    (664, 668)
    (669, 673)
    (674, 678)
    (679, 683)
    (684, 688)
    (689, 693)
    (694, 698)
    (699, 703)
    (704, 708)
    (709, 713)
    (714, 718)
    (719, 723)
    (724, 728)
    (729, 733)
    (734, 738)
    (739, 743)
    (744, 748)
    (749, 753)
    (754, 758)
    (759, 763)
    (764, 768)
    (769, 773)
    (774, 778)
    (779, 783)
    (784, 788)
    (789, 793)
    (794, 798)
    (799, 803)
    (804, 808)
    (809, 813)
    (814, 818)
    (819, 823)
    (824, 828)
    (829, 833)
    (834, 838)
    (839, 843)
    (844, 848)
    (849, 853)
    (854, 858)
    (859, 863)
    (864, 868)
    (869, 873)
    (874, 878)
    (879, 883)
    (884, 888)
    (889, 893)
    (894, 898)
    (899, 903)
    (904, 908)
    (909, 913)
    (914, 918)
    (919, 923)
    (924, 928)
    (929, 933)
    (934, 938)
    (939, 943)
    (944, 948)
    (949, 953)
    (954, 958)
    (959, 963)
    (964, 968)
    (969, 973)
    (974, 978)
    (979, 983)
    (984, 988)
    (989, 993)
    (994, 998)
    (999, 1003)
    (1004, 1008)
    (1009, 1013)
    (1014, 1018)
    (1019, 1023)
    (1024, 1028)
    (1029, 1033)
    (1034, 1038)
    (1039, 1043)
    (1044, 1048)
    (1049, 1053)
    (1054, 1058)
    (1059, 1063)
    (1064, 1068)
    (1069, 1073)
    (1074, 1078)
    (1079, 1083)
    (1084, 1088)
    (1089, 1093)
    (1094, 1098)
    (1099, 1103)
    (1104, 1108)
    (1109, 1113)
    (1114, 1118)
    (1119, 1123)
    (1124, 1128)
    (1129, 1133)
    (1134, 1138)
    (1139, 1143)
    (1144, 1148)
    (1149, 1153)
    (1154, 1158)
    (1159, 1163)
    (1164, 1168)
    (1169, 1173)
    (1174, 1178)
    (1179, 1183)
    (1184, 1188)
    (1189, 1193)
    (1194, 1198)
    (1199, 1203)
    (1204, 1208)
    (1209, 1213)
    (1214, 1218)
    (1219, 1223)
    (1224, 1228)
    (1229, 1233)
    (1234, 1238)
    (1239, 1243)
    (1244, 1248)
    (1249, 1253)
    (1254, 1258)
    (1259, 1263)
    (1264, 1268)
    (1269, 1273)
    (1274, 1278)
    (1279, 1283)
    (1284, 1288)
    (1289, 1293)
    (1294, 1298)
    (1299, 1303)
    (1304, 1308)
    (1309, 1313)
    (1314, 1318)
    (1319, 1323)
    (1324, 1328)
    (1329, 1333)
    (1334, 1338)
    (1339, 1343)
    (1344, 1348)
    (1349, 1353)
    (1354, 1358)
    (1359, 1363)
    (1364, 1368)
    (1369, 1373)
    (1374, 1378)
    (1379, 1383)
    (1384, 1388)
    (1389, 1393)
    (1394, 1398)
    (1399, 1403)
    (1404, 1408)
    (1409, 1413)
    (1414, 1418)
    (1419, 1423)
    (1424, 1428)
    (1429, 1433)
    (1434, 1438)
    (1439, 1443)
    (1444, 1448)
    (1449, 1453)
    (1454, 1458)
    (1459, 1463)
    (1464, 1468)
    (1469, 1473)
    (1474, 1478)
    (1479, 1483)
    (1484, 1488)
    (1489, 1493)
    (1494, 1498)
    (1499, 1503)
    (1504, 1508)
    (1509, 1513)
    (1514, 1518)
    (1519, 1523)
    (1524, 1528)
    (1529, 1533)
    (1534, 1538)
    (1539, 1543)
    (1544, 1548)
    (1549, 1553)
    (1554, 1558)
    (1559, 1563)
    (1564, 1568)
    (1569, 1573)
    (1574, 1578)
    (1579, 1583)
    (1584, 1588)
    (1589, 1593)
    (1594, 1598)
    (1599, 1603)
    (1604, 1608)
    (1609, 1613)
    (1614, 1618)
    (1619, 1623)
    (1624, 1628)
    (1629, 1633)
    (1634, 1638)
    (1639, 1643)
    (1644, 1648)
    (1649, 1653)
    (1654, 1658)
    (1659, 1663)
    (1664, 1668)
    (1669, 1673)
    (1674, 1678)
    (1679, 1683)
    (1684, 1688)
    (1689, 1693)
    (1694, 1698)
    (1699, 1703)
    (1704, 1708)
    (1709, 1713)
    (1714, 1718)
    (1719, 1723)
    (1724, 1728)
    (1729, 1733)
    (1734, 1738)
    (1739, 1743)
    (1744, 1748)
    (1749, 1753)
    (1754, 1758)
    (1759, 1763)
    (1764, 1768)
    (1769, 1773)
    (1774, 1778)
    (1779, 1783)
    (1784, 1788)
    (1789, 1793)
    (1794, 1798)
    (1799, 1803)
    (1804, 1808)
    (1809, 1813)
    (1814, 1818)
    (1819, 1823)
    (1824, 1828)
    (1829, 1833)
    (1834, 1838)
    (1839, 1843)
    (1844, 1848)
    (1849, 1853)
    (1854, 1858)
    (1859, 1863)
    (1864, 1868)
    (1869, 1873)
    (1874, 1878)
    (1879, 1883)
    (1884, 1888)
    (1889, 1893)
    (1894, 1898)
    (1899, 1903)
    (1904, 1908)
    (1909, 1913)
    (1914, 1918)
    (1919, 1923)
    (1924, 1928)
    (1929, 1933)
    (1934, 1938)
    (1939, 1943)
    (1944, 1948)
    (1949, 1953)
    (1954, 1958)
    (1959, 1963)
    (1964, 1968)
    (1969, 1973)
    (1974, 1978)
    (1979, 1983)
    (1984, 1988)
    (1989, 1993)
    (1994, 1998)
    (1999, 2003)
    (2004, 2008)
    (2009, 2013)
    (2014, 2018)
    (2019, 2023)
    (2024, 2028)
    (2029, 2033)
    (2034, 2038)
    (2039, 2043)
    (2044, 2048)
    (2049, 2053)
    (2054, 2058)
    (2059, 2063)
    (2064, 2068)
    (2069, 2073)
    (2074, 2078)
    (2079, 2083)
    (2084, 2088)
    (2089, 2093)
    (2094, 2098)
    (2099, 2103)
    (2104, 2108)
    (2109, 2113)
    (2114, 2118)
    (2119, 2123)
    (2124, 2128)
    (2129, 2133)
    (2134, 2138)
    (2139, 2143)
    (2144, 2148)
    (2149, 2153)
    (2154, 2158)
    (2159, 2163)
    (2164, 2168)
    (2169, 2173)
    (2174, 2178)
    (2179, 2183)
    (2184, 2188)
    (2189, 2193)
    (2194, 2198)
    (2199, 2203)
    (2204, 2208)
    (2209, 2213)
    (2214, 2218)
    (2219, 2223)
    (2224, 2228)
    (2229, 2233)
    (2234, 2238)
    (2239, 2243)
    (2244, 2248)
    (2249, 2253)
    (2254, 2258)
    4518

```python
plt.figure(figsize = (10,10))
plt.plot(x_interpolate[:2000],y_interpolate[:2000], 'k-', markersize = 0.5, label = 'Interpolacion')
plt.plot(range(0,2000),df_closed.iloc[:2000], 'r-', markersize = 0.5, label = 'Real')
plt.legend(loc = 'best')
plt.show()
```

```python
plt.figure(figsize = (10,10))
plt.plot(x_interpolate,y_interpolate, 'k-', markersize = 0.5, label = 'Interpolacion')
plt.plot(range(0,len(df_closed)),df_closed, 'r-', markersize = 0.5, label = 'Real')
plt.legend(loc = 'best')
plt.show()
```

```python
len(x_interpolate)
```

    2127

```python
tointclose.tail()
```

    Date
    2020-12-24    131.970001
    2020-12-28           NaN
    2020-12-29    134.869995
    2020-12-30    133.720001
    2020-12-31    132.690002
    Name: Close, dtype: float64

```python
len(x_interpolate)
```

    1585

```python
len(y_interpolate)
```

    1585

```python
dato_original
```

    15.061785697937012

```python
dato_interpolado
```

$\displaystyle 15.1923572540284$

```python
obj_interpolar.newton_interpolation(obj_interpolar.xx[1:5],obj_interpolar.y[1:5],obj_interpolar.lista_x[0])
```

    15.19235725402832

```python
#1. Randomly construct data
import numpy as np
x=range (10)
y=np.random.randint (10, size=10)
#2. Draw the original image
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
#jupyter notebook
import scipy
from scipy.interpolate import splrep #with scipy library
plt.plot (x, y)
plt.show ()
#3. Draw a smooth curve
from scipy.interpolate import splrep
 #Interpolation method, 50 represents the number of interpolation,Number>= number of actual data,Generally speaking, the greater the number of differences,The smoother the curve
x_new=np.linspace (min (x), max (x), 50)
y_smooth=splrep (x, y, x_new)
plt.plot (x_new, y_smooth)
plt.show ()
```

```python

```


```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('classic')
%matplotlib inline
```

# Discussion: Week 5

## Exercise: More Business Cycle Data

The file `business_cycle_data_actual_trend.csv`, available at https://github.com/letsgoexploring/econ126/raw/master/Data/Csv/business_cycle_data_actual_trend.csv, contains actual and trend data for real GDP per capita, real consumption per capita, real investment per capita, real physical capital per capita, TFP,  hours per capita, real M2 per capita, the rate of PCE (personal consumption expenditures) inflation, the three month T-bill rate, and the unemployment rate at quarterly frequency. The GDP, consumption, investment, capital, and M2 data are in terms of 2012 dollars. Hours is measured as an index with the value in October 2012 set to 100. PCE inflation is measured at the percent change from one year prior. PCE inflation, unemployment, and the T-bill rate are expressed in units of percent.

In this Notebook, you will replicate the work from class 9 but for the following quantities:
* Real GDP per capita
* 3-month T-Bill rate
* PCE inflation rate
* Unemployment rate

Refer to the Notebook from Class 9 for reference: https://github.com/letsgoexploring/econ126/blob/master/Lecture%20Notebooks/Econ126_Class_09.ipynb

## Part (a): Preliminaries

```python
# Read business_cycle_data_actual_trend.csv into a Pandas DataFrame with the first column set as the index and parse_dates=True
df = pd.read_csv('https://github.com/letsgoexploring/econ126/raw/master/Data/Csv/business_cycle_data_actual_trend.csv',index_col=0,parse_dates=True)

# Print the last five rows of the data
df.tail()
```

      gdp
      gdp_trend
      consumption
      consumption_trend
      investment
      investment_trend
      hours
      hours_trend
      capital
      capital_trend
      tfp
      tfp_trend
      real_m2
      real_m2_trend
      t_bill_3mo
      t_bill_3mo_trend
      pce_inflation
      pce_inflation_trend
      unemployment
      unemployment_trend

      2019-07-01
      73.783132
      72.272855
      50.165309
      49.019365
      12.878614
      12.525037
      105.344295
      102.515873
      79.687704
      79.430858
      27.411780
      27.360814
      0.000051
      0.000053
      0.019800
      0.014278
      0.039688
      0.018943
      0.036000
      0.052215

      2019-10-01
      74.049483
      72.347117
      50.254751
      49.058110
      12.709561
      12.519089
      105.428767
      102.221217
      80.003596
      79.790461
      27.458357
      27.396872
      0.000052
      0.000054
      0.015767
      0.014497
      0.040008
      0.015080
      0.036000
      0.053943

      2020-01-01
      73.222987
      72.412037
      49.397299
      49.090095
      12.483490
      12.510535
      103.941972
      101.906176
      80.566022
      80.151695
      27.336596
      27.433124
      0.000053
      0.000055
      0.011100
      0.014671
      0.018833
      0.011056
      0.038000
      0.055803

      2020-04-01
      66.535376
      72.471686
      44.643027
      49.118421
      10.664014
      12.500674
      90.210557
      101.579674
      80.802493
      80.514333
      27.208270
      27.469616
      0.000060
      0.000055
      0.001433
      0.014820
      -0.096568
      0.006943
      0.130667
      0.057744

      2020-07-01
      71.371904
      72.530653
      48.552336
      49.146390
      12.434136
      12.490785
      97.421248
      101.251776
      80.549066
      80.878406
      27.793644
      27.506336
      0.000062
      0.000056
      0.001133
      0.014960
      -0.016645
      0.002819
      0.088000
      0.059703

```python
# CELL PROVIDED
# Construct a 2x2 grid of plots of GDP, consumption, t_bill_3mo, unemployment, and pce_inflation. Multiply
# t_bill_3mo, unemployment, and pce_inflation by 100 inside the plot command to plot in units of percent.
base_year = '2012'
fig = plt.figure(figsize=(12,8))

ax1 = fig.add_subplot(2,2,1)
ax1.plot(df.gdp,'-',lw=3,alpha = 0.7)
ax1.grid()
ax1.set_title('GDP per capita')
ax1.set_ylabel('Thousands of '+base_year+' dollars')

ax2 = fig.add_subplot(2,2,2)
ax2.plot(df.t_bill_3mo*100,'-',lw=3,alpha = 0.7)
ax2.grid()
ax2.set_title('3-month T-Bill mate')
ax2.set_ylabel('Thousands of '+base_year+' dollars')

ax3 = fig.add_subplot(2,2,3)
ax3.plot(df.unemployment*100,'-',lw=3,alpha = 0.7)
ax3.grid()
ax3.set_title('Unemployment rate')
ax3.set_ylabel('Thousands of '+base_year+' dollars')

ax4 = fig.add_subplot(2,2,4)
ax4.plot(df.pce_inflation*100,'-',lw=3,alpha = 0.7)
ax4.grid()
ax4.set_title('PCE inflation')
ax4.set_ylabel('Percent')

fig.tight_layout()
```

## Part (b): Cycles and Trends

Recalle: A time series $X_t$ can be decomposed into a trend component $X_t^{trend}$ and a cyclical component $X_t^{cycle}$ such that:

\begin{align}
X_t & = X_t^{trend} + X_t^{cycle}. \tag{1}
\end{align}

In equation (1), $X_t^{trend}$ is the long-run value about which $X_t$ fluctuates. $X^{cycle}_t$ is the amount by which $X_t$ excedes its trend.

Often times, it's useful to express the cyclical component of a time series as the difference between the (natural) log of the series and the log of the trend:

\begin{align}
\hat{x}_t & = \log\left(X_t\right) - \log\left(X_t^{trend}\right) \approx\frac{X_t-X_t^{trend}}{X_t^{trend}}
\end{align}

The log-deviation from trend is approximately equal to the percent deviation of the series from trend (divided by 100).

### GDP

```python
# CELL PROVIDED
# Construct a plot of real GDP with its trend with:
#    1. Actual line: blue with lw=1, alpha=0.7, label = 'actual'
#    2. Trend line:  red with lw=3, alpha=0.7, label = 'trend'
#    3. A legend in an appropriate place
plt.plot(df.gdp,'-',lw=1,alpha = 0.7,label='actual')
plt.plot(df.gdp_trend,'r-',lw=3,alpha = 0.7,label='trend')
plt.grid()
plt.ylabel('Thousands of '+base_year+' dollars per person')
plt.title('GDP per capita')
plt.legend(loc='lower right',ncol=2)
```

```python
# CELL PROVIDED
# Create a new column called gdp_cycle equal to the log difference between actual GDP and trend GDP:
df['gdp_cycle'] = np.log(df['gdp']) - np.log(df['gdp_trend'])

# Plot the log deviation of GDP from its trend (times 100)
plt.plot(df.gdp_cycle*100,'b-',lw=3,alpha = 0.7)
plt.ylabel('Percent')
plt.title('GDP: Percent deviation from trend')
plt.grid()
```

### 3-month T-bill rate

```python
# Construct a plot of the 3-month T-bill rate (times 100) with its trend with:
#    1. Actual line: blue with lw=1, alpha=0.7, label = 'actual'
#    2. Trend line:  red with lw=3, alpha=0.7, label = 'trend'
#    3. A legend in an appropriate place
plt.plot(df.t_bill_3mo*100,'-',lw=1,alpha = 0.7,label='actual')
plt.plot(df.t_bill_3mo_trend*100,'r-',lw=3,alpha = 0.7,label='trend')
plt.ylabel('Percent')
plt.title('3-month T-bill rate')
plt.legend(loc='upper right',ncol=2)
plt.grid()
```

```python
# Create a new column called t_bill_3mo_cycle equal to the DIFFERENCE (not log difference!) between actual
# 3-month T-bill rate and it's trend:
df['t_bill_3mo_cycle'] = df['t_bill_3mo'] - df['t_bill_3mo_trend']

# Plot the deviation of the 3-month T-bill rate from its trend (times 100)
plt.plot(df.t_bill_3mo_cycle*100,'b-',lw=3,alpha = 0.7,label='t-bill')
plt.plot(df.gdp_cycle*100,'r-',lw=1,alpha = 0.5,label='gdp')
plt.ylabel('Percent')
plt.title('3-month T-bill rate: Deviation from trend')
plt.legend(loc='lower right',ncol=2)
plt.grid()
```

### Unemployment rate

```python
# Construct a plot of the unemployment rate (times 100) with its trend with:
#    1. Actual line: blue with lw=1, alpha=0.7, label = 'actual'
#    2. Trend line:  red with lw=3, alpha=0.7, label = 'trend'
#    3. A legend in an appropriate place
plt.plot(df.unemployment*100,'-',lw=1,alpha = 0.7,label='actual')
plt.plot(df.unemployment_trend*100,'r-',lw=3,alpha = 0.7,label='trend')
plt.ylabel('Percent')
plt.title('Unemployment rate')
plt.legend(loc='upper right',ncol=2)
plt.grid()
```

```python
# Create a new column called unemployment_cycle equal to the DIFFERENCE (not log difference!) between actual
# unemployment and it's trend:
df['unemployment_cycle'] = df['unemployment'] - df['unemployment_trend']

# Plot the deviation of the unemployment rate from its trend (times 100)
plt.plot(df.unemployment_cycle*100,'b-',lw=3,alpha = 0.7,label='unemployment')
plt.plot(df.gdp_cycle*100,'r-',lw=1,alpha = 0.5,label='gdp')
plt.ylabel('Percent')
plt.title('Unemployment rate: Deviation from trend')
plt.legend(loc='lower right',ncol=2)
plt.grid()
```

### PCE Inflation

```python
# Construct a plot of the pce_inflation rate (times 100) with its trend with:
#    1. Actual line: blue with lw=1, alpha=0.7, label = 'actual'
#    2. Trend line:  red with lw=3, alpha=0.7, label = 'trend'
#    3. A legend in an appropriate place
plt.plot(df.pce_inflation*100,'-',lw=1,alpha = 0.7,label='actual')
plt.plot(df.pce_inflation_trend*100,'r-',lw=3,alpha = 0.7,label='trend')
plt.ylabel('Percent')
plt.title('PCE inflation rate')
plt.legend(loc='upper right',ncol=2)
plt.grid()
```

```python
# Create a new column called pce_inflation_cycle equal to the DIFFERENCE (not log difference!) between actual
# pce_inflation and it's trend:
df['pce_inflation_cycle'] = df['pce_inflation'] - df['pce_inflation_trend']

# Plot the deviation of the PCE inflation rate from its trend (times 100)
plt.plot(df.pce_inflation_cycle*100,'b-',lw=3,alpha = 0.7,label='inflation')
plt.plot(df.gdp_cycle*100,'r-',lw=1,alpha = 0.5,label='gdp')
plt.ylabel('Percent')
plt.title('PCE inflation rate: Deviation from trend')
plt.legend(loc='lower left',ncol=2)
plt.grid()
```

## Part (c): Statistics

```python
# Create a new variable called df_cycle that is a DataFrame with columns columns gdp_cycle, t_bill_3mo_cycle,
# pce_inflation_cycle, unemployment_cycle from df.
df_cycle = df[['gdp_cycle', 't_bill_3mo_cycle', 'pce_inflation_cycle', 'unemployment_cycle']]

# Print the first five rows of df_cycle
print(df_cycle.head())
```

                gdp_cycle  t_bill_3mo_cycle  pce_inflation_cycle  \
    1959-01-01   0.010128         -0.001898             0.010258
    1959-04-01   0.022773          0.000568             0.021152
    1959-07-01   0.013910          0.006169             0.021213
    1959-10-01   0.007594          0.013271             0.015073
    1960-01-01   0.016899          0.009906             0.000901

                unemployment_cycle
    1959-01-01            0.000541
    1959-04-01           -0.006929
    1959-07-01           -0.005399
    1959-10-01           -0.002199
    1960-01-01           -0.006988

```python
# Use the DataFrame method .mean() to find the average values of the gdp_cycle, t_bill_3mo_cycle,
# pce_inflation_cycle, unemployment_cycle columns
df_cycle.mean()
```

    gdp_cycle             -8.291703e-14
    t_bill_3mo_cycle      -2.597316e-15
    pce_inflation_cycle   -2.137151e-15
    unemployment_cycle    -1.785487e-15
    dtype: float64

```python
# Use the DataFrame method .std() to find the standard deviations of the gdp_cycle, t_bill_3mo_cycle,
# pce_inflation_cycle, unemployment_cycle columns
df_cycle.std()
```

    gdp_cycle              0.015511
    t_bill_3mo_cycle       0.011561
    pce_inflation_cycle    0.015042
    unemployment_cycle     0.009103
    dtype: float64

```python
# Use the DataFrame method .corr() to find the coeficients of correlation among the gdp_cycle, t_bill_3mo_cycle,
# pce_inflation_cycle, unemployment_cycle columns
df_cycle.corr()
```

      gdp_cycle
      t_bill_3mo_cycle
      pce_inflation_cycle
      unemployment_cycle

      gdp_cycle
      1.000000
      0.415906
      0.640850
      -0.858355

      t_bill_3mo_cycle
      0.415906
      1.000000
      0.266250
      -0.514210

      pce_inflation_cycle
      0.640850
      0.266250
      1.000000
      -0.554755

      unemployment_cycle
      -0.858355
      -0.514210
      -0.554755
      1.000000

**Questions**

1. Of the three quantities besides GDP in the columns of `df_cycle`, which varies the most over the business cycle?
2. Of the three quantities besides GDP in the columns of `df_cycle`, which varies the least over the business cycle?
3. Of the three quantities besides GDP in the columns of `df_cycle`, which is most correlated (in absolute value) with GDP over the business cycle?

**Answers**

1. The PCE inflation rate fluctuates the most over the business cycle.
2. The unemployment rate fluctuates the least over the business cycle.
3. The unemployment rate is the quantity that is most correlated with GDP over the cycle. Since the capital stock changes slowly over time, large fluctuations due primarily to large fluctuations in employment.

## Part (d): Bonus

Do the next cell for fun. You won't get extra credit, but do it if you want to and have time.

```python
# Plot the cyclical components of GDP, three month T-bill rate, PCE inflation rate, and the unemployment rate
# (all times 100) on the same set of axes
fig = plt.figure(figsize=(12,4))
ax = fig.add_subplot(1,1,1)
(df_cycle*100).plot(ax = ax,legend=False,lw=3,alpha=0.7)
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
ax.set_ylabel('Percent')
ax.set_title('Select US Business cycle data')
ax.grid()
```


```python
import numpy as np
import matplotlib.pyplot as plt
import plotutils as pu
import sympy
%matplotlib inline
```

```python
with plt.xkcd():
    fig, axes = plt.subplots(1, figsize=(4, 4))
    ticks = [1, 2, 3, 4]
    args = {
        'xlim': (-1, 4.5), 'ylim': (-1, 4.5),
        'xticks': ticks, 'yticks': ticks,
        'xticklabels': [1, 2, 3, 4],
        'yticklabels': [1, 2, 3, 4],
        'ticklength': 10,
        'tickdirection': 'out'
    }
    pu.setup_axes(axes, **args)
    pu.plot_rect(axes, (np.sqrt(3), np.sqrt(3)))
    pu.plot_rect(axes, (np.sqrt(12), np.sqrt(12)), 'b--')
    plt.plot(np.sqrt(3), np.sqrt(3), 'ko',)
    plt.plot(np.sqrt(12), np.sqrt(12), 'ko')
    plt.annotate('3', (1.90, np.sqrt(3)))
    plt.annotate('12', (3.7, np.sqrt(12)))
    plt.annotate('2 X SQRT(3) = SQRT(12)', (0.5, 4))
    plt.annotate('SQRT(3)', (0.1, 1.2))
    plt.annotate('SQRT(12)', (1.7, 2.9))
```

```python

```


# Import Packages

```python
%load_ext autoreload
%autoreload 2
```

```python
%matplotlib inline
```

    Bad key "text.kerning_factor" on line 4 in
    /Users/michaelnowotny/anaconda3/envs/continuous_time_mcmc/lib/python3.7/site-packages/matplotlib/mpl-data/stylelib/_classic_test_patch.mplstyle.
    You probably need to get an updated matplotlibrc file from
    https://github.com/matplotlib/matplotlib/blob/v3.1.3/matplotlibrc.template
    or from the matplotlib source distribution

```python
import matplotlib.pyplot as plt
import numpy as np
import os
import pandas as pd
import seaborn as sns
sns.set(color_codes=True)
import state_space as ss
import statsmodels.api as sm
import sympy as sym
import typing as tp
```

```python
from state_space import (
    SymbolicStateSpaceModelViaMaximumLikelihood,
    IndependentParameterTransformation,
    LambdaUnivariateTransformation,
    RectangularParameterTransformation)
```

```python
plt.rcParams["figure.figsize"] = (18,12)
```

```python
pd.set_option('display.max_rows', 250)
```

# Read Data

## Returns

```python
# spy_filename = os.path.join('data', 'GSPC_daily.csv')
spy_filename = os.path.join('data', 'SPY_daily.csv')
```

```python
df = pd.read_csv(spy_filename)
```

```python
df['Date'] = pd.to_datetime(df['Date'])
```

```python
df.sort_values('Date', inplace=True)
```

```python
df = df.dropna()
```

```python
df['Log_Return'] = np.log(df['Close']).diff()
```

```python
df.head()
```

      Date
      Open
      High
      Low
      Close
      Adj Close
      Volume
      Log_Return

      0
      1993-01-29
      43.96875
      43.96875
      43.75000
      43.93750
      26.583992
      1003200
      NaN

      1
      1993-02-01
      43.96875
      44.25000
      43.96875
      44.25000
      26.773048
      480500
      0.007087

      2
      1993-02-02
      44.21875
      44.37500
      44.12500
      44.34375
      26.829773
      201300
      0.002116

      3
      1993-02-03
      44.40625
      44.84375
      44.37500
      44.81250
      27.113388
      529400
      0.010515

      4
      1993-02-04
      44.96875
      45.09375
      44.46875
      45.00000
      27.226835
      531500
      0.004175

## Factor Data

```python
factor_filename = os.path.join('data', 'F-F_Research_Data_Factors_daily.CSV')
```

```python
factors \
    = pd.read_csv(factor_filename,
                  engine='python',
                  skiprows=5,
                  names=['Date', 'Mkt-RF', 'SMB', 'HML', 'RF'],
                  skipfooter=1)
factors['Date'] = pd.to_datetime(factors['Date'], format='%Y%m%d')
factors['RF'] *= 0.01
factors = factors.dropna()
```

## Merge Returns and Risk-Free Rate

```python
df = df.merge(factors.loc[:, ['Date', 'RF']], on='Date')
```

```python
df['Excess_Return'] = df['Log_Return'] - np.log(1.0 + df['RF'])
```

```python
df = df.dropna()
```

## Extract Time-Series

Equity returns

```python
# log_returns = np.log(df['Close']).diff().dropna().values
log_returns = np.log(df['Close']).diff().values
```

Risk-free Rate

```python
r = np.log(1.0 + (df['RF'].values))
```

Compute excess returns

```python
excess_returns = df['Excess_Return'].values
```

# Time-Series Model

## Stochastic Process

Assume that the (unobserved) equity premium $\mu_t$ follwos the autoregressive process

$\mu_{t+1} = \alpha + \beta \mu_t + \eta_{t+1}$,

where $\alpha, \beta \in \mathbb{R}$ and $\{\eta\}_{t=1}^T$ is a sequence of i.i.d. normal shocks with mean zero and variance $\sigma_{\eta}^2$.

The (observed) log return $r_t$ is generated via

$r_t = r_{f, t} + \mu_t + \epsilon_t$,

where $r_{f, t}$ is the risk-free rate at time $t$ and $\{\epsilon\}_{t=1}^T$ is a sequence of i.i.d. normal shocks with mean zero and variance $\sigma_{\epsilon}^2$.

Subtracting the risk-free rate, we obtain the following process for the log excess return:

$x_t = r_t - r_{f, t} = \mu_t + \epsilon_t$.

## Linear State Space Representation and Kalman Filter

See https://www.statsmodels.org/stable/statespace.html

The time-varying equity premium model is a linear state space model of the form

$$
\begin{align*}
s_{t+1} & = T_t s_t + c_t + R_t \eta_{t+1} \text{ (state equation)} \\
y_t & = Z_t s_t + d_t + \epsilon_t \text{ (observation equation)},
\end{align*}
$$
where
$$
\begin{align*}
\epsilon_t & \sim N(0, H_t) \\
\eta_t & \sim N(0, Q_t).
\end{align*}
$$
In this time-varying equity premium model, the observation $y_t$ is the log return $x_t$ and the state $\alpha_t$ is the equity premium $\mu_t$. The coefficients specific to this model are given by
$$
\begin{align*}
Z_t & = 1 \\
R_t & = 1 \\
T_t & = \beta_{\mu} \\
H_t & = \sigma^2 \\
Q_t & = \sigma_{\mu}^2 \\
c_t & = \alpha_{\mu}
\end{align*}
$$
All other coefficients are zero and we obtain
$$
\begin{align*}
\mu_{t+1} & = \beta_{\mu} \mu_t + \alpha_{\mu} + \eta_t \text{ (state equation)} \\
x_t & = \mu_t + \epsilon_t \text{ (observation equation)},
\end{align*}
$$

## Representing Coefficients in SymPy and Building the Symbolic State Space Model

Construct parameter symbols (this is used to teell  State Space which parameters are to be estimated via MLE)

```python
parameter_symbols = \
    sym.symbols(('alpha.mu',
                 'beta.mu',
                 'sigma',
                 'sigma.mu'))

alpha_mu, beta_mu, sigma, sigma_mu = parameter_symbols
```

Construct coefficient vectors and matrices

```python
H = sym.Matrix([sigma**2])
Q = sym.Matrix([sigma_mu**2])
c = sym.Matrix([alpha_mu])
T = sym.Matrix([beta_mu])
Z = sym.Matrix.ones(rows=1, cols=1)
R = sym.Matrix.ones(rows=1, cols=1)
```

Define the state vector

```python
state_vector_symbols = tuple([sym.Symbol('mu')])
```

Map data symbols (return) to data arrays (NumPy or Pandas series)

```python
y = sym.Symbol('y')
data_symbol_to_data_map = {y: excess_returns}
```

Set starting values for the numerical optimization

```python
parameter_symbols_to_start_parameters_map = \
    {alpha_mu: 0.0,
     beta_mu: 0.0,
     sigma: 0.001,
     sigma_mu: 0.001}
```

Define transformations so that the numerical optimizer can operate in an unconstrained parameter space

Option A: Using individual univariate transformation functions

```python
squared_univariate_transform = \
    LambdaUnivariateTransformation(
        transform_function=lambda x: x**2,
        untransform_function=lambda x: x**0.5)

parameter_transformation = \
    IndependentParameterTransformation(
        parameter_symbols=parameter_symbols,
        parameter_symbol_to_univariate_transformation_map
        ={sigma: squared_univariate_transform,
          sigma_mu: squared_univariate_transform})
```

Option B: Using lower and upper bounds on individual parameters

```python
# parameter_transformation = \
#     RectangularParameterTransformation(parameter_symbols=parameter_symbols,
#                                        parameter_symbol_to_bounds_map={sigma: (0, np.inf),
#                                                                        sigma_mu: (0, np.inf)})
```

Compile the symbolic definition to the statsmodels format for numeric MLE

```python
time_varying_equity_premium_model = \
    SymbolicStateSpaceModelViaMaximumLikelihood(parameter_symbols=parameter_symbols,
                                                state_vector_symbols=state_vector_symbols,
                                                observation_vector_symbols=tuple([y]),
                                                data_symbol_to_data_map=data_symbol_to_data_map,
                                                parameter_symbols_to_start_parameters_map
                                                =parameter_symbols_to_start_parameters_map,
                                                parameter_transformation=parameter_transformation,
                                                design_matrix=Z,
                                                selection_matrix=R,
                                                transition_matrix=T,
                                                state_intercept_vector=c,
                                                state_covariance_matrix=Q,
                                                observation_covariance_matrix=H)
```

# Estimation

```python
result = time_varying_equity_premium_model.fit(disp=False)
print(result.summary())
```

                                            Statespace Model Results
    =======================================================================================================
    Dep. Variable:                                               y   No. Observations:                 6738
    Model:             SymbolicStateSpaceModelViaMaximumLikelihood   Log Likelihood               20553.314
    Date:                                         Fri, 16 Apr 2021   AIC                         -41098.627
    Time:                                                 21:09:07   BIC                         -41071.366
    Sample:                                                      0   HQIC                        -41089.215
                                                            - 6738
    Covariance Type:                                           opg
    ==============================================================================
                     coef    std err          z      P>|z|      [0.025      0.975]
    ------------------------------------------------------------------------------
    alpha.mu       0.0002      0.000      1.270      0.204      -0.000       0.000
    beta.mu       -0.0627      0.094     -0.664      0.506      -0.248       0.122
    sigma          0.0026      0.036      0.073      0.942      -0.068       0.073
    sigma.mu       0.0111      0.008      1.323      0.186      -0.005       0.028
    ===================================================================================
    Ljung-Box (Q):                      139.18   Jarque-Bera (JB):             28859.62
    Prob(Q):                              0.00   Prob(JB):                         0.00
    Heteroskedasticity (H):               0.68   Skew:                            -0.21
    Prob(H) (two-sided):                  0.00   Kurtosis:                        13.13
    ===================================================================================

    Warnings:
    [1] Covariance matrix calculated using the outer product of gradients (complex-step).

    /Users/michaelnowotny/anaconda3/envs/continuous_time_mcmc/lib/python3.7/site-packages/statsmodels/base/model.py:568: ConvergenceWarning: Maximum Likelihood optimization failed to converge. Check mle_retvals
      "Check mle_retvals", ConvergenceWarning)

Filtered equity premium

```python
plt.plot(df['Date'], result.filtered_state[0, :]);
```

Smoothed equity premium

```python
plt.plot(df['Date'], result.smoothed_state[0, :]);
```

```python

```

notebooks/Time-Variation in the Equity Premium.ipynb


```python
%matplotlib inline

import numpy as np
import pylab as pl
import math
from sympy import *
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D
```

```python
from NN import NN
```

コブ・ダクラス型生産関数と課題文で例に出された関数を用いる。

いずれも定義域は0≤x≤1である。

コブ・ダグラス型生産関数は以下の通りである。

z = x_1**0.5*x_2*0.5

```python
def example1(x_1, x_2):
    z = x_1**0.5*x_2*0.5
    return z

fig = pl.figure()
ax = Axes3D(fig)

X = np.arange(0, 1, 0.1)
Y = np.arange(0, 1, 0.1)

X, Y = np.meshgrid(X, Y)
Z = example1(X, Y)

ax.plot_surface(X, Y, Z, rstride=1, cstride=1)

pl.show()
```

課題の例で使われた関数は以下の通りである。

z = (1+np.sin(4*math.pi*x_1))*x_2*1/2

```python
def example2(x_1, x_2):
    z = (1+np.sin(4*math.pi*x_1))*x_2*1/2
    return z

fig = pl.figure()
ax = Axes3D(fig)

X = np.arange(0, 1, 0.1)
Y = np.arange(0, 1, 0.1)

X, Y = np.meshgrid(X, Y)
Z = example2(X, Y)

ax.plot_surface(X, Y, Z, rstride=1, cstride=1)
ax.set_zlim(-1, 1)

pl.show()
```

NNのクラスはすでにNN.pyからimportしてある。

```python
nn = NN()
```

以下に使い方を説明する。

初めに、このコブ・ダグラス型生産関数を用いる。

```python
x_1 = Symbol('x_1')
x_2 = Symbol('x_2')
f = x_1**0.5*x_2*0.5
```

入力層、中間層、出力層を作る関数を実行する。引数には層の数を用いる。

```python
nn.set_input_layer(2)
```

    array([ 0.,  0.])

```python
nn.set_hidden_layer(2)
```

    (array([ 0.,  0.]), array([ 0.,  0.]))

```python
nn.set_output_layer(2)
```

    (array([ 0.,  0.]), array([ 0.,  0.]), array([ 0.,  0.]))

nn.set_hidden_layer()は同時にシグモイド関数で変換する前の中間層も作る。

set_output_layer()は同時にシグモイド関数で変換する前の出力層、さらに教師データを入れる配列も作る。

nn.setup()で入力層ー中間層、中間層ー出力層間の重みを入れる配列を作成する。

nn.initialize()で重みを初期化する。重みは-1/√d ≤ w ≤ 1/√d (dは入力層及び中間層の数)の範囲で一様分布から決定される。

```python
nn.setup()
nn.initialize()
```

nn.supervised_function(f, idata)は教師データを作成する。引数は関数とサンプルデータをとる。

```python
idata = [1, 2]
```

```python
nn.supervised_function(f, idata)
```

nn.simulate(N, eta)は引数に更新回数と学習率をとる。普通はN=1で行うべきかもしれないが、工夫として作成してみた。N回学習した後に出力層を返す。

```python
nn.simulate(1, 0.1)
```

    array([ 0.53414091,  0.4764263 ])

nn.calculation()は学習せずに入力層から出力層の計算を行う。nn.simulate()内にも用いられている。

次に実際に学習を行う。サンプルデータは、

```python
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)
print X, Y
```

    [ 0.   0.2  0.4  0.6  0.8] [ 0.   0.2  0.4  0.6  0.8]

の組み合わせである。

```python
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)

a = np.array([])
b = np.array([])
c = np.array([])

nn = NN()
nn.set_network()

for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)

for i in range(100):
        l = np.random.choice([i for i in range(len(a))])
        m = nn.main(1, f, [a[l], b[l]], 0.5)

for x in X:
    for y in Y:
        idata = [x, y]
        c = np.append(c, nn.realize(f, idata))
```

```python
a
```

    array([ 0. ,  0. ,  0. ,  0. ,  0. ,  0.2,  0.2,  0.2,  0.2,  0.2,  0.4,
            0.4,  0.4,  0.4,  0.4,  0.6,  0.6,  0.6,  0.6,  0.6,  0.8,  0.8,
            0.8,  0.8,  0.8])

```python
b
```

    array([ 0. ,  0.2,  0.4,  0.6,  0.8,  0. ,  0.2,  0.4,  0.6,  0.8,  0. ,
            0.2,  0.4,  0.6,  0.8,  0. ,  0.2,  0.4,  0.6,  0.8,  0. ,  0.2,
            0.4,  0.6,  0.8])

```python
c
```

    array([ 0.62110062,  0.63653367,  0.65111218,  0.66436166,  0.67598904,
            0.63172135,  0.64662299,  0.66032343,  0.67247157,  0.68290415,
            0.64201944,  0.65613827,  0.66879249,  0.67976226,  0.68900194,
            0.65181452,  0.66495474,  0.67645812,  0.68622916,  0.69431931,
            0.66096283,  0.67299149,  0.68329938,  0.69189792,  0.69891149])

例えば(0, 0)を入力すると0.52328635を返している（つまりa[0]とb[0]を入力して、c[0]の値を返している）。

ここでは交差検定は用いていない。

```python
fig = pl.figure()
ax = Axes3D(fig)

ax.scatter(a, b, c)

pl.show()
```

確率的勾配降下法を100回繰り返したが見た感じから近づいている。回数を10000回に増やしてみる。

```python
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)

a = np.array([])
b = np.array([])
c = np.array([])

nn = NN()
nn.set_network()

for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)

for i in range(10000):
        l = np.random.choice([i for i in range(len(a))])
        m = nn.main(1, f, [a[l], b[l]], 0.5)

for x in X:
    for y in Y:
        idata = [x, y]
        c = np.append(c, nn.realize(f, idata))
```

```python
fig = pl.figure()
ax = Axes3D(fig)

ax.scatter(a, b, c)

pl.show()
```

見た感じ随分近づいているように見える。

同様のことを課題の例で使われた関数でも試してみる。

```python
x_1 = Symbol('x_1')
x_2 = Symbol('x_2')
f = (1+sin(4*math.pi*x_1))*x_2*1/2
```

```python
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)

a = np.array([])
b = np.array([])
c = np.array([])

nn = NN()
nn.set_network()

for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)

for i in range(1000):
        l = np.random.choice([i for i in range(len(a))])
        m = nn.main(1, f, [a[l], b[l]], 0.5)

for x in X:
    for y in Y:
        idata = [x, y]
        c = np.append(c, nn.realize(f, idata))
```

```python
fig = pl.figure()
ax = Axes3D(fig)

ax.scatter(a, b, c)

pl.show()
```

上手く近似できないので中間層の数を変えてみる。5層にしてみる。

```python
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)

a = np.array([])
b = np.array([])
c = np.array([])

nn = NN()
nn.set_network(h=5)

for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)

for i in range(1000):
        l = np.random.choice([i for i in range(len(a))])
        m = nn.main(1, f, [a[l], b[l]], 0.5)

for x in X:
    for y in Y:
        idata = [x, y]
        c = np.append(c, nn.realize(f, idata))
```

```python
fig = pl.figure()
ax = Axes3D(fig)

ax.scatter(a, b, c)

pl.show()
```

目標と比べると大きく異なる。

サンプル数を、

```python
X = np.arange(-1, 1, 0.1)
Y = np.arange(-1, 1, 0.1)
print X, Y
```

で取り、学習の際にランダムに一個選ばれたサンプルを何十回も学習させてみた。

```python
fig = pl.figure()
ax = Axes3D(fig)

f = (1+sin(4*math.pi*x_1))*x_2*1/2

X = np.arange(-1, 1, 0.1)
Y = np.arange(-1, 1, 0.1)

a = np.array([])
b = np.array([])
c = np.array([])

fig = plt.figure()

nn = NN()
nn.set_network()

for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
        c = np.append(c, nn.main2(50, f, [x, y], 0.8))

for i in range(50):
    l = np.random.choice([i for i in range(len(a))])
    m = nn.main2(20, f, [a[l], b[l]], 0.5)
    c[l] = m

a = np.array([])
b = np.array([])
c = np.array([])

for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)
        c = np.append(c, nn.realize(f, [x, y]))

ax.scatter(a, b, c)
ax.set_zlim(0, 1)

pl.show()
```

本来ならば下のような形になるべきであるので上手くいっているとは言い難い。

```python
def example2(x_1, x_2):
    z = (1+np.sin(4*math.pi*x_1))*x_2*1/2
    return z

fig = pl.figure()
ax = Axes3D(fig)

X = np.arange(-1, 1, 0.1)
Y = np.arange(-1, 1, 0.1)

X, Y = np.meshgrid(X, Y)
Z = example2(X, Y)

ax.plot_surface(X, Y, Z, rstride=1, cstride=1)
ax.set_zlim(-1, 1)

pl.show()
```

同じ方法でコブ・ダグラス型生産関数を学習させた様子をアニメーションにしてみた。この方法が何の意味を持つかは分からないが学習はまあまよくできていた。

mp4ファイルで添付した。

[考察]ここにはコードを書けなかったが、サンプル数が多くなった時は、ミニバッチ式の学習を試すべきだと思った。

最後に交差検定を行う。

初めに学習回数が極めて少ないNNである。

```python
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)

a = np.array([])
b = np.array([])
c = np.array([])

for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)

evl = np.array([])

for i in range(len(a)):
    nn = NN()
    nn.set_network()
    for j in range(1):
        l = np.random.choice([i for i in range(len(a))])
        if l != i:
            m = nn.main(1, f, [a[l], b[l]], 0.5)
    idata = [a[i], b[i]]
    est = nn.realize(f, idata)
    evl = np.append(evl, math.fabs(est - nn.supervised_data))
```

```python
np.average(evl)
```

    0.31083460645411465

次に十分大きく(1000回に)してみる。

```python
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)

a = np.array([])
b = np.array([])
c = np.array([])

nn = NN()
nn.set_network(h=7)

for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)

evl = np.array([])

for i in range(len(a)):
    for j in range(10000):
        nn = NN()
        nn.set_network()
        l = np.random.choice([i for i in range(len(a))])
        if l != i:
            m = nn.main(1, f, [a[l], b[l]], 0.5)
    idata = [a[i], b[i]]
    evl = np.append(evl, math.fabs(nn.realize(f, idata) - nn.supervised_data))
```

```python
evl
```

    array([ 0.17422959,  0.37774617,  0.29845184,  0.4247869 ,  0.42139651,
            0.28095943,  0.48263009,  0.12094186,  0.35090278,  0.07039276,
            0.60270475,  0.38029955,  0.47076667,  0.27789737,  0.26027828,
            0.61710335,  0.51095281,  0.29832648,  0.51007664,  0.53242457,
            0.50885681,  0.48114824,  0.53944263,  0.36336567,  0.37925241])

```python
np.average(evl)
```

    0.28091957975738507

誤差の平均であるので小さい方よい。
学習回数を大幅に増やした結果、精度が上がった。

次に回数を100回にして、中間層の数を2と5で精度を比較する。

```python
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)

a = np.array([])
b = np.array([])
c = np.array([])

for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)

evl = np.array([])

for i in range(len(a)):
    for j in range(100):
        nn = NN()
        nn.set_network()
        l = np.random.choice([i for i in range(len(a))])
        if l != i:
            m = nn.main(1, f, [a[l], b[l]], 0.5)
    idata = [a[i], b[i]]
    est = nn.realize(f, idata)
    evl = np.append(evl, math.fabs(est - nn.supervised_data))
```

```python
np.average(evl)
```

    0.3090473511199906

```python
X = np.arange(0, 1, 0.2)
Y = np.arange(0, 1, 0.2)

a = np.array([])
b = np.array([])
c = np.array([])

for x in X:
    for y in Y:
        a = np.append(a, x)
        b = np.append(b, y)

evl = np.array([])

for i in range(len(a)):
    for j in range(100):
        nn = NN()
        nn.set_network(h=5)
        l = np.random.choice([i for i in range(len(a))])
        if l != i:
            m = nn.main(1, f, [a[l], b[l]], 0.5)
    idata = [a[i], b[i]]
    est = nn.realize(f, idata)
    evl = np.append(evl, math.fabs(est - nn.supervised_data))
```

```python
np.average(evl)
```

    0.28516243998794422

コブ・ダグラス型の関数が比較的単純であるから、意味はないかと思ったが、精度はかなり良くなった。

```python

```