{ "cells": [ { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import datetime\n", "from dateutil.relativedelta import relativedelta\n", "import holidays\n", "import matplotlib.pyplot as plt\n", "from scipy.interpolate import CubicSpline\n", "from scipy.stats import norm" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "class USCalendar:\n", " def __init__(self):\n", " self.country='US'\n", " def check_if_date_is_country_holiday(self,date):\n", " return (date in holidays.US(years=date.year))\n", " def check_if_date_is_weekend(self,date):\n", " return (date.weekday()>=5)\n", " def make_date_not_holiday(self,date):\n", " while (self.check_if_date_is_country_holiday(date) or self.check_if_date_is_weekend(date)):\n", " date+=datetime.timedelta(days=1)\n", " return date\n", " def add(self,date,days=0, months=0, years=0,MakeNotHolidayFirst=True,MakeNotHolidayLast=True):\n", " #print(date, days, months, years)\n", " if (MakeNotHolidayFirst):\n", " date=self.make_date_not_holiday(date)\n", " date+=relativedelta(years=years,months=months,days=days)\n", " #print(\"new date=\",date)\n", " if (MakeNotHolidayLast):\n", " date=self.make_date_not_holiday(date)\n", " return date\n", " \n", " \n", " \n", "class RatesCurve:\n", " def __init__(self,name,DayCountConvention,Interpolation,now):\n", " self.name=name\n", " self.DayCountConvention=DayCountConvention\n", " self.Interpolation=Interpolation\n", " self.now=now\n", " self.Dates=[now]\n", " self.DiscFactors={self.Dates[0]:1.0}\n", " def add_date_and_DiscFactor(self,date, DiscFactor):\n", " if (date < self.Dates[-1]):\n", " raise RuntimeError('You may add new DiscFactors only to the very end of the curve!',date,'is not greater than',self.Dates[-1])\n", " else:\n", " self.Dates.append(date)\n", " self.DiscFactors[date]=DiscFactor\n", " def get_disc_factor_now_T(self,date):\n", " if date < self.now:\n", " raise RuntimeError('Date',date,' is in the past!')\n", " elif date > self.Dates[-1]:\n", " raise RuntimeError('Date', date,' is greater than the last date of the constructed curve!')\n", " elif date==self.Dates[0]:\n", " return self.DiscFactors[self.Dates[0]]\n", " else:\n", " i=0\n", " while (date > self.Dates[i]):\n", " i+=1\n", " ti=self.Dates[i]\n", " tim1=self.Dates[i-1]\n", " #print(tim1,ti,self.DiscFactors[tim1],self.DiscFactors[ti])\n", " ln_DFti=np.log(self.DiscFactors[ti])\n", " ln_DFtim1=np.log(self.DiscFactors[tim1])\n", " x=(date-self.now).days/360\n", " xp=[(tim1-self.now).days/360,(ti-self.now).days/360]\n", " fp=[ln_DFtim1,ln_DFti]\n", " #print(x,xp,fp, np.exp(np.interp(x,xp,fp)))\n", " return np.exp(np.interp(x,xp,fp))\n", " def get_disc_factor_t_T(self,date_t, date_T):\n", " return self.get_disc_factor_now_T(date_T)/self.get_disc_factor_now_T(date_t)\n", " \n", " \n", "class InterestRatesSwapProduct:\n", " #даты платежей - уже должны быть в BD-календаре\n", " def __init__(self, now, name,\n", " Leg1IndexIdentifier, #инфо\n", " Leg1Tenor, #(days,months,years)\n", " Leg1StartDateLagInDays, #timedelta\n", " Leg1PaymentLagInDays, #инфо\n", " Leg1FloatingRateSpread, \n", " Leg1FixedRate, \n", " Leg1DayCountConvention, #инфо\n", " Leg1IsFixed,\n", " Leg1Frequency,\n", " Leg2IndexIdentifier, #инфо\n", " Leg2Tenor,\n", " Leg2StartDateLagInDays,\n", " Leg2PaymentLagInDays, #инфо\n", " Leg2FloatingRateSpread, \n", " Leg2FixedRate, \n", " Leg2DayCountConvention,\n", " Leg2IsFixed,\n", " Leg2Frequency): #инфо\n", " self.now=now\n", " self.name=name\n", " self.Leg1Frequency=Leg1Frequency\n", " MyCalendar=USCalendar()\n", " now=MyCalendar.make_date_not_holiday(now)\n", " \n", " tek_period_start_date=MyCalendar.add(now, days=Leg1StartDateLagInDays)\n", " Leg1AbsEndDate=MyCalendar.add(tek_period_start_date, days=Leg1Tenor[0],months=Leg1Tenor[1],years=Leg1Tenor[2])\n", " #print(\"f\",Leg1AbsEndDate)\n", " self.Leg1PeriodStartDates=[]\n", " if (self.Leg1Frequency=='1Y'):\n", " while (len(self.Leg1PeriodStartDates)==0 or MyCalendar.add(tek_period_start_date,years=1,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)<=Leg1AbsEndDate):\n", " #print(\"g\",tek_period_start_date)\n", " self.Leg1PeriodStartDates.append(MyCalendar.make_date_not_holiday(tek_period_start_date))\n", " tek_period_start_date=MyCalendar.add(tek_period_start_date,years=1,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)\n", " elif (self.Leg1Frequency=='3M'):\n", " while (len(self.Leg1PeriodStartDates)==0 or MyCalendar.add(tek_period_start_date,months=3,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)<=Leg1AbsEndDate):\n", " #print(\"g\",tek_period_start_date)\n", " self.Leg1PeriodStartDates.append(MyCalendar.make_date_not_holiday(tek_period_start_date))\n", " tek_period_start_date=MyCalendar.add(tek_period_start_date,months=3,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)\n", " elif (self.Leg1Frequency=='6M'):\n", " while (len(self.Leg1PeriodStartDates)==0 or MyCalendar.add(tek_period_start_date,months=6,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)<=Leg1AbsEndDate):\n", " #print(\"g\",tek_period_start_date)\n", " self.Leg1PeriodStartDates.append(MyCalendar.make_date_not_holiday(tek_period_start_date))\n", " tek_period_start_date=MyCalendar.add(tek_period_start_date,months=6,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)\n", " \n", " tek_period_end_date= Leg1AbsEndDate\n", " #print(\"h\",tek_period_end_date)\n", " self.Leg1PeriodEndDates=[]\n", " if (self.Leg1Frequency=='1Y'):\n", " while (len(self.Leg1PeriodEndDates)==0 or MyCalendar.add(tek_period_end_date,years=-1,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)>=MyCalendar.add(now, days=Leg1StartDateLagInDays)):\n", " #print(\"i\",tek_period_end_date)\n", " #print(MyCalendar.add(tek_period_end_date,datetime.timedelta(days=-360)),MyCalendar.add(now, Leg1StartDateLagInDays))\n", " self.Leg1PeriodEndDates.append(MyCalendar.make_date_not_holiday(tek_period_end_date))\n", " tek_period_end_date=MyCalendar.add(tek_period_end_date,years=-1,MakeNotHolidayFirst=False,MakeNotHolidayLast=False) \n", " elif (self.Leg1Frequency=='3M'):\n", " while (len(self.Leg1PeriodEndDates)==0 or MyCalendar.add(tek_period_end_date,months=-3,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)>=MyCalendar.add(now, days=Leg1StartDateLagInDays)):\n", " #print(\"i\",tek_period_end_date)\n", " #print(MyCalendar.add(tek_period_end_date,datetime.timedelta(days=-360)),MyCalendar.add(now, Leg1StartDateLagInDays))\n", " self.Leg1PeriodEndDates.append(MyCalendar.make_date_not_holiday(tek_period_end_date))\n", " tek_period_end_date=MyCalendar.add(tek_period_end_date,months=-3,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)\n", " elif (self.Leg1Frequency=='6M'):\n", " while (len(self.Leg1PeriodEndDates)==0 or MyCalendar.add(tek_period_end_date,months=-6,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)>=MyCalendar.add(now, days=Leg1StartDateLagInDays)):\n", " #print(\"i\",tek_period_end_date)\n", " #print(MyCalendar.add(tek_period_end_date,datetime.timedelta(days=-360)),MyCalendar.add(now, Leg1StartDateLagInDays))\n", " self.Leg1PeriodEndDates.append(MyCalendar.make_date_not_holiday(tek_period_end_date))\n", " tek_period_end_date=MyCalendar.add(tek_period_end_date,months=-6,MakeNotHolidayFirst=False,MakeNotHolidayLast=False) \n", " \n", " self.Leg1PeriodEndDates=self.Leg1PeriodEndDates[::-1] \n", "\n", " self.Leg1PaymentDates=list(map(lambda x: MyCalendar.add(x,days=Leg1PaymentLagInDays),self.Leg1PeriodEndDates))\n", " self.Leg1Tenor=Leg1Tenor\n", " self.Leg1StartDateLagInDays=Leg1StartDateLagInDays\n", " self.Leg1PaymentLagInDays=Leg1PaymentLagInDays\n", " self.Leg1IndexIdentifier=Leg1IndexIdentifier\n", " self.Leg1FloatingRateSpread=Leg1FloatingRateSpread\n", " self.Leg1FixedRate=Leg1FixedRate\n", " self.Leg1DayCountConvention=Leg1DayCountConvention\n", " self.Leg1IsFixed=Leg1IsFixed\n", " \n", " \n", " self.Leg2Frequency=Leg2Frequency\n", " tek_period_start_date=MyCalendar.add(now, days=Leg2StartDateLagInDays)\n", " Leg2AbsEndDate=MyCalendar.add(tek_period_start_date, days=Leg2Tenor[0],months=Leg2Tenor[1],years=Leg2Tenor[2])\n", " #print(\"f\",Leg1AbsEndDate)\n", " self.Leg2PeriodStartDates=[]\n", " if (self.Leg2Frequency=='1Y'):\n", " while (len(self.Leg2PeriodStartDates)==0 or MyCalendar.add(tek_period_start_date,years=1,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)<=Leg2AbsEndDate):\n", " #print(\"g\",tek_period_start_date)\n", " self.Leg2PeriodStartDates.append(MyCalendar.make_date_not_holiday(tek_period_start_date))\n", " tek_period_start_date=MyCalendar.add(tek_period_start_date,years=1,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)\n", " elif (self.Leg2Frequency=='3M'):\n", " while (len(self.Leg2PeriodStartDates)==0 or MyCalendar.add(tek_period_start_date,months=3,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)<=Leg2AbsEndDate):\n", " #print(\"g\",tek_period_start_date)\n", " self.Leg2PeriodStartDates.append(MyCalendar.make_date_not_holiday(tek_period_start_date))\n", " tek_period_start_date=MyCalendar.add(tek_period_start_date,months=3,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)\n", " elif (self.Leg2Frequency=='6M'):\n", " while (len(self.Leg2PeriodStartDates)==0 or MyCalendar.add(tek_period_start_date,months=6,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)<=Leg2AbsEndDate):\n", " #print(\"g\",tek_period_start_date)\n", " self.Leg2PeriodStartDates.append(MyCalendar.make_date_not_holiday(tek_period_start_date))\n", " tek_period_start_date=MyCalendar.add(tek_period_start_date,months=6,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)\n", "\n", "\n", "\n", " tek_period_end_date= Leg2AbsEndDate\n", " #print(\"h\",tek_period_end_date)\n", " self.Leg2PeriodEndDates=[]\n", " if (self.Leg2Frequency=='1Y'):\n", " while (len(self.Leg2PeriodEndDates)==0 or MyCalendar.add(tek_period_end_date,years=-1,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)>=MyCalendar.add(now, days=Leg2StartDateLagInDays)):\n", " #print(\"i\",tek_period_end_date)\n", " #print(MyCalendar.add(tek_period_end_date,datetime.timedelta(days=-360)),MyCalendar.add(now, Leg1StartDateLagInDays))\n", " self.Leg2PeriodEndDates.append(MyCalendar.make_date_not_holiday(tek_period_end_date))\n", " tek_period_end_date=MyCalendar.add(tek_period_end_date,years=-1,MakeNotHolidayFirst=False,MakeNotHolidayLast=False) \n", " elif (self.Leg2Frequency=='3M'):\n", " while (len(self.Leg2PeriodEndDates)==0 or MyCalendar.add(tek_period_end_date,months=-3,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)>=MyCalendar.add(now, days=Leg2StartDateLagInDays)):\n", " #print(\"i\",tek_period_end_date)\n", " #print(MyCalendar.add(tek_period_end_date,datetime.timedelta(days=-360)),MyCalendar.add(now, Leg1StartDateLagInDays))\n", " self.Leg2PeriodEndDates.append(MyCalendar.make_date_not_holiday(tek_period_end_date))\n", " tek_period_end_date=MyCalendar.add(tek_period_end_date,months=-3,MakeNotHolidayFirst=False,MakeNotHolidayLast=False) \n", " elif (self.Leg2Frequency=='6M'):\n", " while (len(self.Leg2PeriodEndDates)==0 or MyCalendar.add(tek_period_end_date,months=-6,MakeNotHolidayFirst=False,MakeNotHolidayLast=False)>=MyCalendar.add(now, days=Leg2StartDateLagInDays)):\n", " #print(\"i\",tek_period_end_date)\n", " #print(MyCalendar.add(tek_period_end_date,datetime.timedelta(days=-360)),MyCalendar.add(now, Leg1StartDateLagInDays))\n", " self.Leg2PeriodEndDates.append(MyCalendar.make_date_not_holiday(tek_period_end_date))\n", " tek_period_end_date=MyCalendar.add(tek_period_end_date,months=-6,MakeNotHolidayFirst=False,MakeNotHolidayLast=False) \n", " \n", " \n", " self.Leg2PeriodEndDates=self.Leg2PeriodEndDates[::-1] \n", "\n", " self.Leg2PaymentDates=list(map(lambda x: MyCalendar.add(x,days=Leg2PaymentLagInDays),self.Leg2PeriodEndDates))\n", " self.Leg2Tenor=Leg1Tenor\n", " self.Leg2StartDateLagInDays=Leg2StartDateLagInDays\n", " self.Leg2PaymentLagInDays=Leg2PaymentLagInDays\n", " self.Leg2IndexIdentifier=Leg2IndexIdentifier\n", " self.Leg2FloatingRateSpread=Leg2FloatingRateSpread\n", " self.Leg2FixedRate=Leg2FixedRate\n", " self.Leg2DayCountConvention=Leg2DayCountConvention\n", " self.Leg2IsFixed=Leg2IsFixed\n", " def clone(self,Leg1Tenor,Leg2Tenor,Leg2FixedRate=0.0,Leg2FloatingRateSpread=0.0,Leg1Frequency='1Y', Leg2Frequency='1Y', name='Cloned'):\n", " otv=InterestRatesSwapProduct(now=self.now, name=name,\n", " Leg1IndexIdentifier=self.Leg1IndexIdentifier,\n", " Leg1Tenor=Leg1Tenor, ##########(days,months,years)\n", " Leg1StartDateLagInDays=self.Leg1StartDateLagInDays, #timedelta\n", " Leg1PaymentLagInDays=self.Leg1PaymentLagInDays, #инфо\n", " Leg1FloatingRateSpread=self.Leg1FloatingRateSpread, \n", " Leg1FixedRate=self.Leg1FixedRate, \n", " Leg1DayCountConvention=self.Leg1DayCountConvention, #инфо\n", " Leg1IsFixed=self.Leg1IsFixed,\n", " Leg1Frequency=Leg1Frequency,\n", " Leg2IndexIdentifier=self.Leg2IndexIdentifier, #инфо\n", " Leg2Tenor=Leg2Tenor, ############\n", " Leg2StartDateLagInDays=self.Leg2StartDateLagInDays,\n", " Leg2PaymentLagInDays=self.Leg2PaymentLagInDays,\n", " Leg2FloatingRateSpread=self.Leg2FloatingRateSpread,\n", " Leg2FixedRate=Leg2FixedRate, ############\n", " Leg2DayCountConvention=self.Leg2DayCountConvention,\n", " Leg2IsFixed=self.Leg2IsFixed,Leg2Frequency=Leg2Frequency)\n", " return otv\n", " \n", " \n", "class Market:\n", " def __init__(self, RatesCurves, Swaps,now):\n", " self.RatesCurves=RatesCurves\n", " self.Swaps=Swaps\n", " self.now=now\n", " def get_V(self,t,SwapName):\n", " swap=self.Swaps[SwapName]\n", " Leg1PV=0\n", " if (not swap.Leg1IsFixed):\n", " #print(\"Leg1NotFixed\")\n", " for i in range(len(swap.Leg1PeriodStartDates)):\n", " Tim1=swap.Leg1PeriodStartDates[i]\n", " Ti=swap.Leg1PeriodEndDates[i]\n", " Tipaym=swap.Leg1PaymentDates[i]\n", " taui=(Ti-Tim1).days/360\n", " #print(self.RatesCurves['USD_SOFR'].DiscFactors)\n", " #print(t,Tipaym,self.RatesCurves['USD_SOFR'].get_disc_factor_now_T(Tipaym))\n", " #print(t,Tipaym,self.RatesCurves['USD_SOFR'].get_disc_factor_t_T(t,Tipaym))\n", " #print(t,now,self.RatesCurves['USD_SOFR'].get_disc_factor_now_T(t))\n", " #print(Tim1,Ti,Tipaym, taui),\n", "# self.RatesCurves['USD_SOFR'].get_disc_factor_t_T(t,Tipaym),\n", "# self.RatesCurves[swap.Leg1IndexIdentifier].get_disc_factor_t_T(t,Tim1),\n", "# self.RatesCurves[swap.Leg1IndexIdentifier].get_disc_factor_t_T(t,Ti),\n", "# taui*(self.RatesCurves[swap.Leg1IndexIdentifier].get_disc_factor_t_T(t,Tim1)/self.RatesCurves[swap.Leg1IndexIdentifier].get_disc_factor_t_T(t,Ti)-1),\n", "# (swap.Leg2FixedRate/100)*taui)\n", " Leg1PV+=self.RatesCurves['USD_SOFR'].get_disc_factor_t_T(t,Tipaym)*(self.RatesCurves[swap.Leg1IndexIdentifier].get_disc_factor_t_T(t,Tim1)/self.RatesCurves[swap.Leg1IndexIdentifier].get_disc_factor_t_T(t,Ti)-1 + swap.Leg1FloatingRateSpread/100*taui)\n", " else:\n", " for i in range(len(swap.Leg1PeriodStartDates)):\n", " Tim1=swap.Leg1PeriodStartDates[i]\n", " Ti=swap.Leg1PeriodEndDates[i]\n", " Tipaym=swap.Leg1PaymentDates[i]\n", " taui=(Ti-Tim1).days/360\n", " Leg1PV+=self.RatesCurves['USD_SOFR'].get_disc_factor_t_T(t,Tipaym)*(swap.Leg1FixedRate/100)*taui\n", " \n", " Leg2PV=0\n", " if (not swap.Leg2IsFixed):\n", " for i in range(len(swap.Leg2PeriodStartDates)):\n", " Tim1=swap.Leg2PeriodStartDates[i]\n", " Ti=swap.Leg2PeriodEndDates[i]\n", " Tipaym=swap.Leg2PaymentDates[i]\n", " taui=(Ti-Tim1).days/360\n", " Leg2PV+=self.RatesCurves['USD_SOFR'].get_disc_factor_t_T(t,Tipaym)*(self.RatesCurves[swap.Leg2IndexIdentifier].get_disc_factor_t_T(t,Tim1)/self.RatesCurves[swap.Leg2IndexIdentifier].get_disc_factor_t_T(t,Ti)-1+swap.Leg2FloatingRateSpread/100*taui)\n", " else:\n", " for i in range(len(swap.Leg2PeriodStartDates)):\n", " Tim1=swap.Leg2PeriodStartDates[i]\n", " Ti=swap.Leg2PeriodEndDates[i]\n", " Tipaym=swap.Leg2PaymentDates[i]\n", " taui=(Ti-Tim1).days/360\n", " #print(swap.name,\"K=\",swap.Leg2FixedRate/100,'taui=',taui)\n", " Leg2PV+=self.RatesCurves['USD_SOFR'].get_disc_factor_t_T(t,Tipaym)*(swap.Leg2FixedRate/100)*taui\n", " return Leg1PV-Leg2PV\n", " \n", " def solve_for_df(self,t,SwapName,LegToSolve=1):\n", " tolerance=1e-10\n", " RatesCurveName=self.Swaps[SwapName].Leg1IndexIdentifier\n", " a=1.0\n", " b=0.2\n", " #print(\"StartDates=\",self.Swaps[SwapName].Leg1PeriodStartDates)\n", " #print(\"PaymentDates=\",self.Swaps[SwapName].Leg1PaymentDates)\n", " self.RatesCurves[RatesCurveName].add_date_and_DiscFactor(self.Swaps[SwapName].Leg1PaymentDates[-1], b)\n", " #print(\"In solve\", self.RatesCurves[RatesCurveName].DiscFactors)\n", " PV=self.get_V(t,SwapName)\n", " #print(a,b,PV)\n", " while (np.abs(PV) > tolerance):\n", " #print(\"Begin this step:\",\"a=\",a,\"b=\",b)\n", " mid=(a+b)/2\n", " self.RatesCurves[RatesCurveName].add_date_and_DiscFactor(self.Swaps[SwapName].Leg1PaymentDates[-1], a)\n", " #print(\"In solve a\", self.RatesCurves[RatesCurveName].DiscFactors)\n", " PVa=self.get_V(t,SwapName)\n", " #print(\"PVa:\",a,mid,b,PVa)\n", " \n", " self.RatesCurves[RatesCurveName].add_date_and_DiscFactor(self.Swaps[SwapName].Leg1PaymentDates[-1], (a+b)/2)\n", " #print(\"In solve mid\", self.RatesCurves[RatesCurveName].DiscFactors)\n", " PVmid=self.get_V(t,SwapName)\n", " #print(\"PVmid:\",a,mid, b,PVmid)\n", " \n", " self.RatesCurves[RatesCurveName].add_date_and_DiscFactor(self.Swaps[SwapName].Leg1PaymentDates[-1], b)\n", " #print(\"In solve b\", self.RatesCurves[RatesCurveName].DiscFactors)\n", " PVb=self.get_V(t,SwapName)\n", " #print(\"PVb:\",a,mid, b,PVb)\n", " \n", " \n", " if (PVa*PVmid <0):\n", " b=mid\n", " PV=PVmid\n", " elif (PVmid*PVb <0):\n", " a=mid\n", " PV=PVb\n", " #print(\"AFTER this step:\",\"a=\",a,\"b=\",b)\n", " return b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Строим дисконтирующую кривую USD_SOFR" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "text/plain": [ "{datetime.date(2022, 1, 31): 1.0,\n", " datetime.date(2022, 3, 4): 0.9999786669388415,\n", " datetime.date(2022, 4, 6): 0.9998069902881979,\n", " datetime.date(2022, 5, 4): 0.9994732208549977,\n", " datetime.date(2022, 6, 6): 0.9989873617887499,\n", " datetime.date(2022, 7, 7): 0.9983946450054644,\n", " datetime.date(2022, 8, 4): 0.9977826707065105,\n", " datetime.date(2022, 9, 6): 0.9970102585852145,\n", " datetime.date(2022, 10, 5): 0.9961897388100626,\n", " datetime.date(2022, 11, 4): 0.9953212354332209,\n", " datetime.date(2022, 12, 5): 0.9943560235202313,\n", " datetime.date(2023, 1, 5): 0.993283274024725,\n", " datetime.date(2023, 2, 6): 0.99216203764081,\n", " datetime.date(2024, 2, 5): 0.9765340458601712,\n", " datetime.date(2025, 2, 5): 0.9601210072636603,\n", " datetime.date(2026, 2, 4): 0.9442242801189423,\n", " datetime.date(2027, 2, 4): 0.9284011721611023,\n", " datetime.date(2028, 2, 4): 0.91255671530962,\n", " datetime.date(2029, 2, 5): 0.8966276034712793,\n", " datetime.date(2030, 2, 6): 0.8809576995670796,\n", " datetime.date(2031, 2, 5): 0.8656610593199728,\n", " datetime.date(2032, 2, 4): 0.8500757850706577,\n", " datetime.date(2034, 2, 6): 0.8185540597885846,\n", " datetime.date(2037, 2, 4): 0.7736497435718775,\n", " datetime.date(2042, 2, 5): 0.7061769790947436,\n", " datetime.date(2047, 2, 6): 0.6515473835170269,\n", " datetime.date(2052, 2, 5): 0.6053119402378796}" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#MyCalendar=USCalendar()\n", "now=datetime.datetime(2022,1,31).date()\n", "MyRatesCurveUSD_SOFR=RatesCurve('USD_SOFR','Act360','LinearOnLogDF',now=now)\n", "MySofrSwap1M=InterestRatesSwapProduct(now=now,name='SOFRSwap1M',Leg1IndexIdentifier='USD_SOFR',\n", " Leg1Tenor=(0,1,0), \n", " Leg1StartDateLagInDays=2, \n", " Leg1PaymentLagInDays=2, \n", " Leg1FloatingRateSpread=0.0, \n", " Leg1FixedRate=0.0, \n", " Leg1DayCountConvention='Act360',\n", " Leg1IsFixed=False,\n", " Leg1Frequency='1Y',\n", " Leg2IndexIdentifier='USD_fixed_rate', #инфо\n", " Leg2Tenor=(0,1,0),\n", " Leg2StartDateLagInDays=2,\n", " Leg2PaymentLagInDays=2, #инфо\n", " Leg2FloatingRateSpread=0.0, \n", " Leg2FixedRate=0.024, \n", " Leg2DayCountConvention='Act360',\n", " Leg2IsFixed=True,\n", " Leg2Frequency='1Y')\n", "\n", "\n", "\n", "dictSofr={'1M':0.024,'2M':0.107,'3M':0.203,'4M':0.286,'5M':0.369,'6M':0.433,'7M':0.493,'8M':0.558,'9M':0.612,'10M':0.663,\n", " '11M':0.719,'1Y':0.765,'2Y':1.169,'3Y':1.338,'4Y':1.417,'5Y':1.468,'6Y':1.507,'7Y':1.539,'8Y':1.564,\n", " '9Y':1.583,'10Y':1.604,'12Y':1.645,'15Y':1.686,'20Y':1.714,'25Y':1.695,'30Y':1.664}\n", "MasSofrSwapNames=['SOFRSwap1M']\n", "MasSofrSwaps=[MySofrSwap1M]\n", "for i in range(2,12):\n", " #print(dictSofr[str(i)+'M'])\n", " MySofrSwapiM=MySofrSwap1M.clone(Leg1Tenor=(0,i,0),Leg2Tenor=(0,i,0),Leg2FixedRate=dictSofr[str(i)+'M'],name='SOFRSwap'+str(i)+'M')\n", " MasSofrSwaps.append(MySofrSwapiM)\n", " MasSofrSwapNames.append('SOFRSwap'+str(i)+'M')\n", " \n", "for i in range(1,11):\n", " MySofrSwapiY=MySofrSwap1M.clone(Leg1Tenor=(0,0,i),Leg2Tenor=(0,0,i),Leg2FixedRate=dictSofr[str(i)+'Y'],name='SOFRSwap'+str(i)+'Y')\n", " MasSofrSwaps.append(MySofrSwapiY)\n", " MasSofrSwapNames.append('SOFRSwap'+str(i)+'Y')\n", " \n", "for i in [12,15,20,25,30]:\n", " MySofrSwapiY=MySofrSwap1M.clone(Leg1Tenor=(0,0,i),Leg2Tenor=(0,0,i),Leg2FixedRate=dictSofr[str(i)+'Y'],name='SOFRSwap'+str(i)+'Y')\n", " MasSofrSwaps.append(MySofrSwapiY)\n", " MasSofrSwapNames.append('SOFRSwap'+str(i)+'Y')\n", "\n", "MyMarket=Market(RatesCurves={'USD_SOFR':MyRatesCurveUSD_SOFR},Swaps={a:b for (a,b) in zip(MasSofrSwapNames,MasSofrSwaps)},now=now)\n", "for SwapName in MasSofrSwapNames:\n", " MyMarket.solve_for_df(now,SwapName)\n", "\n", "\n", "plt.scatter(MyMarket.RatesCurves['USD_SOFR'].DiscFactors.keys(),MyMarket.RatesCurves['USD_SOFR'].DiscFactors.values())\n", "plt.plot(MyMarket.RatesCurves['USD_SOFR'].DiscFactors.keys(),MyMarket.RatesCurves['USD_SOFR'].DiscFactors.values())\n", "plt.show()\n", "MyMarket.RatesCurves['USD_SOFR'].DiscFactors" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Стороим кривую USD_LIBOR_3M, уже имея дисконтирующую кривую USD_SOFR" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAD4CAYAAAD8Zh1EAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAA2yklEQVR4nO3dd1yV1R/A8c+5bERBRXMAinsk4l6ZWvpzlCMzZ6UtNbXUclW/cjQ07Zdmao6GlabRcFZqBe49cGviQMGNW0DW+f3xXA3hIhe5cPHyfb9evLz3Gef5gvDlcJ7vc47SWiOEEOLBZ7J3AEIIIWxDEroQQjgISehCCOEgJKELIYSDkIQuhBAOwtleF/b19dVly5a11+WFEOKBtGPHjota62KW9tktoZctW5bt27fb6/JCCPFAUkpFZrRPhlyEEMJBSEIXQggHIQldCCEchN3G0IUQOS8xMZGoqCji4+PtHYrIInd3d/z8/HBxcbH6HEnoQjiwqKgoChYsSNmyZVFK2TscYSWtNTExMURFRREYGGj1eZkmdKXU18CTwHmt9cMW9ivgM6AdEAv00VrvtDqCLNi2dBald06khL7Iae3LxKSuLE15hMKeLoxuX51OtUrnxGWFeGDFx8dLMn8AKaUoWrQoFy5cyNJ51oyhzwXa3GN/W6Ci+aMv8EWWIrDStqWzqL7jv5TiIiYFfqaLTHGZwXG3nmxL7kbHxdWIeq88IV//LycuL8QDS5L5g+l+/t8y7aFrrdcqpcre45COwHfamId3s1LKRylVUmt9JsvR3IP/zkl4qgQOpvhzSRckFndcSaKMOkcZdQ6lwE9d5MnICbz+9kXWubeQXrsQIl+xxRh6aeBUqvdR5m3pErpSqi9GL56AgIAsXaS4vgAKrmovmjgduLP9hnbnz5Q6XNWe1DJFUMF0hs9cZhCdFMLEn7ryzqJmfPhUDUnsQgiHl6tli1rr2VrrulrrusWKWXxyNUPnlXF8Q6eDANzSzkSl+HJGF6GR6QDPOK8jBRMzk55km66En+kin7nMYJ16idCfpvHfxXtt/vkIITJ34sQJHn747ttvY8aM4ZNPPmHz5s00aNCA4OBgqlatypgxYwCYO3cuxYoVo1atWlSsWJHWrVuzcePGe14no7YAFi9eTFBQEFWrVqVGjRosXrz4zr4+ffoQGBhIcHAwwcHBTJ06FTCeZq9RowZBQUE0a9aMyMgMH9DMM2zRQ48G/FO99zNvs6lTtYdTaMd/8VQJALipJPzUxTv7r2kPiqpr9HdezsGUAMYkPkcPpzAqm6KY4PIlb22FxWUGSU9diDykd+/ehISEULNmTZKTkzl8+PCdfd26dWPatGkAhIWF0blzZ8LCwqhatWqW2tq9ezfDhg3jzz//JDAwkOPHj9OqVSvKlStHUFAQAJMmTaJLly7p2gwLC8PX15fRo0fzwQcfMGfOHFt/CWzKFgl9KTBIKbUQaABctfX4OUC9Dv3YBneqXABMqe4ZFFJxACRoJ/zVed5znse3ya1YntyA15wXM9w5hG4rW0lCF/nW2GX7OXD6mk3brFaqEKPbV7/v88+fP0/JkiUBcHJyolq1ahaPa9GiBX379mX27NlMnjw5S2198sknvP3223fK/wIDA3nrrbeYNGkS33//vVVxNmrU6E7PPS/LdMhFKbUA2ARUVkpFKaVeUkr1V0r1Nx/yO3AMiADmAANyKth6HfpRasxRTGOvYnp6DrEeJUnRkKRN3F4a1VUl46XiScCZ3k6raOe0jQGJg7muPTh9JS6nQhNC3IehQ4dSuXJlnnrqKWbNmnXPB6Bq167NoUOHstzW/v37qVOnzl3H1q1bl/379995P3z48DtDLnv3ph+eXbFiBZ06dcriZ5f7rKly6ZHJfg0MtFlE1grqimdQVwCW7opmy5KZvKtn3hmScVeJAJQnmikuMxiR2JeC7s6kpGhMJinjEvlPdnrS2ZFR+Z1Sivfee49evXqxatUqfvjhBxYsWMDq1astHp/ZgvZZaSutjIZcWrRowaVLl/Dy8uL999+3qi17coi5XDrVKs34Me/j+fR0brl4k/r/3VUl40oiM1ynMiDpe56bs5Fo6akLkWuKFi3K5cuX79p26dIlfH19AShfvjyvvvoqf//9N7t37yYmJsZiO7t27cpw/Pw2S21Vq1aNHTt23HXcjh07qF49819wYWFhREZGEhwczOjRozM93t4cIqHfEdQVt3dOom4Px6CISvHlY+dXOVamG/2dlzH49DB6TV7KrzujMv2NL4TIPi8vL0qWLEloaChgJPMVK1bwyCOP8Ntvv935OTxy5AhOTk74+Pika2PNmjXMnj2bV155JcPrZNTWsGHDGD9+PCdOnACMqpuPPvqIN99806r4nZ2dmTJlCt999x2XLl3Kwmee+xxzLpdUwzF+wLu3t+9+jLrLBvNryij6/jSIvw42p0l5X2asPsrpK3GU8vFgeOvKcuNUCBv77rvvGDhwIG+88QYAo0ePpnz58rzzzjsMHToUT09PnJ2dmT9/Pk5OTgD8+OOPrF+/ntjYWAIDA/nll1/u2UP//vvvLbYVHBzMxx9/TPv27UlMTMTFxYWJEycSHBxsdfwlS5akR48eTJ8+nXfffTfzE+xE2auXWrduXW2XFYvO7Uf/+Bz60gnGJ/Xg+6TH+cD5azo7reO09mUK3XnkqQGS1IVDOHjwYKbDFCLvsvT/p5TaobWua+l4xxpyscZD1VF9wzBVacs7zvOY7fI/xiT1ZmxSb3zVVcap2YT/NtveUQohRJblv4QO4O4N3eZxJcWTpqZ9rHEbyoaU6nRKeJ9oXYyXE+bZO0IhRAYGDhx4p8Tw9sc333xj77DyBMccQ7eGUhQyxaGAolxnhesoRib25cmED3nX+Xt6aS2z1AmRB02fPt3eIeRZ+bOHbhbvUeLOa2eVwv9cZ/KR85e8m/QCr87byZXYBDtGJ4QQWZOvE7pn23EkObnfte1p5/WEFpvMpkORtP1sHVuOWa6JFUKIvCb/DrkABHU1vgB/j4OrUVCoNJRtQuDen9hSfAIvxA+lx5zNDGpRgTJFC/Dpn/9IeaMQIs/K3wkdIKir8ZFazR64/9SHH3iLWRXfZUKoMRFYirnCM/pKHG/9asz3IEldCJFX5OshlwyVbwF9w1AFS9D/1DAGeazEpBPxIpapzlNZ7/o6rZLXMGnl4czbEiKfy6350Pv06cPPP/+c4bVXr16Nt7c3wcHBBAUF0bJlS86fP3/n2NmzZ1OlShWqVKlC/fr1Wb9+/Z19zZs3p3LlytSsWZN69eoRHh5+z1jatGlDzZo1qV69Ov379yc5OflOjJ6enly/fv3OsUOGDEEpxcWLFzNqzmqS0DNSpBy8/CdUbscw/S073PpTVZ3g9aTX+TTpGf7rPI+61/60d5RCPNB69+7N7NmzCQ8PZ9++fXTt+u9fy926dWPXrl0cOXKEUaNG0blzZw4ePJit6zVt2pTw8HD27NlDvXr17lTMLF++nFmzZrF+/XoOHTrEzJkz6dmzJ2fPnr1z7vz589m9ezcDBgxg+PDh97xOSEgIu3fvZt++fVy4cIGffvrpzr4KFSqwZMkSAFJSUggNDaV0adv8pS9DLvfiVhC6fs/1caXxVrH86PoBXya1Y0JyT7YmVua/LgvsHaEQ1vtjFJy18cpdJWpA2wn3fbot50PPCq01169fp0KFCgB8/PHHTJo06c6EYbVr16Z3795Mnz493SyLjRo1YtKkSfdsv1ChQgAkJSWRkJBwVwl09+7d+fHHH3n22WdZvXo1TZo04Y8//sj25wTSQ8+cyYQXxuyMJgV9XX7nN9e3MKEZkPAan6w8TGJyip2DFOLBZMv50K2xbt06goODCQgI4K+//uLFF18ErJsz/TZr50Zv3bo1xYsXp2DBgndNzVupUiUuXLjA5cuXWbBgAd27d8/W55Sa9NCtoLz94Oq/62BXNZ1ipesI3lODmBZmYt2RC0zuFky5Yl52jFKITGSjJ50duTUfujWaNm3K8uXLAaNXPmLECGbOnGnVub169SIhIYEbN25kOoYOsHLlSuLj4+nVqxehoaG0atXqzr7OnTuzcOFCtmzZwqxZs+7rc7FEeujWePw9cPG4a5OHSmRS1WPM6FmLEzGxPDF1PT9sOcminVE0mRBK4KjfaDIhlMW7bL68qhAPlNycDz0rOnTowNq1awGsmjN9/vz5HDt2jN69e/Paa69ZdQ13d3c6dux4Z8z8tm7duvHuu+/SqlUrTCbbpWFJ6NYI6grtp4K3P6CgkB8ENISDS2j3z7usHFSPOmUK8/aivbz5026ir8Sh+be8UZK6yM9yaz70rFq/fj3ly5cHYMSIEYwcOfLOL5Pw8HDmzp3LgAF3r6iplOL9999n8+bNGQ7/3LhxgzNnjGWVk5KS+O2336hSpcpdx5QpU4YPP/wwXfvZJUMu1kpbr641rJ8Mf4+lxOUTfNdtPrU+vcrV+MS7TotLTGbSysNSry7ytdyYDx2gX79+DBkyBAB/f38WLLi7cOH2GLrWGm9vb7788kvA6K1HR0fTuHFjlFIULFiQefPm3blhm5qHhwdvvvkmkyZN4quvvkq3/+bNm3To0IFbt26RkpJCixYt6N+/f7rj+vXrl/kXLovy33zotnZwGfzaFzyK0O7CAA7osukOUcDxCU/kemhCyHzoDzaZDz23VW0PL64ANL+4jeUdp+/42+UNXnL6DQAvYvH1crNvjEKIfEESui2UrAmvhJLsWZyXnVdQ3uks77rMZ77LhxQgnks345kWeoTkFFnDVIjsykvzod9+yjX1x969Nq71zwIZQ7eVgiXwck4xxlfMmjjtZ5VpJO8wiE9WKVYfNsob/Yt42i9Oke9oB5vbPy/Nh75ly5Yca/t+hsMlodvStdPpNnmrm3yuJ9Ky237eXbKPNlPWMrpDdVxMik9WyeyNIme5u7sTExND0aJFHSqpOzqtNTExMbi7u2d+cCqS0G0pzQNItykvXzrVKk29wCK88WM4I37eI7M3ilzh5+dHVFQUFy5csHcoIovc3d3x8/PL0jlS5WJLe0Jg2euQGJdqowKloPV4aNCPZA21xq3iWnxSutNL+3iwYdRjuRevEOKBI1UuuSXtA0je/tB+ClRqAytGwuJXcUqO57qFZA5w+kqcxe1CCGENGXKxNUsLZtR6HtZOhNXj4fxBgr0HsutqgXSnSnmjECI7pIeeG0wmaD4Kui+AmKMs1CMZ4foT611f55hbTyY7T8OdW8TcvMX0sAgpbxRC3BdJ6LmpSjt4JRQ3V1deNS3Cz3QRk4KnnDey3nMYbf2TmLTyMN1nb+LUpVh7RyuEeMDIkEtuK1YJTE6kLSDzTYlhWvw7PN51Be8t2U/bz9YxtkN1TAopbxRCWEUSuj1YqFcHUNei6Fzbj3pli/BmyG7e/Gk3TkqRbK5EkvJGIcS9yJCLPXhnUFvqWRQA/yKeLOjbkELuzneS+W23Z28UQoi0JKHbg4UFM0BBbAysmQgpKTiZlJQ3CiGyRBK6PViqV+/wubE97ENY2BPirlDKJ23SNxQrKOWNQoj05EnRvERr2DoHVr4FPgGE1vyUgX/dIi4x+a7DnEyKEa0r83LTcjiZZH4OIfKTbD8pqpRqo5Q6rJSKUEqNsrC/jFLqb6XUHqXUaqVU1iYgEAaloEFf6PMbJMTy2PqeLC+/mM3ugznm1pPN7oP5qt5pWlV9iPF/HKLnnM1Ey/CLEMIs0x66UsoJ+AdoBUQB24AeWusDqY75CViutf5WKfUY8ILW+rl7tSs99ExcPwtzn4CYiLu3u3ign5zKz4mNGLN0PyaT4oNOD9MxWKpehMgP7tVDt6ZssT4QobU+Zm5sIdAROJDqmGrAG+bXYcDi+45WGAqWgMT49NsT41Ch43hm6D4aBBbljZBwBi8MZ+7GE5y9Es/Za/FSry5EPmXNkEtpIPWcsFHmbantBjqbXz8FFFRKFU3bkFKqr1Jqu1Jqu0znaYVr0Za3X40CIKCoJz/2a8QTNUqy6+QVzlyLR/NvvfriXRmcL4RwSLaqchkGNFNK7QKaAdFActqDtNaztdZ1tdZ1ixUrZqNLO7CM6tU9Ct956WRShJ+6ku4QqVcXIv+xJqFHA/6p3vuZt92htT6tte6sta4FvGPedsVWQeZblurVlQniLsHvIyA5Eci4Ll1umAqRv1iT0LcBFZVSgUopV6A7sDT1AUopX6XU7bbeAr62bZj5lKV69Y4zoOFA2DoLvusENy5kWK8OMC30CEnJKbkWshDCfqyqQ1dKtQOmAE7A11rrD5VS44DtWuulSqkuwHhAA2uBgVrrW/dqU6pcsmlPCCx9DTx9Cas1mQGhKXfVq7s7m6haqhC7Tl6hVoAPk7sGU9Y3/RzsQogHy72qXOTBogfZ6XD48Vm4eYFjpTviGRlKcX2B86oYp2oPp16HfiwJj+bdxftITNa880RVejUIkMWChXiASUJ3ZDcvwjft4GKaG6AuHsZwTVBXzlyNY8TPe1h35CLNKxejReXizF57TKbkFeIBJGuKOrICvpBwM/32xDj4exwAJb09+PaF+oztUJ0NERcZvXQ/0VfipMRRCAcjCd0RZFiv/u/jAyaTonfjshT2dE13mJQ4CuEYJKE7gozq1V084GbMXZsuXLd8r1qm5BXiwScJ3RFYqlc3OUNSAsxoCIdX3NmcUYmjh6sT1+MTczJKIUQOk4TuCCzVq3f6AvqtAa/isKAbLBkE8dcY3royHi5Od53ubFLEJSbTZso6NkZctM/nIITINqlycXRJt2D1BNgwxRia6fQF2/bsx3/npLtKHJ2CuzIsZDfHLt6kT+OyjGxTBQ9Xp0ybF0LkLilbFHByCyzuD5eOg8kJUlItb2cucYyr8jQTVx7imw0nCPQtQIeapfh5R5SUNwqRh0hCF4aEm/BJJUi4kX6ftz8M3QfAxqMXGTh/J5dj7x5T93BxYnznGpLUhbAjqUMXBtcClmvW4c6UvACNy/vi7pJ+uEXKG4XI2ySh5zcZlTgWurvXffaqhcU1kBkchcjLJKHnN5ZKHAE8i0D81TtvMypvdHUycTImNqeiE0JkgyT0/CZtiWMhP6jZE84fgDmPw8UjABbLG12cFCYTtP1sLQu3nsRe91+EEJbJTVFhOLEeQnpDcgJ0ngOV27B4VzSTVh6+q8qlfmARhv20m41HY2hZtTjjOwexIeJiuuPkxqkQOUOqXIR1rpyCH3vBmT3Q4h3w8YfQD4wbpt5+xnBNUFdSUjRzN55gwopDuDgpEpM0CakW0ZBqGCFyjiR0Yb3EOFg2GPb8aCx3p1OtdpRqSl6AI+eu027qOhKT038PlfbxYMOox3IraiHyDSlbFNZz8YCnZoG7z93JHO6akheg4kMFLSZzkMm+hLAHSegiPaXuqni5S6p6dTB64paU9Ha3dVRCiExIQheWWVmvbqkaBozFZQ+euZYDgQkhMiIJXViWUb164bLGhF9mnWqVZnznGpT28UBh9NhfaRpIYrKm47QNzFpzlOQUKW8UIjfITVGRsT0hxpj51SijZ16yJhz+DfwbQNfvoeBDGZ4ac+MWby/ay8r956gfWIT/PVMT/yKeuRi8EI5JqlyE7exfBIteNZ4s7T4fStXK8FCtNb/sjGbM0v0AjG5fjS51/FBK5Va0QjgcSejCts7shgU9IfYidJxuVMPc7smnqle/7dSlWN4M2c3WE5doXf0hPnqqBkW93Oz4CQjx4JKELmzvxgUIeQ5ObjKWu7Mwv3rqpJ6covly3TH+t+ofCnm4MLFLDR6rkvGQjRDCMqlDF7bnVQyeXwouBe5O5pCuXh3AyaTo16w8SwY1wdfLlRfnbuftRXu5eSvNuUKI+yYJXdw/Z1dIzHx+9dSqlizEkkFN6PdoORZsPckTU9ex8+TlHAxSiPxDErrIHm//DLZnUMcOuDk78Va7qix4pSGJyZouX2zk01WHSUxOyfAcIUTmJKGL7MmoXr1YFUi+93BKw3JF+WNIU56q5cfU0Ag6z9hIxHkLy+MJIawiN0VF9qWtV/etCMfCoMwj8Mw34FU80yb+2HuGtxftJTYhmSdqlGTzsRjOXI2X6XiFSEOqXETu2/2jMWujhw888y0ENMj0lPPX4unzzTYOpJkyQKbjFeJfUuUicl/NbvDyn+DsBnOfgK1zIJPOQ/FC7lyJTUi3XRanFsI6ktBFzilRA/quhgqPw+/DYFE/SLj3eqRnZHFqIe6bJHSRszwKQ/cFxgpIe0Lgq1Zw6ViGh2e0OLUCQrafknVMhbgHSegi55lM0GwE9PrZuHE6qzkcXmHxUEvT8bo5myhXrAAjft5D72+2yeIZQmRAErrIPRVbQr81ULgMLOgGoR9CSvJdh1iajvfjp4P4c2gzxnaozrbjl/jP5LUs3HpSeutCpCFVLiL3JcbBb29C+Hyo0BI6zzFmb7TCyZhYRvyym83HLtG0oi8Tng7KcNUkIRxRtqtclFJtlFKHlVIRSqlRFvYHKKXClFK7lFJ7lFLtshu0cGAuHsYsjU9OhuNrYXYzOB1u1akBRT354eWGvN/pYXZEXuY/n65h/pZI6a0LgRUJXSnlBEwH2gLVgB5KqWppDvsvEKK1rgV0B2bYOlDhYJSCui/CCyuMYZevW8Ou+VadajIpnmtYhpVDHqWmvw/vLNrHs19t4dSle1fQCOHorOmh1wcitNbHtNYJwEKgY5pjNFDI/NobOG27EIVD86sD/daCf31YMgCWDTES++SHYYyP8e+eEIun+hfxZP7LDfjoqRqEn7xC6ylr+X5zJCmy5J3IpzIdQ1dKdQHaaK1fNr9/DmigtR6U6piSwCqgMFAAaKm13mGhrb5AX4CAgIA6kZGRtvo8xIMuOQlC34cNU4zee+rvSwvzq6cVdTmWt37dy7ojF2lYrggTn65JQFFZ8k44ntx4UrQHMFdr7Qe0A75XSqVrW2s9W2tdV2tdt1ixYja6tHAITs7Qaix4Fk3/RKmF+dXT8ivsyXcv1mdC5xrsi75G6ylr+XbjCemti3zFmoQeDaSeI9XPvC21l4AQAK31JsAd8LVFgCKfib1keXsG86unppSie/0AVg19lPqBRRi9dD/d52wmMiaDOduFcDDWJPRtQEWlVKBSyhXjpufSNMecBB4HUEpVxUjoF2wZqMgnMppHvWAJq5so5ePB3BfqMbFLEAfPGL31r9cfl966cHiZJnStdRIwCFgJHMSoZtmvlBqnlOpgPuxN4BWl1G5gAdBHSx2ZuB8Zza8edznDm6OWKKXoWtefP4c2o3F5X8YtP0C32Zs4flF668JxyYNFIu9JPb+6tx80Ggj7F8GpLVCzB7SbBG4FrW5Oa82vO6MZu2w/t5JSGN66Mi80CcTJpHLwkxAiZ8h86OLBl5wEayfC2klQuCw8/SWUrpOlJs5di+edRXv56+B5agf4MOmZmpQv5pUz8QqRQ2Q+dPHgc3KGFm9Dn98gKQG++g9s+AxSrF+H9KFC7sx5vi5TugVz9MJN2n22jtlrj5IsY+vCQUhCFw+WMo3h1fVQuR38+R7M6wzXz1p9ulKKTrVK8+cbj9KsUjE++v0QXWZuJOL89RwMWojcIUMu4sGkNez8Fv4YBa6e0OkLqNQ6i01olu05w+gl+7iZkMzQlpUoXtCNT//8h9NX4mQ9U5EnyRi6cFwXDsPPL8G5vdCgP7QcCy7uWWvi+i3eXbyPFfvPpntIVdYzFXmNjKELx1WsMrz8l5HMt8yEL1saST4rTRR044tna1PY0yXdQ6qynql4kEhCFw8+F3do+zH0DIHrp2FWM9gxN9NFqVNTSnElNtHiPlnPVDwoJKELx1GpNby6EQIawLLBEPK88UCSlTJaz9TN2cTRCzdsFaUQOUYSunAsBUvAs4ug1Tg4/Dt88QhEbrTqVEvrmbqYFEpBmylrmfDHIW7eSsqJqIWwCUnowvGYTNBkMLy0CpxcYO4TEPaR8XDSPVhaz3TSMzVZN+IxOgaXZuaao7T8dA3L95yWFZJEniRVLsKx3boOvw+H3QvAvyE8PQd8Au6rqR2Rl3hvyX72n75G4/JFGduhOhUfsn4KAiFsQcoWhdjzEywfCsoE7afAw53vq5nkFM0PWyKZtPIwsQnJvNCkLINbVsLLzdm28QqRASlbFCLoGei/DnwrwM8vwJJBkJD1mRedTIrnGpUlbFhzutTx48v1x3nsk9UsCY+WYRhhd5LQRf5RJBBeXAmPvAG75hnljWd231dTRb3cmPB0EIsGNKGEtzuDF4bTbfZmDp29ZuOghbCeJHSRvzi5QMvR8PwSSLhhPIi0aXqWJvlKLdjfh0UDmjC+cw2OnLvOE1PXM3bZfq7FW65pFyInyRi6yL9uxsDSQUZ5Y4WWUKmtsUj17XnYH3/vngtTp3X5ZgKfrDrMD1tPUrSAK6PaVqVzrdKYZN51YUNyU1SIjGgN276EFaMgJU1Zo4sHtJ+apaQOsDfqKu8u2Uf4qSvUKVOYcR2rU72Utw2DFvmZ3BQVIiNKQf1XwLNo+n2JccbKSVlUw8+bX19tzMQuQZy4eJP2n6/nvSX7uJrB1AJC2IokdCEAbpy3vP1q1H01ZzIZa5qGvtmc5xqWYd7mSFr8bzU/bjspi1WLHCMJXQgwxswtcfEwxtrvt1lPF8Z2fJjlrzWlfLECjPxlL52/2MieqCv33aYQGZGELgQYN0Bd0kzOZXKGpFswrS6E/5Cl2RvTqlaqECH9GvFp15pEXY6j4/QNvL1oL5dvJmQzcCH+JQldCDBufLafCt7+gDL+7fQF9F8PRSvA4lfhuw4Qc/S+L6GUonNtP0KHNeOFxoH8uO0ULf63mvlbImVdU2ETUuUiRGZSUmDHN/DXWEiKh0eHG5N/Obtmq9nDZ6/z3pJ9bDl+iRqlvRnXsTq1AgrbKGjhqKRsUQhbuH4W/hgJBxZDsSrw5BQo0yhbTWqtWbr7NB/9fpBz127Rta4fI9tUoaiXm01CFo5HEroQtvTPSvjtTbh6Cur0gZZjwCN7Pesbt5L4/O8jfLX+OJ6uTrz5n8r0ahCAs5OMioq7SUIXwtZu3YDV42HzDPD0hTbj4eGnjbr2bIg4f53RS/ezISKGqiUL8X7H6tQtW8RGQQtHIA8WCWFrbl7Q+kPouxoKlYJfXoL5XeDyiWw1W6F4Qea91IDpPWtzJTaBLjM38UZIOOevx9skbOHYpIcuRHalJMPW2RD6gfG6xVvQcIAxEVg2xCYkMS00gjnrjuHu7MSQVpXo3aiMDMPkczLkIkRuuBplrI50+Hd4qAa0/wz86mS72WMXbjBm2QHW/nOByg8VZGzH6jQsZ2GqApEvyJCLELnB2w+6/wBdv4fYi/Dl4/D7CIjP3hzp5Yp58e0L9Zj1XB1u3Eqi++zNvL5gF+euyTCMuJv00IXICfFXjSGYrXOgYEloNxGqts92s3EJyXyxOoKZa4/hYlIMblmRF5oE4iLDMPmGDLkIYS9R22HZYDi3Dyo/Ae0mgXfpbDcbGXOTscsOEHroPBWKezG2Q3WaVPC1QcAir5MhFyHsxa+uUQnTciwcDYXp9WHzTOPmaTaUKVqAr/vU46vedUlISqHXl1sYOH8np6/E2SZu8UCSHroQueXyCVj+Bhz9G0rVNm6algzKdrPxicnMWnOMGasjMCnFa49XoLiXG5P/OsLpK3GU8vFgeOvKdKqV/b8MhP3JkIsQeYXWsO8XY4Wk2EvQaAA0fwtcC2S76VOXYnl/+QFWHTiHAlL/ZHu4ODG+cw1J6g5AhlyEyCuUghpdYOBWqPUsbPwcpjeEf1Zlu2n/Ip7Mfr4uRQu4krabFpeYzKSVh7N9DZG3WZXQlVJtlFKHlVIRSqlRFvZPVkqFmz/+UUpdsXmkQjgSzyLQYSq88IcxD/sPz8BPfeD6uWw3fSmDOdajZXzd4WWa0JVSTsB0oC1QDeihlKqW+hit9VCtdbDWOhj4HPg1B2IVwvGUaQz910GLd+DQ7zCtHmz/2piy9z6V8vHIcF+vLzez6WgM9hpqFTnLmh56fSBCa31Ma50ALAQ63uP4HsACWwQnRL7g7AbNRsCrG42bpMuHwjdt4PzB+2pueOvKeLg43bXN3dlEh5qlOHz2Bj3mbOaZmZsIO3xeEruDsSahlwZOpXofZd6WjlKqDBAIhGawv69SartSavuFCxeyGqsQjs23AvReZqyUdPEIzGwKf78PiVkbKulUqzTjO9egtI8HCijt48GEp4OY2qMW60e2YFzH6py+EscL32yj/bT1rNh3VhaudhCZVrkopboAbbTWL5vfPwc00FoPsnDsSMBPa/1aZheWKhch7uFmDKx6B3YvgCLl4MnJUK65zZpPSEph8a5oZqyO4ERMLJUe8mJgiwo8UaOkTP6Vx2W3yiUa8E/13s+8zZLuyHCLENlXoCg8NROeX2K8/64j/NoPbl60SfOuzia61vPnrzea8Vn3YAAGLwyn5adrCNl2ioSk+x/DF/ZjTQ/dGfgHeBwjkW8Demqt96c5rgqwAgjUVgzMSQ9dCCslxsHaT2DDZ+BWEP7zAQT3zPZiGqmlpGhWHTjH9LAI9kZfpZS3O/2bl6drXX/c04zHC/vK9oNFSql2wBTACfhaa/2hUmocsF1rvdR8zBjAXWudrqzREknoQmTR+YOwbAic2gxlmxprmvpWsOkltNas+ecCn4dGsCPyMsUKuvFK00B6NShDATdnm15L3B95UlQIR5GSAju/hT9HQ1IcNB0GjwwxKmVsSGvN5mOXmBZ2hA0RMfh4uvBSk0Ceb1wWb4/sLdwhskcSuhCO5vo5Y/qA/b+Cb2VoP8Woac8BO09eZnpoBH8fOk9BN2eeb1yGF5sEUtTLtr9EhHUkoQvhqI78aUz4dfUk1H4eWo0Dj8I5cqn9p68yI+wov+87g7uzEz0bBND30XI8VMg9R64nLJOELoQjS7gJqyfApunGlAJtJhjT84a+byyL5+0Hj78HQV1tcrmI89eZsfooS8JP46QUXev50e/R8vgX8bRJ++LeJKELkR+c2WMspnF6JygT6FSlhy4e0H6qzZI6wMmYWL5Yc5Sfd5xCa+OBpgHNy1OumJfNriHSk4QuRH6RkgwTy0H8lfT7vP1h6D6bX/LM1Thmrz3Ggq0nSUhK4YmgUgxsUZ4qJQrZ/FpCps8VIv8wORnrmVpy9ZTl7dlU0tuD0e2rs37kY/RrVp7Qg+doM2Udr3y3nd2nruTINYVlktCFcDTefpa3KyfY/g0kJ+bIZX293BjZpgobRj3GkJYV2Xr8Eh2nb+C5r7aw9filHLmmuJsMuQjhaPaEwLLX757Uy8nVGHK5dBR8ykDzUVCjKzjl3MNCN24lMW9zJF+uO8bFGwnUDyzCoBYVaFrRF2XDp1zzGxlDFyK/2RMCf4+7u8qlxjNGmWPYB3BmNxStYCx/V70zmHLuj/W4hGR+3HaSWWuPceZqPDX9vBn0WEUer1Ick0kSe1ZJQhdC/EtrOLQcwj6C8wegeDVo8TZUedKm88OkdSspmV93RvPF6qOcvBRLlRIFGdiiAu1qlMRJErvVJKELIdJLSTGeNF09AWKOQMma0OK/ULFVjib2pOQUlu05zfSwo0Scv0E53wIMaFGBjsGlcJGpezMlCV0IkbHkJNgbYiT2K5HgVw8e+y8ENsvRxJ6Solm5/yyfh0Zw4Mw1/Ap70L9ZebrU8ZMZHu9BEroQInPJibBrHqydBNeijRkdW7wDZRrl6GW11oQdPs/noRHsOnmFhwq58UrTcvRsEICnq8zwmJYkdCGE9RLjjRkd1/0PbpyD8o8bid2vTo5eVmvNpqMxfB4awaZjMRQp4MpLjwRSxNOVaWERnL4SRykfD4a3rkynWhZXwcwXJKELIbIuIRa2fQkbpkBsDFRqa9w8LRmU45feEXmJaaERhB1Ov/awh4sT4zvXyLdJXZ4UFUJknasnNHkdBu82xtRPboRZTSGkN5w/lKOXrlOmCN+8UJ9iFqbojUtMZuKKnL3+g0oSuhDi3twKwqPDYfAeeHQERPwFMxrCr30h5miOXvrijVsWt5++Gs/8LZHcuJWUo9d/0MiQixAia27GwMbPYMtsSE4w1jdtNgJ8Amx+qSYTQom+Epduu4uTIjFZ4+XmTKdapXi2YZl8MxmYjKELIWzv+jlYPxm2f21M1VunNzR9EwqVstklFu+K5q1f9xKXmHxnm4eLEx899TBlfQswb/NJlu85za2kFOqWKUyvhgG0fbikQ5c9SkIXQuScq9Gw7hPY+Z0xAVi9l+GRoeBVzCbNL94VzaSVhzOscrkSm8DPO6KYv+Ukxy/epLCnC13r+tOzQQBlihawSQx5iSR0IUTOu3wC1kyC3T+Aszs06AeNXzdWUcoFWms2Ho1h3uZIVh04R3KK5tFKxejVIIDHqxTH2UGeQpWELoTIPRcjYM0E2PszuHpBo4HQaAC4e+daCOeuxbNw6ykWbD3J2WvxlPR2p3u9ALrX93/g10CVhC6EyH3nDxoTgB1cCu4+Rglk/X7glntL1CUlpxB66Dzztpxk7T8XcDIpWlV9iGcblqFx+aIP5GyPktCFEPZzZreR2P9ZAZ6+xvh6vZeMdU5zUWTMTX7YcpKQ7ae4HJtIoG8BejUI4OnafhQu4JqrsWSHJHQhhP2d2gZhH8KxMPAqAY8Og9rPg3P6h4dyUnxiMiv2nWXe5ki2R17G1dnEk0ElebZhGWr5++T5xTckoQsh8o4TGyD0A+PJU29/46Gl4J7g5JLroRw8c435WyJZtDOamwnJVCtZiF4NA+gUXJoCbnlzYjBJ6EKIvEVro6ce+iFEb4fCZY3Vk2o8Yyx0nctu3EpiSXg08zaf5OCZa3i5OfNUrdI827AMlUsUzPV47kUSuhAib9Ia/llpDMWc3QO+lYzEXq1Tji6Ll3E4mp0nrzB/SyTL95whISmFemUL06tBGdrWKIGbs/0fWJKELoTI21JS/l0W78JBeOhhY2bHyu1g70/p10cN6prjIV2+efuBpUhOxMRSpIArz9T1o1f9MgQU9czx62dEEroQ4sGQkgz7foXV4+HSUfApA9fPGHPG3ObiAe2n5kpSB2NlpQ1HLzJvcyR/HTx/54GlZxsE8JgdHliShC6EeLAkJ8GehbD0ddDJ6fd7+8PQfbke1tmr8SzcdpKFW0/deWCpR/0Autfzp3guPbAkCV0I8WAak9HTpQrGXMnNSO6SlJzCXwfPM39LJOuOXMTZpPhP9Yfo1cB4YCknSx/vldDzZl2OEEKA0RO/eir9didXiNyU4+udZsTZyUSbh0vQ5uESnLh4kx+2nuSn7af4fe9ZyvkWoGeDALrU8cPHM3cfWJIeuhAi79oTAsteh8RUc6KbXIxx9FvXoFwL4+apf337xWgWn5jMH/vOMG/zSXZEXsbN2cSTQaV4tmEAweYHljKbOdIaMuQihHhw7QlJX+VS5UnY/hWsnwKxF6FCS2j+do4vZG2tA6eNB5YW7zIeWKpeqhAPl/JmSXg08Ukpd467n/VRJaELIRxTwk3YOgc2fAZxl6Bia2jxFpSqZe/IAOOBpUW7opm/OZJDZ69bPKa0jwcbRj1mdZvZXiRaKdVGKXVYKRWhlBqVwTFdlVIHlFL7lVI/WB2dEELcL9cC8MgQGLLH6Lmf2gKzm8OCHsakYHbm5ebMcw3L8Mfgphkec9rCEnv3K9OErpRyAqYDbYFqQA+lVLU0x1QE3gKaaK2rA0NsFqEQQmTGraCx/N2QvdDivxC5AWY9Cgt7wdncL29MSylFaR/Ls0uWymD7/bCmh14fiNBaH9NaJwALgY5pjnkFmK61vgygtT5vswiFEMJa7oWg2XAYvMeYQuD4WpjZBEKeh3MH7Bra8NaV8Uiz1qmHixPDW1e22TWsSeilgdR1Q1HmbalVAioppTYopTYrpdpYakgp1VcptV0ptf3ChQv3F7EQQmTGwweajzKGYh4dARGh8EVj+OkFuHDYLiF1qlWa8Z1rUNrHA4Uxdp7VG6KZyfSmqFKqC9BGa/2y+f1zQAOt9aBUxywHEoGugB+wFqihtb6SUbtyU1QIkWtiL8GmabB5JiTGQo0u0Gwk+Fa0d2RZlt2botGAf6r3fuZtqUUBS7XWiVrr48A/wIP3lRJCOCbPIsZN0yF7oclgOPQbTK8Pv/aDmKP2js5mrEno24CKSqlApZQr0B1YmuaYxUBzAKWUL8YQzDHbhSmEEDZQoCi0GmuMsTcaCAeWwLR6sHgAXDpu7+iyLdOErrVOAgYBK4GDQIjWer9SapxSqoP5sJVAjFLqABAGDNdax+RU0EIIkS1exeA/H8Dg3dCgP+z7BT6vA0sGweVIe0d33+TBIiGEuH4W1k+G7d8YszvWehaaDgMf/8zPzWXZfrBICCEcWsES0PZjGBwOdV6A8B9gai1Y/gZcTXvLMO+ShC6EELcVKgVPfAKv7TR66Tu/g6nB8PtwuHbG3tFlShK6EEKk5eMP7afAazugZnfY/jV8VhP+GAXXz9k7ugxJQhdCiIwULgMdPodB26HGM7B1NnwWBCvfgRt574F4SehCCJGZIoHQaToM2gbVn4LNM2BKEKx6F25etHd0d0hCF0IIaxUtD0/NhIHboGp72Pi5kdj/GmM8jWpnktCFECKrfCvA03Ng4Bao3MZYaGNKDfj7fbsmdknoQghxv4pVhi5fw4BNxqpJ6z4xbp6GfQRxV3I9HEnoQgiRXcWrQtdvof8GKNcM1nxsDMWs/hjir+ZaGJLQhRDCVko8DN3mQb91UPYRWP2RkdjXToJb1431USc/DGN8jH/3hNj08vLovxBC5JTTu2D1BPhnhbFcXtItSEn6d7+LB7SfCkFdrW5SHv0XQgh7KFULev4IL4dCSvLdyRwgMQ7+Hmezy0lCF0KInOZXx+idW3I1ymaXkYQuhBC5wdsva9vvgyR0IYTIDY+/Z4yZp+biYWy3EUnoQgiRG4K6GjdAvf0BZfybxRuimXG2WUtCCCHuLairTRN4WtJDF0IIByEJXQghHIQkdCGEcBCS0IUQwkFIQhdCCAdht7lclFIXgEi7XDw9XyDvLDuSXl6PD/J+jHk9PpAYbSGvxwfZj7GM1rqYpR12S+h5iVJqe0aT3eQFeT0+yPsx5vX4QGK0hbweH+RsjDLkIoQQDkISuhBCOAhJ6IbZ9g4gE3k9Psj7Meb1+EBitIW8Hh/kYIwyhi6EEA5CeuhCCOEgJKELIYSDcMiErpTyV0qFKaUOKKX2K6UGm7cXUUr9qZQ6Yv63sHl7L6XUHqXUXqXURqVUzTTtOSmldimllue1+JRSQ81t7FNKLVBKudspxo7mGMOVUtuVUo+YtwcrpTaZ29ijlOpmi/hsGaN5X4BSapVS6qC5vbK5HV+q8+oppZKUUl1SbettPv6IUqp3dmPLiRjN2wsppaKUUtPyWnxKqYnmNg4qpaYqpZQ9YlRKNVdKXTV/H4Yrpd67VztZorV2uA+gJFDb/Log8A9QDZgIjDJvHwV8bH7dGChsft0W2JKmvTeAH4DleSk+oDRwHPAwvw8B+tgpRi/+vScTBBwyv64EVDS/LgWcAXzyUozm96uBVqmO88zt+MzvnYBQ4Hegi3lbEeCY+d/C5teF7fE1zCjGVPs+M/+sTMtL8Zl/hjaY9zkBm4Dmdvo+bI6FXJJRO1mKxRafUF7/AJYArYDDQMlUX7zDFo4tDESneu8H/A08Zuk/wZ7xYST0U+YfdGdgOfCfPBBjI+BgBu3sxpzg80qM5h++9Xnh+xAYAgwE5qZKRj2AWamOmQX0yEsxmrfXARYCfbBRQrfh17ARsAPwADyB7UBVe8RIBgk9o3aycm2HHHJJzfyncy1gC/CQ1vqMeddZ4CELp7wE/JHq/RRgBJCS1+LTWkcDnwAnMXq+V7XWq+wVo1LqKaXUIeA34EUL7dQHXIGjeSzGSsAVpdSvyhham6SUcsrt+JRSpYGngC/SnH77F/dtUeZtNpWdGJVSJuB/wDBbx2WL+LTWm4AwjJ+TM8BKrfVBe8Ro1kgptVsp9YdSqnom7VjNoRO6UsoL+AUYorW+lnqfNn4F6jTHt8BImCPN758Ezmutd+TR+AoDHYFAjOGMAkqpZ+0Vo9Z6kda6CtAJeD9NOyWB74EXtNY2/eVogxidgaYYyageUA6jl5nb8U0BRtr662MNG8Q4APhda227JextGJ9SqgJQFeMv7tLAY0qppnaKcSfGfCw1gc+Bxda2k6mc+JMjL3wALsBK4I1U2+71Z1oQRs+xUqpt4zF6QycwfsPGAvPyUHzPAF+lev88MMNeX8M05x4DfM2vC5m/ibvYKjZbxgg0BNak2v4cMD2348O4H3LC/HEDOI/xiydHh1xsFON8jL8UT2BMPHUNmJCH4hsOvJvq/PeAEXnk+/BEqp+VdO1kKQ5bfUJ56QNQwHfAlDTbJ3H3TYqJ5tcBQATQ+B5tNsd2N0VtEh/QANiPMSaogG+B1+wUYwX+veFYG4g2t+GKcQ9iSB74f84oRieMsf1i5n3fAANzO740x8zl7puixzHunxQ2vy5ij69hRjGm2d4H290UtdXXsBvwF8ZfYy7m78n2dvo+LJHq+7A+xi9ClVE7WYrFFp9QXvsAHsH482YPEG7+aAcUNf9HHjH/5xYxH/8lcDnVsdsttNkc2yV0m8UHjAUOAfswhjTc7BTjSIxfLuEYFQSPmLc/CySmaiMcCM5LMZr3tTK3sxcjEbjmdnxpzp3L3TccX8T4pR6BMWxll5+Ve8WYansfbJfQbRIfxi/tWcBB4ADwqb2+hsAg8/fhbmAz5o5aRu1kJRZ59F8IIRyEQ98UFUKI/EQSuhBCOAhJ6EII4SAkoQshhIOQhC6EEA5CEroQQjgISehCCOEg/g+QrZKQa8KWrgAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "text/plain": [ "{datetime.date(2022, 1, 31): 1.0,\n", " datetime.date(2022, 5, 2): 0.9992422342300417,\n", " datetime.date(2022, 8, 2): 0.9973306834697724,\n", " datetime.date(2022, 11, 2): 0.9945349350571634,\n", " datetime.date(2023, 2, 2): 0.9909370481967926,\n", " datetime.date(2024, 2, 2): 0.9734856467694042,\n", " datetime.date(2025, 2, 3): 0.9550735272467135,\n", " datetime.date(2026, 2, 2): 0.9362021744251251,\n", " datetime.date(2027, 2, 2): 0.9181210519745946,\n", " datetime.date(2028, 2, 2): 0.9003903057426214,\n", " datetime.date(2029, 2, 2): 0.8822144143283368,\n", " datetime.date(2030, 2, 4): 0.8666447756811977,\n", " datetime.date(2031, 2, 3): 0.8485096540302038,\n", " datetime.date(2032, 2, 2): 0.8300882671028377,\n", " datetime.date(2034, 2, 2): 0.7946747891604904,\n", " datetime.date(2037, 2, 2): 0.7456144481897355,\n", " datetime.date(2042, 2, 3): 0.6745572717860342,\n", " datetime.date(2047, 2, 4): 0.6164654564112425,\n", " datetime.date(2052, 2, 2): 0.5593541905283929}" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "MyRatesCurveUSD_LIBOR_3M=RatesCurve('USD_LIBOR_3M','Act360','LinearOnLogDF',now=now)\n", "MyUSDLIBORDeposit3M=InterestRatesSwapProduct(now=now,name='USDLIBORDeposit3M',Leg1IndexIdentifier='USD_LIBOR_3M',\n", " Leg1Tenor=(0,3,0), \n", " Leg1StartDateLagInDays=2, \n", " Leg1PaymentLagInDays=0, \n", " Leg1FloatingRateSpread=0.0, \n", " Leg1FixedRate=0.0, \n", " Leg1DayCountConvention='Act360',\n", " Leg1IsFixed=False,\n", " Leg1Frequency='3M',\n", " Leg2IndexIdentifier='USD_fixed_rate', #инфо\n", " Leg2Tenor=(0,3,0),\n", " Leg2StartDateLagInDays=2,\n", " Leg2PaymentLagInDays=0, #инфо\n", " Leg2FloatingRateSpread=0.0, \n", " Leg2FixedRate=0.3, \n", " Leg2DayCountConvention='Act360',\n", " Leg2IsFixed=True,\n", " Leg2Frequency='3M')\n", "\n", "dictUSDLIBOR3M={'1Y':0.9,'2Y':1.33,'3Y':1.53,'4Y':1.63,'5Y':1.69,'6Y':1.73,'7Y':1.77,'8Y':1.8,\n", " '9Y':1.82,'10Y':1.84,'12Y':1.89,'15Y':1.93,'20Y':1.96,'25Y':1.95,'30Y':1.92}\n", "\n", "MyUSDLIBORFRA3M6M=MyUSDLIBORDeposit3M.clone(Leg1Tenor=(0,6,0),Leg2Tenor=(0,6,0),Leg2FixedRate=0.75,Leg1Frequency='3M',Leg2Frequency='3M',name='USDLIBORFRA3M6M')\n", "MyUSDLIBORFRA3M6M.Leg1PeriodStartDates.pop(0)\n", "MyUSDLIBORFRA3M6M.Leg1PeriodEndDates.pop(0)\n", "MyUSDLIBORFRA3M6M.Leg1PaymentDates.pop(0)\n", "MyUSDLIBORFRA3M6M.Leg2PeriodStartDates.pop(0)\n", "MyUSDLIBORFRA3M6M.Leg2PeriodEndDates.pop(0)\n", "MyUSDLIBORFRA3M6M.Leg2PaymentDates.pop(0)\n", "\n", "\n", "MyUSDLIBORFRA6M9M=MyUSDLIBORDeposit3M.clone(Leg1Tenor=(0,9,0),Leg2Tenor=(0,9,0),Leg2FixedRate=1.1,Leg1Frequency='3M',Leg2Frequency='3M',name='USDLIBORFRA6M9M')\n", "MyUSDLIBORFRA6M9M.Leg1PeriodStartDates.pop(0)\n", "MyUSDLIBORFRA6M9M.Leg1PeriodEndDates.pop(0)\n", "MyUSDLIBORFRA6M9M.Leg1PaymentDates.pop(0)\n", "MyUSDLIBORFRA6M9M.Leg2PeriodStartDates.pop(0)\n", "MyUSDLIBORFRA6M9M.Leg2PeriodEndDates.pop(0)\n", "MyUSDLIBORFRA6M9M.Leg2PaymentDates.pop(0)\n", "\n", "MyUSDLIBORFRA6M9M.Leg1PeriodStartDates.pop(0)\n", "MyUSDLIBORFRA6M9M.Leg1PeriodEndDates.pop(0)\n", "MyUSDLIBORFRA6M9M.Leg1PaymentDates.pop(0)\n", "MyUSDLIBORFRA6M9M.Leg2PeriodStartDates.pop(0)\n", "MyUSDLIBORFRA6M9M.Leg2PeriodEndDates.pop(0)\n", "MyUSDLIBORFRA6M9M.Leg2PaymentDates.pop(0)\n", "\n", "\n", "MasUSDLIBOR3MSwapNames=['USDLIBORDeposit3M','USDLIBORFRA3M6M','USDLIBORFRA6M9M']\n", "MasUSDLIBOR3MSwaps=[MyUSDLIBORDeposit3M,MyUSDLIBORFRA3M6M,MyUSDLIBORFRA6M9M]\n", "\n", "for i in range(1,11):\n", " MyUSDLIBOR3MSwapiY=MyUSDLIBORDeposit3M.clone(Leg1Tenor=(0,0,i),Leg2Tenor=(0,0,i),Leg2FixedRate=dictUSDLIBOR3M[str(i)+'Y'],Leg1Frequency='3M',Leg2Frequency='1Y',name='USDLIBOR3MSwap'+str(i)+'Y')\n", " MasUSDLIBOR3MSwaps.append(MyUSDLIBOR3MSwapiY)\n", " MasUSDLIBOR3MSwapNames.append('USDLIBOR3MSwap'+str(i)+'Y')\n", " \n", "for i in [12,15,20,25,30]:\n", " MyUSDLIBOR3MSwapiY=MyUSDLIBORDeposit3M.clone(Leg1Tenor=(0,0,i),Leg2Tenor=(0,0,i),Leg2FixedRate=dictUSDLIBOR3M[str(i)+'Y'],Leg1Frequency='3M',Leg2Frequency='1Y',name='USDLIBOR3MSwap'+str(i)+'Y')\n", " MasUSDLIBOR3MSwaps.append(MyUSDLIBOR3MSwapiY)\n", " MasUSDLIBOR3MSwapNames.append('USDLIBOR3MSwap'+str(i)+'Y')\n", " \n", "\n", "MyMarket2=Market(RatesCurves={'USD_SOFR':MyMarket.RatesCurves['USD_SOFR'], 'USD_LIBOR_3M':MyRatesCurveUSD_LIBOR_3M},Swaps={a:b for (a,b) in zip(MasUSDLIBOR3MSwapNames,MasUSDLIBOR3MSwaps)},now=now)\n", "for SwapName in MasUSDLIBOR3MSwapNames:\n", " MyMarket2.solve_for_df(now,SwapName)\n", "\n", "\n", "plt.scatter(MyMarket.RatesCurves['USD_SOFR'].DiscFactors.keys(),MyMarket.RatesCurves['USD_SOFR'].DiscFactors.values())\n", "plt.plot(MyMarket.RatesCurves['USD_SOFR'].DiscFactors.keys(),MyMarket.RatesCurves['USD_SOFR'].DiscFactors.values(),label='USD_SOFR')\n", "plt.scatter(MyMarket2.RatesCurves['USD_LIBOR_3M'].DiscFactors.keys(),MyMarket2.RatesCurves['USD_LIBOR_3M'].DiscFactors.values())\n", "plt.plot(MyMarket2.RatesCurves['USD_LIBOR_3M'].DiscFactors.keys(),MyMarket2.RatesCurves['USD_LIBOR_3M'].DiscFactors.values(),label='USD_LIBOR_3M')\n", "plt.legend()\n", "plt.show()\n", "MyMarket2.RatesCurves['USD_LIBOR_3M'].DiscFactors\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Стороим кривую USD_LIBOR_6M, уже имея дисконтирующую кривую USD_SOFR и кривую USD_LIBOR_3M" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "text/plain": [ "{datetime.date(2022, 1, 31): 1.0,\n", " datetime.date(2022, 8, 2): 0.9978763280436396,\n", " datetime.date(2023, 2, 2): 0.9854529123753311,\n", " datetime.date(2024, 2, 2): 0.9627627981826663,\n", " datetime.date(2025, 2, 3): 0.9390788331627846,\n", " datetime.date(2026, 2, 2): 0.9157150747254492,\n", " datetime.date(2027, 2, 2): 0.8930861433967949,\n", " datetime.date(2028, 2, 2): 0.8710166892036795,\n", " datetime.date(2029, 2, 2): 0.8487253712490201,\n", " datetime.date(2030, 2, 4): 0.8272911366075278,\n", " datetime.date(2031, 2, 3): 0.8064497105777264,\n", " datetime.date(2032, 2, 2): 0.7855119723826649,\n", " datetime.date(2034, 2, 2): 0.7437425073236228,\n", " datetime.date(2037, 2, 2): 0.6863624721765518,\n", " datetime.date(2042, 2, 3): 0.6021334782242774,\n", " datetime.date(2047, 2, 4): 0.532728469464928,\n", " datetime.date(2052, 2, 2): 0.47440766803920265}" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "MyRatesCurveUSD_LIBOR_6M=RatesCurve('USD_LIBOR_6M','Act360','LinearOnLogDF',now=now)\n", "MyUSDLIBORDeposit6M=InterestRatesSwapProduct(now=now,name='USDLIBORDeposit6M',\n", " Leg1IndexIdentifier='USD_LIBOR_6M',\n", " Leg1Tenor=(0,6,0), \n", " Leg1StartDateLagInDays=2, \n", " Leg1PaymentLagInDays=0, \n", " Leg1FloatingRateSpread=0.0, \n", " Leg1FixedRate=0.0, \n", " Leg1DayCountConvention='Act360',\n", " Leg1IsFixed=False,\n", " Leg1Frequency='6M',\n", " Leg2IndexIdentifier='USD_LIBOR_3M', #инфо\n", " Leg2Tenor=(0,3,0),\n", " Leg2StartDateLagInDays=2,\n", " Leg2PaymentLagInDays=0, #инфо\n", " Leg2FloatingRateSpread=0.55, \n", " Leg2FixedRate=0.0, \n", " Leg2DayCountConvention='Act360',\n", " Leg2IsFixed=False,\n", " Leg2Frequency='3M')\n", "\n", "dictUSDLIBOR6M={'1Y':3, '18M':4,'2Y':6,'3Y':10,'4Y':11,'5Y':12,'6Y':13,'7Y':14,'8Y':14.5,\n", " '9Y':15,'10Y':15.25,'12Y':15.5,'15Y':15.75,'20Y':16,'25Y':16.25,'30Y':16.5}\n", "\n", "\n", "\n", "MasUSDLIBOR6MSwapNames=['USDLIBORDeposit6M']\n", "MasUSDLIBOR6MSwaps=[MyUSDLIBORDeposit6M]\n", "\n", "for i in range(1,2):\n", " MyUSDLIBOR6MSwapiY=MyUSDLIBORDeposit6M.clone(Leg1Tenor=(0,0,i),Leg2Tenor=(0,0,i),Leg2FloatingRateSpread=dictUSDLIBOR6M[str(i)+'Y'],Leg1Frequency='6M',Leg2Frequency='3M',name='USDLIBOR6MSwap'+str(i)+'Y')\n", " MasUSDLIBOR6MSwaps.append(MyUSDLIBOR6MSwapiY)\n", " MasUSDLIBOR6MSwapNames.append('USDLIBOR6MSwap'+str(i)+'Y')\n", " \n", "MyUSDLIBOR6MSwap18M=MyUSDLIBORDeposit6M.clone(Leg1Tenor=(0,6,1),Leg2Tenor=(0,6,1),Leg2FloatingRateSpread=dictUSDLIBOR6M['18M'],Leg1Frequency='6M',Leg2Frequency='3M',name='USDLIBOR6MSwap18M')\n", "MasUSDLIBOR6MSwaps.append(MyUSDLIBOR6MSwapiY)\n", "MasUSDLIBOR6MSwapNames.append('USDLIBOR6MSwap18M')\n", "\n", "for i in range(2,11):\n", " MyUSDLIBOR6MSwapiY=MyUSDLIBORDeposit6M.clone(Leg1Tenor=(0,0,i),Leg2Tenor=(0,0,i),Leg2FloatingRateSpread=dictUSDLIBOR6M[str(i)+'Y'],Leg1Frequency='6M',Leg2Frequency='3M',name='USDLIBOR6MSwap'+str(i)+'Y')\n", " MasUSDLIBOR6MSwaps.append(MyUSDLIBOR6MSwapiY)\n", " MasUSDLIBOR6MSwapNames.append('USDLIBOR6MSwap'+str(i)+'Y')\n", " \n", "for i in [12,15,20,25,30]:\n", " MyUSDLIBOR6MSwapiY=MyUSDLIBORDeposit6M.clone(Leg1Tenor=(0,0,i),Leg2Tenor=(0,0,i),Leg2FloatingRateSpread=dictUSDLIBOR6M[str(i)+'Y'],Leg1Frequency='6M',Leg2Frequency='3M',name='USDLIBOR6MSwap'+str(i)+'Y')\n", " MasUSDLIBOR6MSwaps.append(MyUSDLIBOR6MSwapiY)\n", " MasUSDLIBOR6MSwapNames.append('USDLIBOR6MSwap'+str(i)+'Y')\n", " \n", "\n", "MyMarket3=Market(RatesCurves={'USD_SOFR':MyMarket.RatesCurves['USD_SOFR'], 'USD_LIBOR_3M':MyMarket2.RatesCurves['USD_LIBOR_3M'], 'USD_LIBOR_6M':MyRatesCurveUSD_LIBOR_6M},Swaps={a:b for (a,b) in zip(MasUSDLIBOR6MSwapNames,MasUSDLIBOR6MSwaps)},now=now)\n", "for SwapName in MasUSDLIBOR6MSwapNames:\n", " MyMarket3.solve_for_df(now,SwapName)\n", "\n", "\n", "plt.scatter(MyMarket.RatesCurves['USD_SOFR'].DiscFactors.keys(),MyMarket.RatesCurves['USD_SOFR'].DiscFactors.values())\n", "plt.plot(MyMarket.RatesCurves['USD_SOFR'].DiscFactors.keys(),MyMarket.RatesCurves['USD_SOFR'].DiscFactors.values(),label='USD_SOFR')\n", "plt.scatter(MyMarket2.RatesCurves['USD_LIBOR_3M'].DiscFactors.keys(),MyMarket2.RatesCurves['USD_LIBOR_3M'].DiscFactors.values())\n", "plt.plot(MyMarket2.RatesCurves['USD_LIBOR_3M'].DiscFactors.keys(),MyMarket2.RatesCurves['USD_LIBOR_3M'].DiscFactors.values(),label='USD_LIBOR_6M')\n", "plt.scatter(MyMarket3.RatesCurves['USD_LIBOR_6M'].DiscFactors.keys(),MyMarket3.RatesCurves['USD_LIBOR_6M'].DiscFactors.values())\n", "plt.plot(MyMarket3.RatesCurves['USD_LIBOR_6M'].DiscFactors.keys(),MyMarket3.RatesCurves['USD_LIBOR_6M'].DiscFactors.values(),label='USD_LIBOR_6M')\n", "plt.legend()\n", "plt.show()\n", "MyMarket3.RatesCurves['USD_LIBOR_6M'].DiscFactors\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PVcaplet= 0.1535248274894729\n", "PVcaplet_inarrears= 0.11851554963232741\n" ] } ], "source": [ "class VolSmile:\n", " def __init__(self, Strikes,Vols):\n", " self.Strikes=np.array(Strikes)/100\n", " self.Vols=np.array(Vols)/100\n", " def getvol(self,s):\n", " if (sself.Strikes[-1]):\n", " #print('Extrapolation, Linear')\n", " return np.sqrt(np.interp(s,self.Strikes, self.Vols**2))\n", " \n", " else:\n", " #print(\"Interpolation, Cubic\")\n", " spline=CubicSpline(self.Strikes, self.Vols**2, bc_type='natural')\n", " return np.sqrt(spline(s))\n", " \n", "def PVExpectation(t,T,tau,F,K,sigma):\n", " d=(F-K)/sigma/np.sqrt(T-t)\n", " return sigma*np.sqrt(T-t)*(d*norm.cdf(d)+norm.pdf(d))\n", " \n", "MyCalendar=USCalendar()\n", "Tdate=MyCalendar.add(now, years=2)\n", "Tptaudate=MyCalendar.add(Tdate, months=6)\n", "tdate=now\n", "tau=(Tptaudate-Tdate).days/360\n", "T=(Tdate-now).days/360\n", "t=0\n", "K=3/100\n", "FtTTptau=(MyMarket3.RatesCurves['USD_LIBOR_6M'].get_disc_factor_t_T(now,Tdate)/MyMarket3.RatesCurves['USD_LIBOR_6M'].get_disc_factor_t_T(now,Tptaudate)-1)/tau\n", "\n", "Strikes=[0.25,0.5,0.75,1,1.5,2,2.5,3,4,5,6,7,8,9,10,12,15] #in persent\n", "Vols=[42,38,35,32,29.5,28.3,27.7,27.5,27.7,28.5,30,32,34,36,38,41,43] #in persent\n", "MyVolSmile=VolSmile(Strikes, Vols)\n", "PVcaplet=PVExpectation(t,T,tau,FtTTptau,K,MyVolSmile.getvol(K))\n", "summa_integrala=0\n", "for k in np.linspace(K,30/100, 10000):\n", " #print(\"k=\",k, PVExpectation(t,T,tau,FtTTptau,k,MyVolSmile.getvol(k)))\n", " summa_integrala+=PVExpectation(t,T,tau,FtTTptau,k,MyVolSmile.getvol(k))*(30/100-K)/10000\n", "\n", "df0Tptau=MyMarket3.RatesCurves['USD_LIBOR_6M'].get_disc_factor_t_T(now,Tptaudate)\n", "PVcaplet_inarrears=df0Tptau*tau*((1+K)*PVExpectation(t,T,tau,FtTTptau,K,MyVolSmile.getvol(K))+2*summa_integrala)\n", "PVCaplet=df0Tptau*tau*PVExpectation(t,T,tau,FtTTptau,K,MyVolSmile.getvol(K))\n", "print(\"PVcaplet=\",PVcaplet)\n", "print(\"PVcaplet_inarrears=\",PVcaplet_inarrears)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 2 }