158 lines
6.3 KiB
C#
158 lines
6.3 KiB
C#
using YLErp.BLL;
|
|
using YLErp.Model;
|
|
using YLErp.QdpModule;
|
|
|
|
namespace YLErp.Modules.TradeModule.DealModule
|
|
{
|
|
/// <summary>
|
|
/// 价差期权数据验证
|
|
/// </summary>
|
|
public static class SpreadOptionValidator
|
|
{
|
|
/// <summary>
|
|
/// 验证价差期权数据
|
|
/// </summary>
|
|
public static string Validate(trade req)
|
|
{
|
|
var errorMsg = "";
|
|
SpreadOptionPayoff payoff = null;
|
|
try
|
|
{
|
|
payoff = new SpreadOptionPayoff(req.trade_spread_option.Payoff);
|
|
}
|
|
catch (ArgumentException e)
|
|
{
|
|
errorMsg = e.Message;
|
|
}
|
|
var numberOfUnderlyings = payoff.Weights.Length;
|
|
if (string.IsNullOrEmpty(errorMsg))
|
|
{
|
|
req.trade_spread_option.UnderlyingId1 = req.UnderlyingId;
|
|
req.trade_spread_option.UnderlyingAssetCode1 = req.UnderlyingCode;
|
|
req.trade_spread_option.TradeOpenVolatility1 = req.TradeOpenVolatility;
|
|
req.trade_spread_option.TradeCloseVolatility1 = req.TradeCloseVolatility;
|
|
req.trade_spread_option.NumOfSmoothingDays1 = req.NumOfSmoothingDays;
|
|
// remove redundant underlying ids/codes
|
|
if (numberOfUnderlyings == 2)
|
|
{
|
|
req.trade_spread_option.UnderlyingId3 = null;
|
|
req.trade_spread_option.UnderlyingId4 = null;
|
|
req.trade_spread_option.UnderlyingAssetCode3 = null;
|
|
req.trade_spread_option.UnderlyingAssetCode4 = null;
|
|
}
|
|
else if (numberOfUnderlyings == 3)
|
|
{
|
|
req.trade_spread_option.UnderlyingId4 = null;
|
|
req.trade_spread_option.UnderlyingAssetCode4 = null;
|
|
}
|
|
|
|
if (!req.trade_spread_option.UnderlyingId1.HasValue ||
|
|
string.IsNullOrEmpty(req.trade_spread_option.UnderlyingAssetCode1) ||
|
|
!req.trade_spread_option.UnderlyingId2.HasValue ||
|
|
string.IsNullOrEmpty(req.trade_spread_option.UnderlyingAssetCode2))
|
|
{
|
|
errorMsg = "标的ID和代码不能为空";
|
|
}
|
|
if (string.IsNullOrEmpty(errorMsg) && numberOfUnderlyings >= 3)
|
|
{
|
|
if (!req.trade_spread_option.UnderlyingId3.HasValue ||
|
|
string.IsNullOrEmpty(req.trade_spread_option.UnderlyingAssetCode3))
|
|
{
|
|
errorMsg = "标的ID和代码不能为空";
|
|
}
|
|
if (string.IsNullOrEmpty(errorMsg) && numberOfUnderlyings >= 4)
|
|
{
|
|
if (!req.trade_spread_option.UnderlyingId4.HasValue ||
|
|
string.IsNullOrEmpty(req.trade_spread_option.UnderlyingAssetCode4))
|
|
{
|
|
errorMsg = "标的ID和代码不能为空";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (string.IsNullOrEmpty(errorMsg))
|
|
{
|
|
errorMsg = checkSpreadOptionVolatilitySettings(req, numberOfUnderlyings);
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(errorMsg))
|
|
{
|
|
errorMsg = checkCorrelations(req.trade_spread_option);
|
|
}
|
|
return errorMsg;
|
|
}
|
|
|
|
private static string checkCorrelations(trade_spread_option spreadOption)
|
|
{
|
|
var errorMsg = "";
|
|
var ids = spreadOption.UnderlyingIds();
|
|
var codes = spreadOption.UnderlyingAssetCodes();
|
|
using (var db = DbContextFactory.GetYLDbContext())
|
|
{
|
|
for (int i = 0; i < ids.Length - 1 && string.IsNullOrEmpty(errorMsg); i++)
|
|
{
|
|
for (int j = i + 1; j < ids.Length && string.IsNullOrEmpty(errorMsg); j++)
|
|
{
|
|
if (correlationBLL.findCorrelation(ids[i], ids[j], db) == 0.0)
|
|
{
|
|
errorMsg = $"未设定{codes[i]}与{codes[j]}的相关性";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return errorMsg;
|
|
}
|
|
|
|
private static string checkSpreadOptionVolatilitySettings(trade req, int numberOfUnderlyings)
|
|
{
|
|
var errorMsg = checkVolatilitySetting(req.trade_spread_option.TradeOpenVolatility2,
|
|
req.trade_spread_option.TradeCloseVolatility2,
|
|
req.trade_spread_option.NumOfSmoothingDays2,
|
|
req.StartDate, req.ExerciseDate);
|
|
if (string.IsNullOrEmpty(errorMsg) && numberOfUnderlyings >= 3)
|
|
{
|
|
errorMsg = checkVolatilitySetting(req.trade_spread_option.TradeOpenVolatility3,
|
|
req.trade_spread_option.TradeCloseVolatility3,
|
|
req.trade_spread_option.NumOfSmoothingDays3,
|
|
req.StartDate, req.ExerciseDate);
|
|
}
|
|
if (string.IsNullOrEmpty(errorMsg) && numberOfUnderlyings >= 4)
|
|
{
|
|
errorMsg = checkVolatilitySetting(req.trade_spread_option.TradeOpenVolatility4,
|
|
req.trade_spread_option.TradeCloseVolatility4,
|
|
req.trade_spread_option.NumOfSmoothingDays4,
|
|
req.StartDate, req.ExerciseDate);
|
|
}
|
|
return errorMsg;
|
|
}
|
|
|
|
private static string checkVolatilitySetting(double? open, double? close, int? smoothing, DateTime? startDate, DateTime? exerciseDate)
|
|
{
|
|
if (open.HasValue && open.Value < 0)
|
|
{
|
|
return "开仓波动率不能小于0";
|
|
}
|
|
if (close.HasValue && close.Value < 0)
|
|
{
|
|
return "目标波动率不能小于0";
|
|
}
|
|
|
|
if (smoothing.HasValue)
|
|
{
|
|
if (smoothing.Value < 0)
|
|
{
|
|
return "平滑过渡天数不能小于0";
|
|
}
|
|
if (exerciseDate.HasValue && startDate.HasValue
|
|
&& smoothing > QdpCalendarHelper.GetNonHolidayDaysBetween(startDate.Value, exerciseDate.Value) + 1)
|
|
{
|
|
return "平滑过渡天数不能大于存续天数";
|
|
}
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
}
|
|
}
|