public void OutputCsvCashflows(string filepath) { using (var sw = new System.IO.StreamWriter(filepath, false)) { sw.WriteLine(Cashflow.ToStringValuesHeader()); for (int i = 0; i < _cashflows.Length; ++i) { sw.WriteLine(_cashflows[i].ToStringValues()); } } }
/// <summary> /// 標準的なヨーロピアンスワップションの簡易化された条件を取得する. /// スワップレートは後で設定すること。 /// リセット日の日付調整は実施していない。 /// 利払い日が次のCFのリセット日になっている。 /// 権利行使日はリセット日に一致させる。 /// 必要ならいくつか条件を細かく改修すること。 /// </summary> /// <param name="startResetDate"></param> /// <param name="resetIntervalMonths"></param> /// <param name="cashflowNumber"></param> /// <param name="exerciseDate"></param> /// <param name="cashflows"></param> static public void GetSwaptionCondition(DateTime startResetDate, int resetIntervalMonths, int cashflowNumber , out DateTime[] exerciseDate, out Cashflow[] cashflows) { exerciseDate = new DateTime[1] { startResetDate }; cashflows = new Cashflow[cashflowNumber]; for (int i = 0; i < cashflows.Length; ++i) { cashflows[i] = new Cashflow(startResetDate.AddMonths(resetIntervalMonths * i) , startResetDate.AddMonths(resetIntervalMonths * (i + 1)) , 0D); } }
/// <summary> /// 分割後の区間を取得 /// </summary> /// <param name="baseDate"></param> /// <param name="leftDate"></param> /// <param name="rightDate"></param> /// <param name="divideIntervalDays"></param> /// <param name="isLeftDiscountBondPriceMaturity"></param> /// <param name="isRightExerciseDate"></param> /// <param name="leftTreeTimeIndex"></param> /// <param name="force">分割できないときも分割結果を取得するときはtrue(オプション引数デフォルトfalse)</param> public bool SetTimeInterval(DateTime baseDate, DateTime leftDate, DateTime rightDate, double divideIntervalDays , bool isLeftDiscountBondPriceMaturity, bool isRightExerciseDate , Cashflow cashflow, ref int leftTreeTimeIndex, bool force = false) { /// 分割できないときはfalse if (!DivideTimeInterval(baseDate, leftDate, rightDate, divideIntervalDays)) { if (!force) { return(false); } } ; IsDiscountBondPriceMaturity = isLeftDiscountBondPriceMaturity; IsExerciseDate = isRightExerciseDate; this.cashflow = cashflow; MinTreeTimeIndex = leftTreeTimeIndex; MaxTreeTimeIndex = leftTreeTimeIndex + TreeTimes.Length - 1; leftTreeTimeIndex = MaxTreeTimeIndex; return(true); }
/// <summary> /// 評価対象バミューダンスワップション情報を用いてツリー分割区間を構成する. /// 権利行使日と基準日が一致するとき、権利行使未実施かつ当日行使可能とみなして評価する。 /// 基準日当日の権利を失っているものとして評価するときは、その権利行使日を入力しないこと。 /// </summary> /// <param name="baseDate"></param> /// <param name="exerciseDates"></param> /// <param name="cashflows"></param> /// <param name="divideIntervalDays"></param> public void DivideTimeIntervals(DateTime baseDate, DateTime[] exerciseDates, Cashflow[] cashflows , double[] divideIntervalDays) { Debug.Assert(cashflows.Length <= divideIntervalDays.Length); Debug.Assert(exerciseDates.Length > 0); Debug.Assert(DateTime.Compare(baseDate, exerciseDates[0]) <= 0); _baseDate = baseDate; _cashflows = cashflows; _exerciseDates = exerciseDates; timeIntervals = new List <TimeInterval>(); int treeTimeIndex = 0; /// cashflow index int cashflowIndex = 0; Cashflow cf = cashflows[cashflowIndex]; TimeInterval tval = new TimeInterval(); /// 初回の扱い : 権利行使日と基準日が一致するときも追加する if (tval.SetTimeInterval(baseDate, baseDate, exerciseDates[0], (double)divideIntervalDays[0], false, true, cf, ref treeTimeIndex, true)) { timeIntervals.Add(tval); } /// 2つめの権利行使時点から最後の権利行使時点まで。 for (int i = 1; i < exerciseDates.Length; ++i) { cf = cashflows[cashflowIndex]; /// 実装チェック Debug.Assert(DateTime.Compare(exerciseDates[i - 1], cf.ResetDate) <= 0); /// 次の権利行使時点が直近のcf.ResetDateよりも手前かどうかで分ける; /// 複数の権利行使時点があるとき /// [i-1番目の権利行使時点, i番目の権利行使時点] /// 権利行使日 = リセット日となるケースを含めることに注意 if (DateTime.Compare(exerciseDates[i], cf.ResetDate) <= 0) { tval = new TimeInterval(); ///このTimeIntervalの右端が権利行使時点 if (tval.SetTimeInterval(baseDate, exerciseDates[i - 1], exerciseDates[i], divideIntervalDays[i] , false, true, cf, ref treeTimeIndex)) { timeIntervals.Add(tval); } continue; } Debug.Assert(DateTime.Compare(exerciseDates[i], cf.ResetDate) > 0); /// [i-1番目の権利行使時点, cashflowIndexのリセット時点] /// ただディスカウントする期間 /// cashflowIndexを更新しないことに注意 tval = new TimeInterval(); ///このTimeIntervalの右端が権利行使時点でない if (tval.SetTimeInterval(baseDate, exerciseDates[i - 1], cf.ResetDate, divideIntervalDays[i] , false, false, cf, ref treeTimeIndex)) { timeIntervals.Add(tval); } /// 次のcashflowのリセット時点がi番目の権利行使日よりも手前かどうかで場合わけ /// 次のcashflowがないときはパス while (cashflowIndex + 1 < cashflows.Length && DateTime.Compare(cashflows[cashflowIndex + 1].ResetDate, exerciseDates[i]) < 0) { Cashflow nextCf = cashflows[cashflowIndex + 1]; /// [cashflowIndexのリセット時点, 次のcashflowIndexのリセット時点] tval = new TimeInterval(); if (tval.SetTimeInterval(baseDate, cf.ResetDate, nextCf.ResetDate, divideIntervalDays[i] , true, false, cf, ref treeTimeIndex)) { timeIntervals.Add(tval); } cashflowIndex++; cf = cashflows[cashflowIndex]; } /// [cashflowIndexのリセット時点, i番目の権利行使時点] /// このTimeIntervalの左端を満期とする債券価格を考える tval = new TimeInterval(); if (tval.SetTimeInterval(baseDate, cf.ResetDate, exerciseDates[i], divideIntervalDays[i] , true, true, cf, ref treeTimeIndex)) { timeIntervals.Add(tval); } /// cashflow Indexの更新 cashflowIndex++; } /// 最終権利行使時点以降 /// [最後の権利行使時点, cashflowIndexのリセット時点] /// ただディスカウントする期間 /// cashflowIndexを更新しないことに注意 tval = new TimeInterval(); if (tval.SetTimeInterval(baseDate, exerciseDates[exerciseDates.Length - 1] , cashflows[cashflowIndex].ResetDate, divideIntervalDays[exerciseDates.Length - 1] , false, false, cf, ref treeTimeIndex)) { timeIntervals.Add(tval); } /// [cashflowIndexのリセット時点, 次のcashflowIndexのリセット時点 = このcashflowのSettlement] while (cashflowIndex < cashflows.Length) { tval = new TimeInterval(); if (tval.SetTimeInterval(baseDate, cashflows[cashflowIndex].ResetDate, cashflows[cashflowIndex].SettlementDate , divideIntervalDays[cashflowIndex], true, false, cf, ref treeTimeIndex)) { timeIntervals.Add(tval); } cashflowIndex++; } }