Files
zszq-trs/YLErpDAL/Modules/ApiModule/PricingModule/OptionPricingApiHelper.cs
T
2024-05-09 14:06:26 +08:00

157 lines
5.7 KiB
C#

using System.Reflection;
namespace YLErp.Modules.ApiModule.PricingModule
{
/// <summary>
/// OptionPricingApiHelper
/// </summary>
public static class OptionPricingApiHelper
{
static readonly Dictionary<string, (Func<string, object> valueConv, Action<OptionPricingModelV2, object> valueSet)> _dic;
static OptionPricingApiHelper()
{
_dic = new Dictionary<string, (Func<string, object> valueConv, Action<OptionPricingModelV2, object> valueSet)>(StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// 根据模型属性名设置属性值
/// </summary>
public static void SetValueByPropName(OptionPricingModelV2 model, string propName, string value)
{
if (string.IsNullOrEmpty(value))
{
return;
}
if (!_dic.TryGetValue(propName, out var tuple))
{
Func<string, object> valueConv = null;
var prop = typeof(OptionPricingModelV2).GetProperty(propName,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.SetProperty);
if (prop != null)
{
if (prop.PropertyType == typeof(string))
{
valueConv = s => s;
}
else if (prop.PropertyType == typeof(int) || prop.PropertyType.IsEnum || prop.PropertyType == typeof(int?))
{
valueConv = s => int.TryParse(s, out var n) ? (object)n : throw new ServiceException("参数值不符合要求,参数名:" + propName);
}
else if (prop.PropertyType == typeof(double) || prop.PropertyType == typeof(double?))
{
valueConv = s => double.TryParse(s, out var d) ? (object)d : throw new ServiceException("参数值不符合要求,参数名:" + propName);
}
else if (prop.PropertyType == typeof(bool) || prop.PropertyType == typeof(bool?))
{
valueConv = s => s == "true";
}
else if (prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(DateTime?))
{
valueConv = s => DateTime.TryParse(s, out var d) ? (object)d : throw new ServiceException("参数值不符合要求,参数名:" + propName);
}
else
{
System.Diagnostics.Debug.WriteLine("!!!ExtendSetter:没有处理值转换:" + propName);
}
}
else
{
System.Diagnostics.Debug.WriteLine("!!!ExtendSetter:没有找到对应属性信息:" + propName);
}
_dic[propName] = tuple = (valueConv, (m, o) => prop?.SetValue(m, o));
}
if (tuple.valueConv != null)
{
tuple.valueSet(model, tuple.valueConv(value));
}
}
/// <summary>
/// 检查请求数据是否正确
/// </summary>
public static void CheckPricingRequestData(OptionPricingModelV2 req)
{
if (req == null)
{
throw new ServiceException("参数为null");
}
if (string.IsNullOrEmpty(req.UnderlyingCode))
{
throw new ServiceException("缺少标的代码");
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(req.UnderlyingCode);
if (underlying == null)
{
throw new ServiceException("没有找到标的信息:" + req.UnderlyingCode);
}
if (!req.MaturityDate.HasValue || req.MaturityDate.Value == default)
{
req.MaturityDate = req.ExerciseDate;
}
req.UnderlyingId = underlying.id;
req.UnderlyingAssetClass = underlying.UnderlyingType;
req.UnderlyingAssetName = underlying.UnderlyingName;
req.UnderlyingInstrumentType = underlying.UnderlyingInstrumentType;
if (req.Notional <= 0)
{
throw new ServiceException("持仓份额必须大于0");
}
if (req.TradeType != "香草期权" && req.ExtendFields != null && req.ExtendFields.Count > 0)
{
foreach (var kv in req.ExtendFields)
{
OptionPricingApiHelper.SetValueByPropName(req, kv.Key, kv.Value);
}
var isAutoCall = req.TradeType == "雪球期权" || req.TradeType == "凤凰期权";
if (isAutoCall)
{
req.Strike = req.SpreadStrike1;
}
if (!req.IsAnnualized)
{
req.AnnualizeFactor = 1;
if (isAutoCall)
{
req.IsAnnualized2 = false;
req.AnnualizeFactor2 = 1;
}
}
else if (isAutoCall)
{
req.IsAnnualized2 = true;
req.AnnualizeFactor2 = req.AnnualizeFactor;
req.IsAnnualized = false;
req.AnnualizeFactor = 1;
}
}
//检查并尽可能修复数据
req.CheckAndRepairValues();
if (!req.VolValue.HasValue)
{
req.VolValue = 0.3;
}
req.Vol = req.VolValue;
}
}
}