185 lines
5.8 KiB
C#
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; }
|
|
}
|
|
}
|