Files
zszq-trs/YLErpDAL/QdpModule/QdpObservationHelperForSnowball.cs
T
2024-05-09 14:06:26 +08:00

185 lines
5.8 KiB
C#

using Qdp.Pricing.Base.Enums;
using YLErp.Models;
namespace YLErp.QdpModule
{
/// <summary>
/// 雪球观察日列表帮助类
/// </summary>
public static class QdpObservationHelperForSnowball
{
/// <summary>
/// 生成观察日列表
/// </summary>
public static IEnumerable<ObservationItemForSnowball> GenerateObservationList(ObservationRequestForSnowball req)
{
if (req is null)
{
throw new ArgumentNullException(nameof(req));
}
req.LockCount--; //前端锁3个月实际代表抹去2个月
if (req.LockCount < 0)
{
req.LockCount = 0;
}
var dates = GetDatesWithFixedTerm(req);
if (dates.Length == 0 || dates[^1] != req.EndDate)
{
var arr = new DateTime[dates.Length + 1];
dates.CopyTo(arr, 0);
dates = arr;
dates[^1] = req.EndDate;
}
if (dates.Length <= req.LockCount)
{
req.LockCount = dates.Length - 1;
}
var kobarrier = req.KoBarrier;
var touchLimit = Math.Abs(req.KoBarrierStep) < 1e-6;
var list = new List<ObservationItemForSnowball>(dates.Length);
var noTouchLimit = req.KoBarrierStep > 0 ? req.KoBarrierLimit < req.KoBarrier : req.KoBarrierLimit > req.KoBarrier;
for (var i = req.LockCount; i < dates.Length; i++)
{
var date = dates[i].ToString("yyyy-MM-dd");
var item = new ObservationItemForSnowball
{
KoDate = date,
CouponDate = date,
KoBarrier = kobarrier,
KoCoupon = req.KoCoupon
};
//票息支付日递延
if (req.CouponPaymentDateDeferred != 0)
{
item.CouponDate = QdpCalendarHelper.AddDate(dates[i], req.CouponPaymentDateDeferred).ToString("yyyy-MM-dd");
}
if (i > req.LockCount)
{
if (noTouchLimit)
{
kobarrier += req.KoBarrierStep;
item.KoBarrier = kobarrier;
}
else if (!touchLimit)
{
kobarrier += req.KoBarrierStep;
touchLimit = req.KoBarrierStep > 0
? kobarrier > req.KoBarrierLimit : kobarrier < req.KoBarrierLimit;
if (touchLimit)
{
kobarrier = req.KoBarrierLimit;
}
item.KoBarrier = kobarrier;
}
}
list.Add(item);
}
return list;
}
/// <summary>
///
/// </summary>
private static DateTime[] GetDatesWithFixedTerm(ObservationDatesRequest req)
{
//观察日间隔
if (string.IsNullOrEmpty(req.Interval))
{
req.Interval = "1D";
}
//节假日调整,可选值:None 不调整、Previous 向前调整、Following 向后调整,默认:向后调整
var bdc = BusinessDayConvention.Following;
if (!string.IsNullOrWhiteSpace(req.HolidayAdjustment))
{
bdc = req.HolidayAdjustment switch
{
"None" => BusinessDayConvention.None,
"Previous" => BusinessDayConvention.Previous,
"ModifiedPrevious" => BusinessDayConvention.ModifiedPrevious,
"Following" => BusinessDayConvention.Following,
"ModifiedFollowing" => BusinessDayConvention.ModifiedFollowing,
_ => throw new ServiceException("请求参数'HolidayAdjustment'的值不符合要求"),
};
}
//对齐规则,可选值:EndDate 向到期日对齐、StartDate 向开始日对齐,默认:向到期日对齐
var alignEnd = true;
if (!string.IsNullOrEmpty(req.Alignment))
{
alignEnd = req.Alignment switch
{
"EndDate" or "向到期日对齐" => true,
"StartDate" or "向开始日对齐" => false,
_ => throw new ServiceException("请求参数'Alignment'的值不符合要求"),
};
}
if (!string.IsNullOrEmpty(req.CalcMode))
{
switch (req.CalcMode)
{
case "00":
case "01":
case "10":
case "11": break;
default: throw new ServiceException("请求参数'CalcMode'的值不符合要求");
}
}
else
{
req.CalcMode = "01";
}
return QdpObservationHelper.GetDatesWithFixedTerm(req.StartDate, req.EndDate, req.Interval, bdc, alignEnd, req.CalcMode);
}
}
/// <summary>
/// 雪球观察日列表数据项
/// </summary>
public class ObservationItemForSnowball
{
/// <summary>
/// 敲出观察日
/// </summary>
public string KoDate { get; set; }
/// <summary>
/// 票息支付日
/// </summary>
public string CouponDate { get; set; }
/// <summary>
/// 敲出障碍价格
/// </summary>
public double KoBarrier { get; set; }
/// <summary>
/// 敲出票息
/// </summary>
public string KoCoupon { get; set; }
}
}