// return forward start swap as same building block used in building curve recalculated starting on custom StartDate, Tenor is the tenor of swap
    public double SwapFwd(Date StartDate, string Tenor)
    {
        // 1. Build the swap. Rate is not important I use 0.0
        SwapStyle myS = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(StartDate, 0.0, Tenor, SwapType.buildingBlockType);

        return(ParRate(myS));
    }
Пример #2
0
    public static double CapBlack(string Tenor, double strike, double N, IRateCurve curve, BilinearInterpolator VolCapletMatrix)
    {
        Date      refDate = curve.RefDate();
        SwapStyle y       = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(refDate, 0, Tenor, curve.GetSwapStyle().buildingBlockType);

        double[] yf       = y.scheduleLeg2.GetYFVect(Dc._Act_360);
        int      toRemove = yf.Length - 1;

        yf = yf.Where((val, inx) => inx != toRemove).ToArray();

        List <Date> ToDate = y.scheduleLeg2.toDates.ToList();

        ToDate.RemoveAt(ToDate.Count - 1);      // remove last element
        double[] T = (from c in ToDate
                      select refDate.YF_365(c)).ToArray();

        // df- getting relevant dates
        Date[] dfDate  = y.scheduleLeg2.payDates;
        int    Ncaplet = yf.Length;   // number of caplets

        double[] df = new double[Ncaplet];
        // fwd rate
        double[] fwd     = new double[Ncaplet];
        Date[]   fwdDate = y.scheduleLeg2.fromDates;

        for (int i = 0; i < Ncaplet; i++) // Note the loop start from 1
        {                                 // first discount factor is on first payment date of caplet (first caplet skipped)
            df[i]  = curve.Df(dfDate[i + 1]);
            fwd[i] = curve.Fwd(fwdDate[i + 1]);
        }

        double[] sigma = (from t in T
                          select VolCapletMatrix.Solve(t, strike)).ToArray();
        return(CapBlack(T, yf, N, strike, sigma, df, fwd));
    }
Пример #3
0
    // calculate forward start swap
    public double SwapFwd(Date StartDate, string Tenor)
    {
        // 1. Build the swap. Rate is not important I use 0.0
        SwapStyle myS = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(StartDate, 0.0, Tenor, SwapType.buildingBlockType);

        // 2. Calculate Par Rate
        // fixed leg data
        double[] yfFixLeg = myS.scheduleLeg1.GetYFVect(myS.swapLeg1.DayCount); // fixed is leg 1

        // dfs array of fixed lag
        double[] dfDates = Date.GetSerialValue(myS.scheduleLeg1.payDates); // serial date of fixed lag (each dates we should find df)
        // Vector<double> k = PostProcessInterpo.Curve(new Vector<double>(dfDates, 0));

        double[] dfFixLeg = PostProcessInterpo.Curve(dfDates); // get interpolated value (i.e. log df or log r or...
        // transform interpolated value back to discount factor
        for (int i = 0; i < yfFixLeg.Length; i
             ++)
        {
            dfFixLeg[i] = interpAdapter.FromInterpToDf(dfFixLeg[i], dfDates[i]);
        }

        // Interpolation Methods for Curve Construction PATRICK S. HAGAN & GRAEME WEST Applied Mathematical Finance,Vol. 13, No. 2, 89–129, June 2006
        // Formula 2) page 4
        double iniDf = interpAdapter.FromInterpToDf(PostProcessInterpo.Solve(StartDate.SerialValue), StartDate.SerialValue);

        return(Formula.ParRate(yfFixLeg, dfFixLeg, iniDf)); // Calculate par rate
    }
    protected void PrePorcessData(RateSet rateSetMC, ISingleRateCurve DiscountingCurve)
    {
        this.refDate    = rateSetMC.refDate;
        this.DCurve     = DiscountingCurve;    // my curve used in discounting
        FWDInterpolator = new Interpolation(); // Interpolator used in fwd
        this.mktRateSet = rateSetMC;           // pass market rate set

        // Create Building block
        IEnumerable <BuildingBlock> BB = mktRateSet.GetArrayOfBB();

        // Sort ascending end date
        BBArray = from c in BB
                  orderby c.endDate.SerialValue ascending
                  select c;

        // Only Given Swap from BBArray
        OnlyGivenSwap = (from c in BBArray
                         where c.GetType().BaseType == typeof(SwapStyle)
                         select(SwapStyle) c).ToArray();


        // validating underlying tenor: swap should be all vs the same tenor
        string UnderlyingTenor = ((SwapStyle)OnlyGivenSwap.First()).swapLeg2.UnderlyingRateTenor;

        // Getting the fixing
        fixing = (from c in BBArray
                  where c.GetType().BaseType == typeof(OnePaymentStyle)
                  where c.endDate == refDate.add_period(UnderlyingTenor)
                  select c.rateValue).Single();

        // From date of each fwd rate from longer swap(LS)
        // FromDatesSerial = Date.GetSerialValue(OnlyGivenSwap.Last().scheduleLeg2.fromDates);
        List <double> SerialDate = (from c in OnlyGivenSwap
                                    select c.scheduleLeg2.fromDates.Last().SerialValue).ToList <double>();

        // adding reference date at beginning (this is important since I use the fixing)
        SerialDate.Insert(0, refDate.SerialValue);
        FromDatesSerial = SerialDate.ToArray();

        // some data validation: swap should be all of same building block

        // the type of building block
        BuildingBlockType BBT = OnlyGivenSwap[0].buildingBlockType;

        // Are all them the same?
        bool IsSameSwapType = OnlyGivenSwap.All(s => s.buildingBlockType == BBT);

        if (IsSameSwapType)  // if true
        {
            // it is swap type used as inputs (i.e. EurSwapVs6m, EurSwapVs3m, ...)
            SwapType = (SwapStyle) new BuildingBlockFactory().CreateEmptyBuildingBlock(BBT);
        }
        else
        {
            throw new ArgumentException("error in building blocktype"); // if not throw an exception
        }
    }
Пример #5
0
    // NPV of swap
    public static double NPV(SwapStyle BB, IRateCurve c, bool PayOrRec)
    {
        #region FixLeg
        // fixed leg data
        double[] yfFixLeg = BB.scheduleLeg1.GetYFVect(BB.swapLeg1.DayCount);     // fixed is leg 1

        // dfs array of fixed lag
        Date[] dfDates = BB.scheduleLeg1.payDates;     // serial date of fixed lag (each dates we should find df)

        // # of fixed cash flows
        int n_fix = dfDates.Length;

        double NPV_fix = 0.0;
        // calculate df
        for (int i = 0; i < n_fix; i++)
        {
            NPV_fix += c.Df(dfDates[i]) * yfFixLeg[i] * BB.rateValue;      // df*yf
        }
        #endregion

        #region FloatLeg
        // floating leg data
        double[] yfFloatLeg = BB.scheduleLeg2.GetYFVect(BB.swapLeg2.DayCount);     // float is leg 2

        // dfs array of fixed lag
        Date[] dfDatesFloat = BB.scheduleLeg2.payDates;     // serial date of float leg (each dates we should find df)

        Date[] FromDateFloat = BB.scheduleLeg2.fromDates;

        // # of floating cash flows
        int n_float = dfDatesFloat.Length;

        double[] fwd = new double[n_float];     // fwd rates container

        // getting fwd rates
        for (int i = 0; i < n_float; i++)
        {
            fwd[i] = c.Fwd(FromDateFloat[i]);
        }

        double NPV_float = 0.0;
        // calculate df
        for (int i = 0; i < n_float; i++)
        {
            NPV_float += c.Df(dfDatesFloat[i]) * yfFloatLeg[i] * fwd[i];      // df*yf
        }

        #endregion
        if (!PayOrRec)
        {
            return(-NPV_fix + NPV_float);
        }                                // Receiver Swap
        return(NPV_fix - NPV_float);     // NPV Payer Swap
    }
Пример #6
0
    public VanillaSwap(IMultiRateCurve MultiCurve, double Rate, string SwapTenor, bool PayOrRec, double Nominal)
    {
        // Standard swap
        Type SwapType  = MultiCurve.GetSwapStyle().GetType();
        Date myRefDate = MultiCurve.RefDate();

        // using reflection
        this.mySwap     = (SwapStyle)Activator.CreateInstance(SwapType, myRefDate, Rate, SwapTenor);
        this.payOrRec   = PayOrRec;
        this.multiCurve = MultiCurve;
        this.nominal    = Nominal;
    }
    private delegate double SwapRate(SwapStyle S);  // used in function to calculate swap rate

    private double ParRate(SwapStyle S)
    {                                                                        // floating leg data
        double[] yfFloatLeg = S.scheduleLeg2.GetYFVect(S.swapLeg2.DayCount); // floating leg is leg 2
        double[] dfFloatLeg = (from c in S.scheduleLeg2.payDates
                               select DCurve.Df(c)).ToArray();
        double[] fwdFloatLeg = (from c in S.scheduleLeg2.fromDates
                                select FWDInterpolator.Solve(c.SerialValue)).ToArray();
        // fixed leg data
        double[] yfFixLeg = S.scheduleLeg1.GetYFVect(S.swapLeg1.DayCount);  // fixed is leg 1
        double[] dfFixLeg = (from c in S.scheduleLeg1.payDates
                             select DCurve.Df(c)).ToArray();

        // calculate par swap rate according to given data
        return(Formula.ParRateFormula(yfFloatLeg, dfFloatLeg, fwdFloatLeg, yfFixLeg, dfFixLeg));
    }
Пример #8
0
    public static double Swaption(double N, double K, string Start, string SwapTenor, bool isPayer, double sigma, IRateCurve Curve)
    {
        Date refDate = Curve.RefDate();                         // curve ref date
        // false/true with fwd swap matrix
        Date      startDate = refDate.add_period(Start, false); // swap start 2 business days after the expiry
        Date      expDate   = startDate.add_workdays(-2);       // expiry of swaption
        Date      today     = refDate.add_workdays(-2);
        double    T         = today.YF_365(expDate);
        Period    p         = new Period(SwapTenor); // should be in year 1Y, 2Y (not 3m,...)
        SwapStyle y         = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(startDate, 0, SwapTenor, Curve.GetSwapStyle().buildingBlockType);

        double[] yf = y.scheduleLeg1.GetYFVect(Dc._30_360);
        double[] df = (from payDay in y.scheduleLeg1.payDates
                       select Curve.Df(payDay)).ToArray();

        return(Swaption(N, Curve.SwapFwd(startDate, SwapTenor), K, sigma, T, isPayer, yf, df));
    }
Пример #9
0
    // constructor
    public CapletMatrixVolBuilder(string[] Tenor, IRateCurve Curve, double[] strike, List <double[]> VolSilos)
    {
        #region preparing data

        // yf of longer cap
        SwapStyle y        = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(Curve.RefDate(), 0, Tenor.Last(), Curve.GetSwapStyle().buildingBlockType);
        double[]  yf       = y.scheduleLeg2.GetYFVect(Dc._Act_360);
        int       toRemove = yf.Length - 1;
        yf = yf.Where((val, inx) => inx != toRemove).ToArray();

        // T all tenor needed. They are more than input
        Date        refDate = Curve.RefDate();
        List <Date> ToDate  = y.scheduleLeg2.toDates.ToList();
        ToDate.RemoveAt(ToDate.Count - 1);    // remove last element
        double[] T = (from c in ToDate
                      select refDate.YF_365(c)).ToArray();

        // available T from input
        double[] Tquoted = new double[Tenor.Length];
        for (int i = 0; i < Tquoted.Length; i++)
        {        // calculate yf of each available T as it was a swap
            SwapStyle myS    = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(Curve.RefDate(), 0, Tenor[i], Curve.GetSwapStyle().buildingBlockType);
            int       L      = myS.scheduleLeg2.toDates.Count() - 1;
            Date[]    toDate = myS.scheduleLeg2.toDates;
            Tquoted[i] = refDate.YF_365(toDate[L - 1]);
        }

        // df- getting relevant dates
        Date[]   dfDate  = y.scheduleLeg2.payDates;
        int      Ncaplet = yf.Length; // number of caplets
        double[] df      = new double[Ncaplet];
        // fwd rate
        double[] fwd     = new double[Ncaplet];
        Date[]   fwdDate = y.scheduleLeg2.fromDates;

        for (int i = 0; i < Ncaplet; i++) // Note the loop start from 1
        {                                 // first discount factor is on first payment date of caplet (first caplet skipped)
            df[i]  = Curve.Df(dfDate[i + 1]);
            fwd[i] = Curve.Fwd(fwdDate[i + 1]);
        }

        #endregion

        Ini(T, df, fwd, yf, Tquoted, VolSilos, strike);
    }
Пример #10
0
    // used in constructor
    private void Ini(string tenor, IRateCurve curve, BilinearInterpolator capletVolMatrix, double nominal)
    {
        stringTenor = tenor;
        rateCurve   = curve;
        volMatrix   = capletVolMatrix;
        N           = nominal;

        // yf of longer cap
        SwapStyle y = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(curve.RefDate(), 0, tenor, curve.GetSwapStyle().buildingBlockType);

        yf          = y.scheduleLeg2.GetYFVect(Dc._Act_360);
        capSchedule = y.scheduleLeg2;
        int toRemove = yf.Length - 1;

        yf = yf.Where((val, inx) => inx != toRemove).ToArray();

        // T all tenor needed. They are more than input
        Date        refDate = curve.RefDate();
        List <Date> ToDate  = y.scheduleLeg2.toDates.ToList();

        ToDate.RemoveAt(ToDate.Count - 1);  // remove last element
        T = (from c in ToDate
             select refDate.YF_365(c)).ToArray();
        // df- getting relevant dates
        Date[] dfDate  = y.scheduleLeg2.payDates;
        int    Ncaplet = yf.Length; // number of caplets

        df = new double[Ncaplet];
        // fwd rate
        fwd = new double[Ncaplet];
        Date[] fwdDate = y.scheduleLeg2.fromDates;

        for (int i = 0; i < Ncaplet; i++) // Note the loop start from 1
        {                                 // first discount factor is on first payment date of caplet (first caplet skipped)
            df[i]  = curve.Df(dfDate[i + 1]);
            fwd[i] = curve.Fwd(fwdDate[i + 1]);
        }
    }
Пример #11
0
    public RateSet mktRateSet;                  // market starting data

    // constructor: RateSet rateSet are market data inputs
    public SingleCurveBuilder(RateSet rateSet)
    {
        // RefDate
        refDate            = rateSet.refDate;
        PostProcessInterpo = new Interpolation(); // Post process interpolator
        interpAdapter      = new DoInterpOn();
        mktRateSet         = rateSet;

        // Create Building block
        IEnumerable <BuildingBlock> BB = rateSet.GetArrayOfBB();

        // Sort ascending end date
        BBArray = from c in BB
                  orderby c.endDate.SerialValue ascending
                  select c;

        // Only Given Swap from BBArray
        OnlyGivenSwap = (from c in BBArray
                         where c.GetType().BaseType == typeof(SwapStyle)
                         select(SwapStyle) c).ToArray();

        // some data validation: swap should be all of same building block
        // the type of building block
        BuildingBlockType BBT = OnlyGivenSwap[0].buildingBlockType;

        // Are all them the same?
        bool IsSameSwapType = OnlyGivenSwap.All(s => s.buildingBlockType == BBT);

        if (IsSameSwapType)  // if true
        {
            // it is swap type used as inputs (i.e. EurSwapVs6m, EurSwapVs3m, ...)
            SwapType = (SwapStyle) new BuildingBlockFactory().CreateEmptyBuildingBlock(BBT);
        }
        else
        {
            throw new ArgumentException("error in building blocktype"); // if not throw an exception
        }
    }
Пример #12
0
    public static double FwdBasis(Date StartDate, string SwapTenor, IRateCurve Curve1, IRateCurve Curve2)
    {
        SwapStyle S1 = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(StartDate, 0.0, SwapTenor, Curve1.GetSwapStyle().buildingBlockType);
        SwapStyle S2 = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(StartDate, 0.0, SwapTenor, Curve2.GetSwapStyle().buildingBlockType);

        double[] yfFloatLeg1 = S1.scheduleLeg2.GetYFVect(S1.swapLeg2.DayCount);

        // using LINQ syntax
        double[] dfFloatLeg1 = (from d in S1.scheduleLeg2.payDates
                                select Curve1.Df(d)).ToArray <double>();
        double[] fwdFloatLeg1 = (from d in S1.scheduleLeg2.fromDates
                                 select Curve1.Fwd(d)).ToArray <double>();

        double[] yfFloatLeg2 = S2.scheduleLeg2.GetYFVect(S2.swapLeg2.DayCount);
        // using LINQ syntax
        double[] dfFloatLeg2 = (from d in S2.scheduleLeg2.payDates
                                select Curve2.Df(d)).ToArray <double>();

        double[] fwdFloatLeg2 = (from d in S2.scheduleLeg2.fromDates
                                 select Curve2.Fwd(d)).ToArray <double>();

        return(SpreadBasisFormula(yfFloatLeg1, dfFloatLeg1, fwdFloatLeg1,
                                  yfFloatLeg2, dfFloatLeg2, fwdFloatLeg2));
    }
Пример #13
0
    // More on sensitivities calc
    public static void MoreOnSensitivities()
    {
        #region Inputs
        // Start input
        Date refDate = new Date(2010, 10, 11);

        // I populate market rates set: from file, from real time, ...
        RateSet mktRates = new RateSet(refDate);

        // Depos
        mktRates.Add(1.243e-2, "1m", BuildingBlockType.EURDEPO);
        mktRates.Add(1.435e-2, "3m", BuildingBlockType.EURDEPO);
        mktRates.Add(1.720e-2, "6m", BuildingBlockType.EURDEPO);
        // Swap Vs 6M
        mktRates.Add(1.869e-2, "1Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(2.316e-2, "2Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(2.544e-2, "3Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(2.745e-2, "4Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(2.915e-2, "5Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.057e-2, "6Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.175e-2, "7Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.273e-2, "8Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.362e-2, "9Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.442e-2, "10Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.589e-2, "12Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.750e-2, "15Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.835e-2, "20Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.787e-2, "25Y", BuildingBlockType.EURSWAP6M);
        #endregion end Inputs

        #region building curve
        List <ISingleRateCurve> Curves = new List <ISingleRateCurve>();

        // initialised each class and add to list. You can add more curves

        // Setup (a) in Table 15.3
        SingleCurveBuilderStandard <OnLogDf, LinearInterpolator> c2 = new SingleCurveBuilderStandard <OnLogDf, LinearInterpolator>(mktRates, OneDimensionInterpolation.Linear); Curves.Add(c2);

        // Setup (b) in Table 15.3
        SingleCurveBuilderSmoothingFwd <OnLogDf, SimpleCubicInterpolator> c1 = new SingleCurveBuilderSmoothingFwd <OnLogDf, SimpleCubicInterpolator>(mktRates); Curves.Add(c1);

        string swapTenor = "11y"; // you can change it
        #endregion end building curve

        #region myFunction
        Func <SwapStyle, IRateCurve, double> NPV = (BB, c) =>
        {
            #region FixLeg
            // fixed leg data
            double[] yfFixLeg = BB.scheduleLeg1.GetYFVect(BB.swapLeg1.DayCount); // fixed is leg 1

            // dfs array of fixed lag
            Date[] dfDates = BB.scheduleLeg1.payDates; // serial date of fixed lag (each dates we should find df)

            // # of fixed cash flows
            int n_fix = dfDates.Length;

            double NPV_fix = 0.0;
            // calculate df
            for (int i = 0; i < n_fix; i++)
            {
                NPV_fix += c.Df(dfDates[i]) * yfFixLeg[i] * BB.rateValue;  // df*yf
            }
            // NPV_fix *= BB.rateValue;
            #endregion

            #region FloatLeg
            // fixed leg data
            double[] yfFloatLeg = BB.scheduleLeg2.GetYFVect(BB.swapLeg2.DayCount); // float is leg 2

            // dfs array of fixed lag
            Date[] dfDatesFloat = BB.scheduleLeg2.payDates; // serial date of float lag (each dates we should find df)

            Date[] toDateFloat = BB.scheduleLeg2.toDates;

            // # of fixed cash flows
            int n_float = dfDatesFloat.Length;

            double[] fwd = new double[n_float];

            fwd[0] = ((1 / c.Df(toDateFloat[0])) - 1) / refDate.YF(toDateFloat[0], Dc._Act_360);;
            for (int i = 1; i < n_float; i++)
            {
                double yf     = toDateFloat[i - 1].YF(toDateFloat[i], Dc._Act_360);
                double df_ini = c.Df(toDateFloat[i - 1]);
                double df_end = c.Df(toDateFloat[i]);
                fwd[i] = ((df_ini / df_end) - 1) / yf;
            }

            double NPV_float = 0.0;
            // calculate df
            for (int i = 0; i < n_float; i++)
            {
                NPV_float += c.Df(dfDatesFloat[i]) * yfFloatLeg[i] * fwd[i];  // df*yf
            }

            #endregion
            return(NPV_fix - NPV_float);
        };
        #endregion

        #region Print results
        foreach (ISingleRateCurve C in Curves)
        {
            double swapRate = C.SwapFwd(refDate, swapTenor);

            IRateCurve[] cs = C.ShiftedCurveArray(0.0001); IRateCurve csp = C.ParallelShift(0.0001);

            // initialise some variable used in sensitivities
            double sens   = 0.0;
            double runSum = 0.0;

            // standard
            Console.WriteLine(C.ToString());
            SwapStyle y      = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(refDate, swapRate, swapTenor, BuildingBlockType.EURSWAP6M);
            double    iniMTM = NPV(y, C) * 100000000;
            Console.WriteLine("{0} swap ATM fwd: {1:f5}", swapTenor, swapRate);
            Console.WriteLine("Starting P&L {0:f}", iniMTM);
            int nOfRate = mktRates.Count;
            for (int i = 0; i < nOfRate; i++)
            {
                sens = NPV(y, cs[i]) * 100000000 - iniMTM;
                Console.WriteLine("{0} BPV: {1:f}", mktRates.Item(i).M.GetPeriodStringFormat(), sens);
                runSum += sens;
            }
            Console.WriteLine("Total: {0:f}", runSum);
            Console.WriteLine("Parallel Total: {0:f}", NPV(y, csp) * 100000000 - iniMTM);

            Console.WriteLine("Press a key to continue"); Console.ReadLine();
        }
        #endregion
    }
Пример #14
0
    // Prepare data to be used in Solve()
    protected override void PreProcessInputs()
    {
        /*
         * 1) Check if input data are ok (data validation): from date contained
         * 2) I choose the Longer Swap (LS)
         * 3) I get array of dates of payment of LS (pass it to data member)
         * 4) I get array of year fraction of LS (pass it to data member)
         */

        // From date of each fwd rate from longer swap(LS)
        List <double> FromDatesSerial = Date.GetSerialValue(OnlyGivenSwap.Last().scheduleLeg2.fromDates).ToList <double>();

        // validating underlying tenor: swap should be all vs the same tenor
        string UnderlyingTenor = ((SwapStyle)OnlyGivenSwap.First()).swapLeg2.UnderlyingRateTenor;

        foreach (SwapStyle b in OnlyGivenSwap)
        {
            // Check if contained
            if (!FromDatesSerial.Contains(((SwapStyle)b).scheduleLeg2.fromDates.Last().SerialValue))
            {
                throw new ArgumentException("From date not contained");
            }
        }

        DateDf = new SortedList <double, double>(); // Inizialize DateDF
        DateDf.Add(refDate.SerialValue, 1.0);       // first discount factor
        // IEnumerable<KeyValuePair<double,double>>
        var f = from c in BBArray
                where c.GetType().BaseType == typeof(OnePaymentStyle)
                where c.endDate != refDate.add_period(UnderlyingTenor)
                let yf                   = refDate.YF(c.endDate, c.dayCount) // year fraction
                                  let df = Formula.DFsimple(yf, c.rateValue) // calculate discount factor
                                           select new KeyValuePair <double, double>(c.endDate.SerialValue, df);

        foreach (KeyValuePair <double, double> kpv in f)
        {
            DateDf.Add(kpv.Key, kpv.Value);
        }

        // Getting the fixing
        fixing = (from c in BBArray
                  where c.GetType().BaseType == typeof(OnePaymentStyle)
                  where c.endDate == refDate.add_period(UnderlyingTenor)
                  select c.rateValue).Single();


        // Inizialize some data member
        SwapStyle LongerSwap = OnlyGivenSwap.Last(); // Swap with longer maturity

        // Year Fraction of floating leg of longer swap. It is needed to calculate DF
        yfFloatLegLongerSwap = LongerSwap.scheduleLeg2.GetYFVect(LongerSwap.swapLeg2.DayCount); // floating leg is leg 2

        // Dates on which I calculate Df
        DatesDfLongerSwap = Date.GetSerialValue(LongerSwap.scheduleLeg2.payDates);

        // number of fwd rate to find
        N = DatesDfLongerSwap.Length;

        // fwd rate of longer swap
        fwdGuessLongerSwap    = new double[N];
        fwdGuessLongerSwap[0] = fixing;  // first is the fixing
    }
Пример #15
0
    // sensitivities/DVO1. ATM swap has no sensitivities with respect to the discount curve
    public static void SensitivitiesParallel()
    {
        #region Inputs
        // Start input
        // Start input, reference date.
        Date refDate = (new Date(DateTime.Now)).mod_foll();
        #region Eonia market data
        // I populate market rates set: from file, from real time, ...
        RateSet mktRates = new RateSet(refDate);

        mktRates.Add(0.447e-2, "1w", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.583e-2, "2w", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.627e-2, "3w", BuildingBlockType.EONIASWAP);

        mktRates.Add(0.635e-2, "1m", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.675e-2, "2m", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.705e-2, "3m", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.734e-2, "4m", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.758e-2, "5m", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.780e-2, "6m", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.798e-2, "7m", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.816e-2, "8m", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.834e-2, "9m", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.849e-2, "10m", BuildingBlockType.EONIASWAP);
        mktRates.Add(0.864e-2, "11m", BuildingBlockType.EONIASWAP);

        mktRates.Add(0.878e-2, "1Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(1.098e-2, "2Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(1.36e-2, "3Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(1.639e-2, "4Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(1.9e-2, "5Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(2.122e-2, "6Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(2.308e-2, "7Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(2.467e-2, "8Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(2.599e-2, "9Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(2.715e-2, "10Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(2.818e-2, "11Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(2.908e-2, "12Y", BuildingBlockType.EONIASWAP);
        // From here interpolation is need
        mktRates.Add(3.093e-2, "15Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(3.173e-2, "20Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(3.114e-2, "25Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(3.001e-2, "30Y", BuildingBlockType.EONIASWAP);
        #endregion

        #region Swap Market Data
        // RateSet EUR 6m swap
        RateSet rs = new RateSet(refDate);
        rs.Add(1.16e-2, "6m", BuildingBlockType.EURDEPO);
        rs.Add(1.42e-2, "1y", BuildingBlockType.EURSWAP6M);
        rs.Add(1.635e-2, "2y", BuildingBlockType.EURSWAP6M);
        rs.Add(1.872e-2, "3y", BuildingBlockType.EURSWAP6M);
        rs.Add(2.131e-2, "4y", BuildingBlockType.EURSWAP6M);
        rs.Add(2.372e-2, "5y", BuildingBlockType.EURSWAP6M);
        rs.Add(2.574e-2, "6y", BuildingBlockType.EURSWAP6M);
        rs.Add(2.743e-2, "7y", BuildingBlockType.EURSWAP6M);
        rs.Add(2.886e-2, "8y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.004e-2, "9y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.107e-2, "10y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.198e-2, "11y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.278e-2, "12y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.344e-2, "13y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.398e-2, "14y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.438e-2, "15y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.467e-2, "16y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.484e-2, "17y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.494e-2, "18y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.495e-2, "19y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.491e-2, "20y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.483e-2, "21y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.471e-2, "22y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.455e-2, "23y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.436e-2, "24y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.415e-2, "25y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.391e-2, "26y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.366e-2, "27y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.340e-2, "28y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.314e-2, "29y", BuildingBlockType.EURSWAP6M);
        rs.Add(3.29e-2, "30y", BuildingBlockType.EURSWAP6M);
        #endregion

        #endregion end Inputs

        #region building curve

        string swapTenor = "11y"; // you can change it

        // I build my multi curve,
        SingleCurveBuilderStandard <OnLogDf, SimpleCubicInterpolator> DCurve = new SingleCurveBuilderStandard <OnLogDf, SimpleCubicInterpolator>(mktRates, OneDimensionInterpolation.LogLinear); // discount curve
        MultiCurveBuilder <SimpleCubicInterpolator> C = new MultiCurveBuilder <SimpleCubicInterpolator>(rs, DCurve);                                                                             // multi curve
        #endregion end building curve

        #region myFunction
        // my function to calculate Net Present Value of a Vanilla Swap (receiver swap)
        Func <SwapStyle, IRateCurve, double> NPV = (BB, c) =>
        {
            #region FixLeg
            // fixed leg data
            double[] yfFixLeg = BB.scheduleLeg1.GetYFVect(BB.swapLeg1.DayCount); // fixed is leg 1

            // dfs array of fixed lag
            Date[] dfDates = BB.scheduleLeg1.payDates; // serial date of fixed lag (each dates we should find df)

            // # of fixed cash flows
            int n_fix = dfDates.Length;

            double NPV_fix = 0.0;
            // calculate df
            for (int i = 0; i < n_fix; i++)
            {
                NPV_fix += c.Df(dfDates[i]) * yfFixLeg[i] * BB.rateValue;  // df*yf
            }
            // NPV_fix *= BB.rateValue;
            #endregion

            #region FloatLeg
            // fixed leg data
            double[] yfFloatLeg = BB.scheduleLeg2.GetYFVect(BB.swapLeg2.DayCount); // float is leg 2

            // dfs array of fixed lag
            Date[] dfDatesFloat = BB.scheduleLeg2.payDates; // serial date of float lag (each dates we should find df)

            Date[] FromDateFloat = BB.scheduleLeg2.fromDates;

            // # of fixed cash flows
            int n_float = dfDatesFloat.Length;

            double[] fwd = new double[n_float]; // fwd rate container

            // getting fwd rates
            for (int i = 0; i < n_float; i++)
            {
                fwd[i] = c.Fwd(FromDateFloat[i]);
            }

            double NPV_float = 0.0;
            // calculate df
            for (int i = 0; i < n_float; i++)
            {
                NPV_float += c.Df(dfDatesFloat[i]) * yfFloatLeg[i] * fwd[i];  // df*yf
            }

            #endregion
            return(NPV_fix - NPV_float);  // NPV
        };
        #endregion

        #region Print results

        double atmSwap = C.SwapFwd(refDate, swapTenor);   // At The Money swap (i.e. par rate)

        List <double> swapRateList = new List <double>(); // lists of  swap to analyze
        swapRateList.Add(atmSwap);                        // it is ATM
        swapRateList.Add(atmSwap + 0.01);                 // it has positive mark to market (MtM). It is a receiver swap with a contract rate > than Atm)
        swapRateList.Add(atmSwap - 0.01);                 // it has negative MtM

        // iterate for each swap:
        // see how change the sign of sensitivities for discount curve and for forwarding curve changing contract rates
        Console.WriteLine("Executing parallel loop...");
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();

        Parallel.ForEach(swapRateList, swapRate =>
        {
            Console.WriteLine("Pricing Receiver Swap {0}, Atm Rate: {1:f6}, Contract Rate: {2:f6}", swapTenor, atmSwap, swapRate);
            IRateCurve[] cs = C.ShiftedCurvesArrayFwdCurve(0.0001);
            IRateCurve csp  = C.ParallelShiftFwdCurve(0.0001);

            // initialise some variable used in sensitivities
            double sens   = 0.0;
            double runSum = 0.0;

            // Standard swap
            SwapStyle y   = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(refDate, swapRate, swapTenor, BuildingBlockType.EURSWAP6M);
            double iniMTM = NPV(y, C) * 100000000;  // initial mark to market for 100ml receiver contract

            Console.WriteLine("Starting Mark To Market {0:f}", iniMTM);
            Console.WriteLine("Sensitivities to Curve used for forward rate: ");
            int nOfRate = rs.Count;  // iterate for market input for forwarding curve
            for (int i = 0; i < nOfRate; i++)
            {
                sens = NPV(y, cs[i]) * 100000000 - iniMTM;
                Console.WriteLine("{0} BPV: {1:f}", rs.Item(i).M.GetPeriodStringFormat(), sens);
                runSum += sens;
            }
            Console.WriteLine("Total: {0:f}", runSum);
            Console.WriteLine("\nParallel Shift Total: {0:f}", NPV(y, csp) * 100000000 - iniMTM); // parallel shift

            // reset some variable used in sensitivities
            sens   = 0.0;
            runSum = 0.0;

            Console.WriteLine("Sensitivities to Discount Curve:");
            // let's consider discounting curve
            IRateCurve[] DCrvs    = C.ShiftedCurvesArrayDCurve(0.0001); // shifting each bucket
            IMultiRateCurve DCrvp = C.ParallelShiftDCurve(0.0001);      // parallel shift
            nOfRate = mktRates.Count;                                   // iterate for market input for discounting curve
            for (int i = 0; i < nOfRate; i++)
            {
                sens = NPV(y, DCrvs[i]) * 100000000 - iniMTM;
                Console.WriteLine("{0} BPV: {1:f}", mktRates.Item(i).M.GetPeriodStringFormat(), sens);
                runSum += sens;
            }
            Console.WriteLine("Total: {0:f}", runSum);
            Console.WriteLine("\nParallel Shift Total: {0:f}", NPV(y, DCrvp) * 100000000 - iniMTM);
        });

        stopwatch.Stop();
        Console.WriteLine("Parallel loop time in milliseconds: {0}", stopwatch.ElapsedMilliseconds);
        #endregion
    }
Пример #16
0
    // Print on excel forward rate using different curve builder for 3m
    public static void CheckFwdRatesVs3m()
    {
        #region Inputs
        // Start input
        Date refDate = (new Date(DateTime.Now)).mod_foll();

        // I populate market rates set: from file, from real time, ...
        RateSet mktRates = new RateSet(refDate);

        // Depos
        mktRates.Add(0.434e-2, "3m", BuildingBlockType.EURDEPO);

        // Swap Vs 3M
        mktRates.Add(0.813e-2, "1Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(1.096e-2, "2Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(1.322e-2, "3Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(1.529e-2, "4Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(1.709e-2, "5Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(1.862e-2, "6Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(1.991e-2, "7Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(2.101e-2, "8Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(2.197e-2, "9Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(2.285e-2, "10Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(2.443e-2, "12Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(2.614e-2, "15Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(2.711e-2, "20Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(2.671e-2, "25Y", BuildingBlockType.EURSWAP3M);
        mktRates.Add(2.589e-2, "30Y", BuildingBlockType.EURSWAP3M);
        #endregion end Inputs

        #region building curve

        SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator> C1 = new SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator>(mktRates);
        double firstFixing = 0.434e-2; SingleCurveBuilderSmoothingFwd <OnLogDf, SimpleCubicInterpolator> C2 = new SingleCurveBuilderSmoothingFwd <OnLogDf, SimpleCubicInterpolator>(mktRates, firstFixing);
        SingleCurveBuilderStandard <OnLogDf, LinearInterpolator> C3 = new SingleCurveBuilderStandard <OnLogDf, LinearInterpolator>(mktRates, OneDimensionInterpolation.Linear);
        #endregion end building curve

        List <IRateCurve> CurveList   = new List <IRateCurve>(); // list containing curve
        List <string>     CurveString = new List <string>();     // list containing labels

        // populate lists
        CurveList.Add(C1); CurveString.Add(C1.ToString());
        CurveList.Add(C2); CurveString.Add(C2.ToString());
        CurveList.Add(C3); CurveString.Add(C3.ToString());

        #region printing output
        // I get the longer swap
        SwapStyle LS = (SwapStyle)mktRates.GetArrayOfBB().Last();

        Dc     dc       = Dc._Act_360;
        Date[] FromDate = LS.scheduleLeg2.fromDates;
        Date[] ToDate   = LS.scheduleLeg2.toDates;
        int    N        = FromDate.Length;
        List <Vector <double> > Fwds = new List <Vector <double> >();
        double[] dt = new double[N];
        for (int i = 0; i < N; i++)
        {
            dt[i] = FromDate[0].YF(ToDate[i], Dc._30_360);
        }

        foreach (IRateCurve myC in CurveList)
        {
            double[] fwd = new double[N];
            for (int i = 0; i < N; i++)
            {
                double yf     = FromDate[i].YF(ToDate[i], dc);
                double df_ini = myC.Df(FromDate[i]);
                double df_end = myC.Df(ToDate[i]);
                fwd[i] = ((df_ini / df_end) - 1) / yf;
            }
            Fwds.Add(new Vector <double>(fwd));
        }

        ExcelMechanisms exl = new ExcelMechanisms();

        exl.printInExcel(new Vector <double>(dt), CurveString, Fwds, "Fwd vs 3M", "time", "rate"); // .printInExcel<T>
        #endregion end printing output
    }
Пример #17
0
    // Print on excel forward rate using different curve builder for OIS fwd 3m
    public static void CheckFwdRatesOIS3m()
    {
        #region Inputs
        // ref date
        Date refDate = (new Date(DateTime.Now)).mod_foll();

        // I populate market rates set: from file, from real time, ...
        RateSet mktRates = new RateSet(refDate);

        mktRates.Add(2.338e-2, "1d", BuildingBlockType.EURDEPO);    //
        mktRates.Add(2.272e-2, "1w", BuildingBlockType.EONIASWAP);  //
        mktRates.Add(2.241e-2, "2w", BuildingBlockType.EONIASWAP);  //
        mktRates.Add(2.16e-2, "3w", BuildingBlockType.EONIASWAP);   //
        mktRates.Add(2.226e-2, "1m", BuildingBlockType.EONIASWAP);  //
        mktRates.Add(2.299e-2, "2m", BuildingBlockType.EONIASWAP);  //
        mktRates.Add(2.323e-2, "3m", BuildingBlockType.EONIASWAP);  //
        mktRates.Add(2.344e-2, "4m", BuildingBlockType.EONIASWAP);  //
        mktRates.Add(2.371e-2, "5m", BuildingBlockType.EONIASWAP);  //
        mktRates.Add(2.39e-2, "6m", BuildingBlockType.EONIASWAP);   //
        mktRates.Add(2.41e-2, "7m", BuildingBlockType.EONIASWAP);   //
        mktRates.Add(2.4316e-2, "8m", BuildingBlockType.EONIASWAP); //
        mktRates.Add(2.449e-2, "9m", BuildingBlockType.EONIASWAP);  //
        mktRates.Add(2.466e-2, "10m", BuildingBlockType.EONIASWAP); //
        mktRates.Add(2.48e-2, "11m", BuildingBlockType.EONIASWAP);  //

        mktRates.Add(2.529e-2, "15m", BuildingBlockType.EONIASWAP); //
        mktRates.Add(2.565e-2, "18m", BuildingBlockType.EONIASWAP); //
        mktRates.Add(2.603e-2, "21m", BuildingBlockType.EONIASWAP); //

        mktRates.Add(2.493e-2, "1Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(2.644e-2, "2Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(2.849e-2, "3Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(3.08e-2, "4Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(3.292e-2, "5Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(3.471e-2, "6Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(3.621e-2, "7Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(3.748e-2, "8Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(3.86e-2, "9Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(3.965e-2, "10Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(4.064e-2, "11Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(4.155e-2, "12Y", BuildingBlockType.EONIASWAP);
        // From here interpolation is need
        mktRates.Add(4.358e-2, "15Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(4.48e-2, "20Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(4.465e-2, "25Y", BuildingBlockType.EONIASWAP);
        mktRates.Add(4.415e-2, "30Y", BuildingBlockType.EONIASWAP);

        List <IRateCurve> CurveList   = new List <IRateCurve>(); // list containing curve
        List <string>     CurveString = new List <string>();     // list containing labels

        #endregion end Inputs

        #region building curve
        SingleCurveBuilderStandard <OnDf, LinearInterpolator> C1 = new SingleCurveBuilderStandard <OnDf, LinearInterpolator>(mktRates, OneDimensionInterpolation.Linear);
        SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator> C2 = new SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator>(mktRates);
        #endregion end building curve

        // populate lists
        CurveList.Add(C1); CurveString.Add(C1.ToString());
        CurveList.Add(C2); CurveString.Add(C2.ToString());

        #region printing output
        // I get the longer eonia swap available from the input data
        SwapStyle LS = (SwapStyle)mktRates.GetArrayOfBB().Last();
        Schedule  s  = new Schedule(refDate, LS.endDate, "3m", Rule.Backward, LS.swapLeg1.SwapBusDayRollsAdj, "0d", LS.swapLeg1.SwapBusDayPayAdj);

        Dc     dc       = Dc._Act_360;
        Date[] FromDate = s.fromDates;
        Date[] ToDate   = s.toDates;
        int    N        = FromDate.Length;
        List <Vector <double> > Fwds = new List <Vector <double> >();
        double[] dt = new double[N];
        for (int i = 0; i < N; i++)
        {
            dt[i] = FromDate[0].YF(ToDate[i], Dc._30_360);
        }

        foreach (IRateCurve myC in CurveList)
        {
            double[] fwd = new double[N];
            for (int i = 0; i < N; i++)
            {
                double yf     = FromDate[i].YF(ToDate[i], dc);
                double df_ini = myC.Df(FromDate[i]);
                double df_end = myC.Df(ToDate[i]);
                fwd[i] = ((df_ini / df_end) - 1) / yf;
            }
            Fwds.Add(new Vector <double>(fwd));
        }

        ExcelMechanisms exl = new ExcelMechanisms();

        exl.printInExcel(new Vector <double>(dt), CurveString, Fwds, "Fwd 3M", "time", "rate"); // .printInExcel<T>
        #endregion end printing output
    }
Пример #18
0
    // Calculate sensitivities
    public static void Sensitivities()
    {
        #region Inputs
        // Start input
        Date refDate = new Date(2019, 2, 25);

        // I populate market rates set: from file, from real time, ...
        RateSet mktRates = new RateSet(refDate);

        // Depos
        mktRates.Add(1.243e-2, "1m", BuildingBlockType.EURDEPO);
        mktRates.Add(1.435e-2, "3m", BuildingBlockType.EURDEPO);
        mktRates.Add(1.720e-2, "6m", BuildingBlockType.EURDEPO);
        // Swap Vs 6M
        mktRates.Add(1.869e-2, "1Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(2.316e-2, "2Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(2.544e-2, "3Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(2.745e-2, "4Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(2.915e-2, "5Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.057e-2, "6Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.175e-2, "7Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.273e-2, "8Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.362e-2, "9Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.442e-2, "10Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.589e-2, "12Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.750e-2, "15Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.835e-2, "20Y", BuildingBlockType.EURSWAP6M);
        mktRates.Add(3.787e-2, "25Y", BuildingBlockType.EURSWAP6M);

        // I shift 1bp up 10y swap input rate
        int     IndexShifted = 12;
        RateSet mktRates2    = mktRates.ShiftedRateSet(IndexShifted, 0.0001);

        // print out first and second market input rates
        for (int i = 0; i < mktRates.Count; i++)
        {
            Console.WriteLine("First: {0} {1}  Second: {2} {3}", mktRates.Item(i).M.GetPeriodStringFormat(), mktRates.Item(i).V, mktRates2.Item(i).M.GetPeriodStringFormat(), mktRates2.Item(i).V);
        }
        #endregion end Inputs

        #region building curve

        // First curve: using markets rates
        SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator> c1 = new SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator>(mktRates);
        // Second curve: like c1 but 10Y input rate is shifted
        SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator> c2 = new SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator>(mktRates2);
        string swapTenor = "10y"; // you can change it
        #endregion end building curve

        #region myFunction
        Func <SwapStyle, IRateCurve, double> NPV = (BB, c) =>
        {
            #region FixLeg
            // fixed leg data
            double[] yfFixLeg = BB.scheduleLeg1.GetYFVect(BB.swapLeg1.DayCount); // fixed is leg 1

            // dfs array of fixed lag
            Date[] dfDates = BB.scheduleLeg1.payDates; // serial date of fixed lag (each dates we should find df)

            // # of fixed cash flows
            int n_fix = dfDates.Length;

            double NPV_fix = 0.0;
            // calculate df
            for (int i = 0; i < n_fix; i++)
            {
                NPV_fix += c.Df(dfDates[i]) * yfFixLeg[i] * BB.rateValue;  // df*yf
            }
            // NPV_fix *= BB.rateValue;
            #endregion

            #region FloatLeg
            // fixed leg data
            double[] yfFloatLeg = BB.scheduleLeg2.GetYFVect(BB.swapLeg2.DayCount); // float is leg 2

            // dfs array of fixed lag
            Date[] dfDatesFloat = BB.scheduleLeg2.payDates; // serial date of float lag (each dates we should find df)

            Date[] toDateFloat = BB.scheduleLeg2.toDates;

            // # of fixed cash flows
            int n_float = dfDatesFloat.Length;

            double[] fwd = new double[n_float];

            fwd[0] = ((1 / c.Df(toDateFloat[0])) - 1) / refDate.YF(toDateFloat[0], Dc._Act_360);;
            for (int i = 1; i < n_float; i++)
            {
                double yf     = toDateFloat[i - 1].YF(toDateFloat[i], Dc._Act_360);
                double df_ini = c.Df(toDateFloat[i - 1]);
                double df_end = c.Df(toDateFloat[i]);
                fwd[i] = ((df_ini / df_end) - 1) / yf;
            }

            double NPV_float = 0.0;
            // calculate df
            for (int i = 0; i < n_float; i++)
            {
                NPV_float += c.Df(dfDatesFloat[i]) * yfFloatLeg[i] * fwd[i];  // df*yf
            }

            #endregion
            return(NPV_fix - NPV_float);
        };
        #endregion

        #region Print results

        // test forward swap starting in ref date (it should be like simple spot swap)
        double swapRate = c1.SwapFwd(refDate, swapTenor);

        // I create the swap according to standard convention
        SwapStyle y = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(refDate, swapRate, swapTenor, BuildingBlockType.EURSWAP6M);

        // initial NPV
        double iniMTM = NPV(y, c1) * 100000000;

        // print out
        Console.WriteLine("IRS to be priced tenor: {0}. IRS to be priced rate: {1:f5}", swapTenor, swapRate);
        Console.WriteLine("{0} swap ATM fwd according the starting curve: {1:f5}. Starting P&L {2:f}", swapTenor, swapRate, iniMTM);
        Console.WriteLine("Let's shift {0} rate from {1:f5} to {2:f5}", mktRates.Item(IndexShifted).M.GetPeriodStringFormat(), mktRates.Item(IndexShifted).V, mktRates2.Item(IndexShifted).V);

        // NPV after shift
        double endMTM = NPV(y, c2) * 100000000;
        Console.WriteLine("{0} swap ATM fwd after shifting: {1:f5}. P&L after shifting {2:f}", swapTenor, c2.SwapFwd(refDate, swapTenor), endMTM);
        Console.WriteLine("Press a key to continue"); Console.ReadLine();
        #endregion
    }