249 lines
9.5 KiB
C#
249 lines
9.5 KiB
C#
using Qdp.Foundation.Implementations;
|
|
using Qdp.Pricing.Base.Enums;
|
|
using Qdp.Pricing.Base.Implementations;
|
|
using Qdp.Pricing.Base.Utilities;
|
|
|
|
namespace YLErp.QdpModule
|
|
{
|
|
/// <summary>
|
|
/// QDP日历帮助类
|
|
/// </summary>
|
|
public static class QdpCalendarHelper
|
|
{
|
|
/// <summary>
|
|
/// 给定任一日期,按特定交易日历和偏移量,给出交易日。
|
|
/// 例如:
|
|
/// 2018-06-16,2018-06-17,2018-06-18三天是chn假期
|
|
///
|
|
/// BizDayShift("2018-06-15", "chn", 0); //2018-06-15
|
|
/// BizDayShift("2018-06-15", "chn", 1); //2018-06-19
|
|
/// BizDayShift("2018-06-16", "chn", 0); //2018-06-19
|
|
/// BizDayShift("2018-06-17", "chn", 0); //2018-06-19
|
|
/// BizDayShift("2018-06-18", "chn", 0); //2018-06-19
|
|
/// BizDayShift("2018-06-19", "chn", 0); //2018-06-19
|
|
/// BizDayShift("2018-06-16", "chn", 1); //2018-06-20
|
|
/// BizDayShift("2018-06-17", "chn", 1); //2018-06-20
|
|
/// BizDayShift("2018-06-18", "chn", 1); //2018-06-20
|
|
/// BizDayShift("2018-06-19", "chn", 1); //2018-06-20
|
|
/// BizDayShift("2018-06-16", "chn", -1); //2018-06-15
|
|
/// BizDayShift("2018-06-17", "chn", -1); //2018-06-15
|
|
/// BizDayShift("2018-06-18", "chn", -1); //2018-06-15
|
|
/// BizDayShift("2018-06-19", "chn", -1); //2018-06-15
|
|
/// </summary>
|
|
/// <param name="date">日期</param>
|
|
/// <param name="calendarName">交易日历名称</param>
|
|
/// <param name="offset">偏移天数</param>
|
|
/// <returns></returns>
|
|
public static DateTime BizDayShift(DateTime date, int offset = 0, string calendarName = "chn")
|
|
{
|
|
return BizDayShift2(date, offset, calendarName).DateTime;
|
|
}
|
|
|
|
public static Date BizDayShift2(DateTime date, int offset = 0, string calendarName = "chn")
|
|
{
|
|
if (string.IsNullOrEmpty(calendarName))
|
|
{
|
|
calendarName = "chn";
|
|
}
|
|
|
|
var calendar = CalendarImpl.Get(calendarName);
|
|
if (calendar == null)
|
|
{
|
|
return new Date(date);
|
|
}
|
|
|
|
var qdpDate = new Date(date);
|
|
var bizDay = calendar.IsBizDay(qdpDate) ? qdpDate : calendar.NextBizDay(qdpDate);
|
|
return calendar.AddBizDays(bizDay, offset);
|
|
}
|
|
|
|
public static DateTime PrevBizDayShift(DateTime date, int offset = 0, string calendarName = "chn")
|
|
{
|
|
if (string.IsNullOrEmpty(calendarName))
|
|
{
|
|
calendarName = "chn";
|
|
}
|
|
|
|
var calendar = CalendarImpl.Get(calendarName);
|
|
if (calendar == null)
|
|
{
|
|
return date;
|
|
}
|
|
|
|
var qdpDate = new Date(date);
|
|
var bizDay = calendar.IsBizDay(qdpDate) ? qdpDate : calendar.PrevBizDay(qdpDate);
|
|
return calendar.AddBizDays(bizDay, offset).DateTime;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 返回一个日期区间内的所有交易日
|
|
/// AllBizDays(2022-04-26,2022-04-26) null
|
|
/// AllBizDays(2022-04-26,2022-04-27) 2022-04-26
|
|
/// </summary>
|
|
/// <param name="startDate"></param>
|
|
/// <param name="endDate"></param>
|
|
/// <param name="calendarName"></param>
|
|
/// <returns></returns>
|
|
public static List<DateTime> AllBizDays(DateTime startDate, DateTime endDate, string calendarName = "chn")
|
|
{
|
|
if (string.IsNullOrEmpty(calendarName))
|
|
{
|
|
calendarName = "chn";
|
|
}
|
|
|
|
var calendar = CalendarImpl.Get(calendarName);
|
|
if (calendar == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var qdpStartDate = new Date(startDate);
|
|
var qdpEndDate = new Date(endDate);
|
|
var holidays = calendar.BizDaysBetweenDates(qdpStartDate, qdpEndDate);
|
|
return holidays.Select(x => x.DateTime).ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从到期日天数转换成以年为单位的时间
|
|
/// </summary>
|
|
/// <param name="timeToMaturityDays">天数,可以是小数</param>
|
|
/// <param name="optionDayCount">DayCount规则名称</param>
|
|
/// <param name="referenceDate">参考日期,对于某些DayCount有效</param>
|
|
/// <returns></returns>
|
|
public static double CalculateTFromDays(double timeToMaturityDays, string optionDayCount, DateTime referenceDate)
|
|
{
|
|
if (double.IsNaN(timeToMaturityDays))
|
|
{
|
|
return double.NaN;
|
|
}
|
|
|
|
var dayCount = optionDayCount.ToDayCountImpl();
|
|
return timeToMaturityDays / dayCount.DaysInYear(new Date(referenceDate));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取date(包括)之前的第一个非假日
|
|
/// </summary>
|
|
public static DateTime GetNonHolidayDefore(DateTime date, string country = "chn")
|
|
{
|
|
var calendar = CalendarImpl.Get(country);
|
|
var qdpDate = new Date(date);
|
|
return calendar.IsBizDay(qdpDate) ? date : calendar.PrevBizDay(qdpDate).DateTime;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取tuningdays后的工作日信息
|
|
/// </summary>
|
|
public static DateTime GetWorkingDay(DateTime fromdate, int tuningdays)
|
|
{
|
|
var calendar = CalendarImpl.Get("chn");
|
|
return calendar.AddBizDays(new Date(fromdate), tuningdays).DateTime;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取工作日天数(不包括from,包括to)
|
|
/// </summary>
|
|
public static int GetWorkDayCount(DateTime from, DateTime to)
|
|
{
|
|
var calendar = CalendarImpl.Get("chn");
|
|
return (int)Math.Round(calendar.NumberBizDaysBetweenDate(new Date(from), new Date(to), excludeEndDate: true));
|
|
}
|
|
|
|
public static List<DateTime> GetWorkingDatesBeforeDate(DateTime toDate, int days)
|
|
{
|
|
var calendar = CalendarImpl.Get("chn");
|
|
var toQdpDate = new Date(toDate);
|
|
var fromQdpDate = calendar.AddBizDays(toQdpDate, -days + 1);
|
|
return calendar.BizDaysBetweenDatesInclEndDay(fromQdpDate, toQdpDate).Select(x => x.DateTime).Reverse().ToList();
|
|
}
|
|
|
|
|
|
public static DateTime AddDate(DateTime fromDate,int days)
|
|
{
|
|
var calendar = CalendarImpl.Get("chn");
|
|
var toQdpDate = new Date(fromDate);
|
|
return calendar.AddBizDays(toQdpDate,days);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 获取fromDate到toDate天数
|
|
/// </summary>
|
|
public static int GetNonHolidayDaysBetween(DateTime fromDate, DateTime toDate, string country = "chn")
|
|
{
|
|
var calendar = CalendarImpl.Get(country);
|
|
return (int)Math.Round(calendar.NumberBizDaysBetweenDate(new Date(fromDate), new Date(toDate), excludeEndDate: true));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取date(包括)之后的第一个非假日
|
|
/// </summary>
|
|
public static DateTime GetNonHoliday(DateTime date, string country = "chn")
|
|
{
|
|
var calendar = CalendarImpl.Get(country);
|
|
var qdpDate = new Date(date);
|
|
return calendar.IsBizDay(qdpDate) ? date : calendar.NextBizDay(qdpDate).DateTime;
|
|
}
|
|
|
|
public static bool IsHoliday(DateTime date, string country = "chn")
|
|
{
|
|
var calendar = CalendarImpl.Get(country);
|
|
return calendar.IsHoliday(new Date(date));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取不超过到期日的实行日
|
|
/// 1个月,2周,1周,到日期这样的规则向前计算
|
|
/// </summary>
|
|
public static DateTime GetUnderlyingExerciseDate(DateTime underlyingMaturityDate, DateTime SystemDate)
|
|
{
|
|
//OTC - 6717 组合报价-默认的到期日为交易日后一个月,且算头不算尾
|
|
DateTime exerciseDate = GetNonHoliday(SystemDate.AddMonths(1).AddDays(-1));
|
|
if (underlyingMaturityDate < exerciseDate)
|
|
{
|
|
exerciseDate = GetNonHoliday(SystemDate.AddDays(14));
|
|
if (underlyingMaturityDate < exerciseDate)
|
|
{
|
|
exerciseDate = GetNonHoliday(SystemDate.AddDays(7));
|
|
if (underlyingMaturityDate < exerciseDate)
|
|
{
|
|
exerciseDate = GetNonHolidayDefore(underlyingMaturityDate);
|
|
}
|
|
}
|
|
}
|
|
return exerciseDate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据DayCount规则和调整天数来调整日期
|
|
/// </summary>
|
|
public static string ShiftDate(string date, string dayCount, int maturityShift)
|
|
{
|
|
return ShiftDate(DateTime.Parse(date), dayCount, maturityShift).ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据DayCount规则和调整天数来调整日期
|
|
/// </summary>
|
|
public static Date ShiftDate(DateTime date, string dayCount, int maturityShift)
|
|
{
|
|
return ShiftDate(new Date(date), dayCount, maturityShift);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据DayCount规则和调整天数来调整日期
|
|
/// </summary>
|
|
public static Date ShiftDate(Date qdpDate, string dayCount, int maturityShift)
|
|
{
|
|
if (dayCount == "Act365")
|
|
{
|
|
return CalendarImpl.Get("chn").AddDays(qdpDate, maturityShift);
|
|
}
|
|
else
|
|
{
|
|
return CalendarImpl.Get("chn").AddBizDays(qdpDate, maturityShift, BusinessDayConvention.Following);
|
|
}
|
|
}
|
|
}
|
|
}
|