Files
zszq-trs/YLErpDAL/QdpModule/QdpObservationHelper.cs
T

419 lines
14 KiB
C#

using Qdp.Foundation.Implementations;
using Qdp.Pricing.Base.Enums;
using Qdp.Pricing.Base.Implementations;
using System.Runtime.CompilerServices;
namespace YLErp.QdpModule
{
/// <summary>
/// QDP观察条款帮助类
/// </summary>
public static class QdpObservationHelper
{
#region----在一段日期中,使用固定的期限获取一组日期----
/// <summary>
/// 在一段日期中,使用固定的期限获取一组日期
/// 主要可用于生成期权的观察日
/// </summary>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <param name="termStr"></param>
/// <returns></returns>
public static DateTime[] GetDatesWithFixedTerm(
DateTime startDate,
DateTime endDate,
string termStr,
BusinessDayConvention bdc = BusinessDayConvention.None,
bool alignEnd = false,
string calcMode = "01")
{
if (!Term.IsTerm(termStr))
{
return null;
}
return GetDatesWithFixedTerm(startDate, endDate, new Term(termStr), bdc, alignEnd, calcMode);
}
/// <summary>
/// 在一段日期中,使用固定的期限获取一组日期
/// 主要可用于生成期权的观察日
///
/// alignEnd为false时,生成的日期是向开始日对齐,例如:
/// startDate=2019-09-11, endDate=2019-12-26, term=1M, bdc=None
/// 生成的日期序列为:2019-09-11,2019-10-11,2019-11-11,2019-12-11,2019-12-26
///
/// alignEnd为true时,生成的日期是想结束日对齐
/// 生成的日期序列为:2019-09-26,2019-10-26,2019-11-26,2019-12-26
/// </summary>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <param name="term">日期之前的间隔期限</param>
/// <param name="bdc">遇到节假日的调整规则</param>
/// <param name="alignEnd">生成的日期序列是否向结束日对齐</param>
/// <param name="IncludeStartDate">是否包含开始日当天</param>
/// <returns></returns>
public static DateTime[] GetDatesWithFixedTerm(
DateTime startDate,
DateTime endDate,
Term term,
BusinessDayConvention bdc = BusinessDayConvention.None,
bool alignEnd = false,
string calcMode = "01")
{
return alignEnd
? GetDatesWithFixedTermStartAlignEnd(startDate, endDate, term, bdc, calcMode)
: GetDatesWithFixedTermStartAlignStart(startDate, endDate, term, bdc, calcMode);
}
private static DateTime[] GetDatesWithFixedTermStartAlignEnd(
DateTime startDate,
DateTime endDate,
Term term,
BusinessDayConvention bdc = BusinessDayConvention.None,
string calcMode = "01")
{
var qdpStart = new Date(startDate);
var qdpEnd = new Date(endDate);
var dates = new List<Date>();
var calendar = CalendarImpl.Get("chn");
if (calcMode == "11")//算头算尾
{
while (qdpEnd >= qdpStart)
{
dates.Add(qdpEnd);
qdpEnd = term.Prev(qdpEnd);
}
}
else if (calcMode == "10")//算头不算尾
{
qdpEnd = term.Prev(qdpEnd);
while (qdpEnd >= qdpStart)
{
dates.Add(qdpEnd);
qdpEnd = term.Prev(qdpEnd);
}
}
else if (calcMode == "01")//不算头算尾
{
while (qdpEnd > qdpStart)
{
dates.Add(qdpEnd);
qdpEnd = term.Prev(qdpEnd);
}
}
else if (calcMode == "00")//不算头不算尾
{
qdpEnd = term.Prev(qdpEnd);
while (qdpEnd > qdpStart)
{
dates.Add(qdpEnd);
qdpEnd = term.Prev(qdpEnd);
}
}
//简单规则生成日期时,周期为空就用到期日
if (dates.Count == 0)
{
dates.Add(new Date(endDate));
}
dates = dates.Select(d => calendar.Adjust(d, bdc)).Distinct().ToList();
dates.Reverse();
return dates.Select(x => x.DateTime).ToArray();
}
private static DateTime[] GetDatesWithFixedTermStartAlignStart(
DateTime startDate,
DateTime endDate,
Term term,
BusinessDayConvention bdc = BusinessDayConvention.None,
string calcMode = "01")
{
var qdpStart = new Date(startDate);
var qdpEnd = new Date(endDate);
var dates = new List<Date>();
var calendar = CalendarImpl.Get("chn");
if (calcMode == "11")//算头算尾
{
while (qdpStart <= qdpEnd)
{
dates.Add(qdpStart);
qdpStart = term.Next(qdpStart);
}
}
else if (calcMode == "10")//算头不算尾
{
while (qdpStart < qdpEnd)
{
dates.Add(qdpStart);
qdpStart = term.Next(qdpStart);
}
}
else if (calcMode == "01")//不算头算尾
{
qdpStart = term.Next(qdpStart);
while (qdpStart <= qdpEnd)
{
dates.Add(qdpStart);
qdpStart = term.Next(qdpStart);
}
}
else if (calcMode == "00")//不算头不算尾
{
qdpStart = term.Next(qdpStart);
while (qdpStart < qdpEnd)
{
dates.Add(qdpStart);
qdpStart = term.Next(qdpStart);
}
}
dates = dates.Select(d => calendar.Adjust(d, bdc)).Distinct().ToList();
//简单规则生成日期时,周期为空就用到期日
if (dates.Count == 0)
{
dates.Add(qdpEnd);
}
return dates.Select(x => x.DateTime).ToArray();
}
/// <summary>
/// 在一段日期中,使用固定的期限获取观察日字符串
/// </summary>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <param name="termStr"></param>
/// <returns></returns>
public static string GetObservationDateString(
DateTime startDate,
DateTime endDate,
string termStr,
BusinessDayConvention bdc = BusinessDayConvention.None,
bool alignEnd = false)
{
var dates = GetDatesWithFixedTerm(startDate, endDate, termStr, bdc, alignEnd);
return string.Join(",", dates.Select(x => x.ToString("yyyy-MM-dd")));
}
#endregion
/// <summary>
/// 为雪球返回默认的敲出观察日数据(按月观察)
/// </summary>
[MethodImpl(methodImplOptions: MethodImplOptions.AggressiveInlining)]
public static DateTime[] GetDefaultKoObservationDatesForSnowbal(DateTime startDate, DateTime endDate)
{
return GetDatesWithFixedTerm(startDate, endDate, "1M", bdc: BusinessDayConvention.Following, alignEnd: true);
}
/// <summary>
/// 为雪球返回默认的敲出观察日数据(按月观察)
/// </summary>
public static Date[] GetDefaultKoObservationDatesForSnowbalV2(DateTime startDate, DateTime endDate)
{
var monthlyDates = GetDefaultKoObservationDatesForSnowbal(startDate, endDate);
return monthlyDates.Select(x => (Date)x).ToArray();
}
public static DateTime[] GetDatesWithFixedTerm(
DateTime startDate,
DateTime endDate,
string termStr,
string calendarStr,
BusinessDayConvention bdc = BusinessDayConvention.None,
bool alignEnd = false,
string calcMode = "01")
{
if (!Term.IsTerm(termStr))
{
return null;
}
var calendarName = string.IsNullOrEmpty(calendarStr) ? "chn" : calendarStr.ToLower();
return GetDatesWithFixedTerm(startDate, endDate, new Term(termStr), calendarName, bdc, alignEnd, calcMode);
}
public static DateTime[] GetDatesWithFixedTerm(
DateTime startDate,
DateTime endDate,
Term term,
string calendarStr,
BusinessDayConvention bdc = BusinessDayConvention.None,
bool alignEnd = false,
string calcMode = "01")
{
var calendarName = string.IsNullOrEmpty(calendarStr) ? "chn" : calendarStr.ToLower();
return alignEnd
? GetDatesWithFixedTermStartAlignEnd(startDate, endDate, term, calendarName, bdc, calcMode)
: GetDatesWithFixedTermStartAlignStart(startDate, endDate, term, calendarName, bdc, calcMode);
}
private static DateTime[] GetDatesWithFixedTermStartAlignEnd(
DateTime startDate,
DateTime endDate,
Term term,
string calendarName,
BusinessDayConvention bdc = BusinessDayConvention.None,
string calcMode = "01")
{
var qdpStart = new Date(startDate);
var qdpEnd = new Date(endDate);
var dates = new List<Date>();
var calendar = CalendarImpl.Get(calendarName);
if (calcMode == "11")
{
while (qdpEnd >= qdpStart)
{
dates.Add(qdpEnd);
qdpEnd = term.Prev(qdpEnd);
}
}
else if (calcMode == "10")
{
qdpEnd = term.Prev(qdpEnd);
while (qdpEnd >= qdpStart)
{
dates.Add(qdpEnd);
qdpEnd = term.Prev(qdpEnd);
}
}
else if (calcMode == "01")
{
while (qdpEnd > qdpStart)
{
dates.Add(qdpEnd);
qdpEnd = term.Prev(qdpEnd);
}
}
else if (calcMode == "00")
{
qdpEnd = term.Prev(qdpEnd);
while (qdpEnd > qdpStart)
{
dates.Add(qdpEnd);
qdpEnd = term.Prev(qdpEnd);
}
}
if (dates.Count == 0)
{
dates.Add(new Date(endDate));
}
dates = dates.Select(d => calendar.Adjust(d, bdc)).Distinct().ToList();
dates.Reverse();
return dates.Select(x => x.DateTime).ToArray();
}
private static DateTime[] GetDatesWithFixedTermStartAlignStart(
DateTime startDate,
DateTime endDate,
Term term,
string calendarName,
BusinessDayConvention bdc = BusinessDayConvention.None,
string calcMode = "01")
{
var qdpStart = new Date(startDate);
var qdpEnd = new Date(endDate);
var dates = new List<Date>();
var calendar = CalendarImpl.Get(calendarName);
if (calcMode == "11")
{
while (qdpStart <= qdpEnd)
{
dates.Add(qdpStart);
qdpStart = term.Next(qdpStart);
}
}
else if (calcMode == "10")
{
while (qdpStart < qdpEnd)
{
dates.Add(qdpStart);
qdpStart = term.Next(qdpStart);
}
}
else if (calcMode == "01")
{
qdpStart = term.Next(qdpStart);
while (qdpStart <= qdpEnd)
{
dates.Add(qdpStart);
qdpStart = term.Next(qdpStart);
}
}
else if (calcMode == "00")
{
qdpStart = term.Next(qdpStart);
while (qdpStart < qdpEnd)
{
dates.Add(qdpStart);
qdpStart = term.Next(qdpStart);
}
}
dates = dates.Select(d => calendar.Adjust(d, bdc)).Distinct().ToList();
if (dates.Count == 0)
{
dates.Add(qdpEnd);
}
return dates.Select(x => x.DateTime).ToArray();
}
public static ObservationSettleDateResult[] GetObservationAndSettleDates(
DateTime startDate,
DateTime endDate,
string termStr,
string calendarStr,
int settlementRules,
BusinessDayConvention bdc = BusinessDayConvention.None,
bool alignEnd = false,
string calcMode = "01")
{
if (!Term.IsTerm(termStr))
{
return null;
}
var calendarName = string.IsNullOrEmpty(calendarStr) ? "chn" : calendarStr.ToLower();
var calendar = CalendarImpl.Get(calendarName);
var term = new Term(termStr);
DateTime[] observationDates = alignEnd
? GetDatesWithFixedTermStartAlignEnd(startDate, endDate, term, calendarName, bdc, calcMode)
: GetDatesWithFixedTermStartAlignStart(startDate, endDate, term, calendarName, bdc, calcMode);
var results = new List<ObservationSettleDateResult>();
foreach (var obsDate in observationDates)
{
var settleDate = obsDate.AddDays(settlementRules);
settleDate = calendar.Adjust(new Date(settleDate), bdc).DateTime;
results.Add(new ObservationSettleDateResult
{
ObservationDate = obsDate,
SettleDate = settleDate
});
}
return results.ToArray();
}
}
public class ObservationSettleDateResult
{
public DateTime ObservationDate { get; set; }
public DateTime SettleDate { get; set; }
}
}