从山证v2.3.0拷贝
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
using System.Linq.Expressions;
|
||||
using YLErp.BLL.Hedge;
|
||||
using YLErp.Modules.CalculationModule;
|
||||
using YLErp.Modules.CalculationModule.Abstract;
|
||||
using YLErp.Modules.DataProviderModule;
|
||||
using YLErp.Modules.EodModule;
|
||||
|
||||
namespace YLErp.Modules.ExchangeOptionTradeModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 日终场内期权风险计算服务
|
||||
/// </summary>
|
||||
public class EodExchangeOptionRiskCalcService : YLBaseService
|
||||
{
|
||||
private EodPriceProvider _eodPriceProvider = null;
|
||||
|
||||
EodExchangeOptionPriceProvider _eodExchangeOptionProvider;
|
||||
|
||||
public EodExchangeOptionRiskCalcService(OptUserInfo userInfo) : base(userInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EodExchangeOptionRiskCalcService(YLBaseService baseService) : base(baseService)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取结算日期的场内期权收盘持仓数据并进行风险计算
|
||||
/// </summary>
|
||||
/// <typeparam name="T">EodTradePositionBase</typeparam>
|
||||
/// <param name="valueDate">结算日期</param>
|
||||
/// <param name="volType">波动率类型</param>
|
||||
/// <param name="predicate">数据过滤预测</param>
|
||||
public IEnumerable<HedgePnl> CalculateEodRisk<T>(DateTime valueDate, string volType, bool useClosePrice, Expression<Func<T, bool>> predicate = null)
|
||||
where T : EodTradePosition
|
||||
{
|
||||
if (volType is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(volType));
|
||||
}
|
||||
|
||||
predicate = predicate == null
|
||||
? PredicateBuilder.Create<T>(p => p.TradeType == "场内期权")
|
||||
: PredicateBuilder.Create<T>(p => p.TradeType == "场内期权").And(predicate);
|
||||
|
||||
var oldHoldPosition = new EodSettlementService(this).GetEodTradePosition(valueDate, predicate);
|
||||
|
||||
if (_eodPriceProvider == null || _eodPriceProvider.ValueDate != valueDate)
|
||||
{
|
||||
_eodPriceProvider = new EodPriceProvider(valueDate);
|
||||
_eodExchangeOptionProvider = new EodExchangeOptionPriceProvider(valueDate, useClosePrice);
|
||||
}
|
||||
|
||||
var priceProvider = _eodPriceProvider.GetPriceProvider(useClosePrice ? SettlementTypeEnum.ClosePrice : SettlementTypeEnum.SettlePrice);
|
||||
|
||||
var context =
|
||||
new HedgePnlCalcContext(Enums.CalcScenarioEnum.EodSettlement, valueDate, volType, true, priceProvider
|
||||
, _eodPriceProvider.GetPriceProvider(SettlementTypeEnum.SettlePrice), _eodExchangeOptionProvider, OptUser)
|
||||
{
|
||||
ExchangeOptionPriceUseFlag = PS.Config.ErpElement.ExchangeOptionSettleByPrice
|
||||
? ExchangeOptionPriceUseFlag.CalcPv : ExchangeOptionPriceUseFlag.None
|
||||
};
|
||||
|
||||
return new HedgePnlCalc(context).Calculate(null, oldHoldPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
using System.Text;
|
||||
using YLErp.Model;
|
||||
using YLErp.Modules.CalculationModule;
|
||||
|
||||
namespace YLErp.Modules.ExchangeOptionTradeModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 场内期权交易结算服务
|
||||
/// </summary>
|
||||
public class ExchangeOptionSettlementService : YLBaseService
|
||||
{
|
||||
/// <summary>
|
||||
/// 开仓类型
|
||||
/// </summary>
|
||||
private readonly string[] openTypes = new[] { "空头开仓", "多头开仓" };
|
||||
|
||||
/// <summary>
|
||||
/// 平仓类型
|
||||
/// </summary>
|
||||
private readonly string[] closeTypes = new[] { "空头平仓", "多头平仓" };
|
||||
|
||||
public ExchangeOptionSettlementService(OptUserInfo optUser) : base(optUser)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行结算
|
||||
/// </summary>
|
||||
public void Execute(DateTime valueDate)
|
||||
{
|
||||
RebackOption(valueDate);
|
||||
|
||||
SaveOpenTrade(valueDate);
|
||||
|
||||
SaveCloseTrade(valueDate);
|
||||
|
||||
CloseMaturityTrade(valueDate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回滚操作
|
||||
/// </summary>
|
||||
private void RebackOption(DateTime valueDate)
|
||||
{
|
||||
Exchange_Option_Trade tt;
|
||||
|
||||
var tableName = DbContext.GetTableName<Exchange_Option_Trade>();
|
||||
|
||||
var valueDateStr = valueDate.ToString("yyyy-MM-dd");
|
||||
var sb = new StringBuilder(500);
|
||||
sb.AppendFormat("delete from {0} where {1}>='{2}';", tableName, nameof(tt.TradeDate), valueDateStr)
|
||||
.AppendLine()
|
||||
.Append("update ").Append(tableName).Append(" set ")
|
||||
.Append(nameof(tt.TradeStatus)).Append("='确认成交',")
|
||||
.Append(nameof(tt.ExerciseDate)).Append("='0001-01-01',")
|
||||
.Append(nameof(tt.ExercisePrice)).Append("=0,")
|
||||
.Append(nameof(tt.ExerciseServiceFee)).Append("=0 ")
|
||||
.Append(" where ")
|
||||
.Append(nameof(tt.ExerciseDate)).Append(">='").Append(valueDateStr).Append("';");
|
||||
|
||||
DbContext.Database.ExecuteSqlRaw(sb.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关掉过期合约
|
||||
/// </summary>
|
||||
private void CloseMaturityTrade(DateTime date)
|
||||
{
|
||||
var startDate = date.AddYears(-2);
|
||||
var exchangeOptionTrade = DbContext.exchange_list_option;
|
||||
|
||||
var query = from t in DbContext.Exchange_Option_Trade
|
||||
join e in DbContext.exchange_list_option on t.Code equals e.ContractCode
|
||||
where t.TradeDate > startDate && t.TradeStatus == "确认成交" && e.MaturityDate <= date
|
||||
select t;
|
||||
|
||||
var trades = query.ToList();
|
||||
|
||||
foreach (var item in trades)
|
||||
{
|
||||
item.TradeStatus = "已平仓";
|
||||
item.ExerciseDate = date;
|
||||
item.ExercisePrice = 0;
|
||||
item.ExerciseServiceFee = 0;
|
||||
}
|
||||
|
||||
DbContext.SaveChanges();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存开仓交易
|
||||
/// </summary>
|
||||
private void SaveOpenTrade(DateTime date)
|
||||
{
|
||||
var trades = DbContext.ExchangeTrade
|
||||
.Where(t => t.TradeDate == date && t.TradeType == "场内期权" && t.IsValid && openTypes.Contains(t.TradeSide)).ToList();
|
||||
|
||||
|
||||
var result = new ExchangeTradeCommissionCalc().GetTradeCommission(trades);
|
||||
|
||||
var items = trades.Where(t => t.TradeType == "场内期权" && t.IsValid && openTypes.Contains(t.TradeSide))
|
||||
.Select(t => new Exchange_Option_Trade()
|
||||
{
|
||||
Code = t.OptionCode,
|
||||
//AssetBookName = t.AssetBookName,
|
||||
AssetId = t.AssetBookId,
|
||||
CreateDate = DateTime.Now,
|
||||
ExerciseDate = DateTime.MinValue,
|
||||
ExerciseMode = t.ExerciseMode,
|
||||
ExercisePrice = 0,
|
||||
TradeAmount = t.TradeAmount,
|
||||
//TradeUnitValue = GetTradeUnitValue(t.TradeUnit) ?? 0,
|
||||
//TradeUnit = Regex.Match(t.TradeUnit, @"(?<=\d)\D+").Value,
|
||||
ServiceFee = result.GetTradeCommission(t.id),
|
||||
OptionType = t.OptionType,
|
||||
Strike = t.OptionStrike ?? 0,
|
||||
TradeDate = t.TradeDate,
|
||||
TradePrice = t.TradeSinglePrice * t.Notional,
|
||||
TraderId = t.TraderId,
|
||||
TraderName = t.TraderName,
|
||||
TradeStatus = "确认成交",
|
||||
TradeType = t.TradeSide == "空头开仓" ? "空头" : "多头",
|
||||
UnderlyingCode = t.UnderlyingCode
|
||||
}).ToList();
|
||||
|
||||
if (items.Count > 0)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
var un = UnderlyingDataProvider.GetUnderlying(item.UnderlyingCode);
|
||||
if (un != null)
|
||||
{
|
||||
item.TradeUnitValue = un.ContractSize;
|
||||
item.TradeUnit = un.TradeUnitString;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.TradeUnit = "吨"; //为了收盘通过暂时增加这行代码
|
||||
}
|
||||
item.AssetBookName = DataCacheProvider.GetAssetUnitDataSource().GetData(item.AssetId)?.Name;
|
||||
}
|
||||
DbContext.Exchange_Option_Trade.AddRange(items);
|
||||
DbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存平仓交易
|
||||
/// </summary>
|
||||
private void SaveCloseTrade(DateTime date)
|
||||
{
|
||||
var trades = DbContext.ExchangeTrade.Where(t =>
|
||||
t.TradeDate == date &&
|
||||
t.TradeType == "场内期权" &&
|
||||
t.IsValid && closeTypes.Contains(t.TradeSide)).ToList();
|
||||
|
||||
var result = new ExchangeTradeCommissionCalc().GetTradeCommission(trades);
|
||||
|
||||
foreach (var close in trades)
|
||||
{
|
||||
var tradeType = "";
|
||||
switch (close.TradeSide)
|
||||
{
|
||||
case "多头平仓":
|
||||
tradeType = "多头";
|
||||
break;
|
||||
case "空头平仓":
|
||||
tradeType = "空头";
|
||||
break;
|
||||
}
|
||||
var tradeAmount = close.TradeAmount;
|
||||
var singlePrice = close.TradeSinglePrice;
|
||||
var singleServiceFee = result.GetTradeCommission(close.id) / tradeAmount;
|
||||
var openInfos =
|
||||
(from exchange in DbContext.Exchange_Option_Trade
|
||||
where
|
||||
exchange.TradeStatus == "确认成交" &&
|
||||
exchange.Code == close.OptionCode &&
|
||||
exchange.TradeType == tradeType
|
||||
orderby exchange.TradeDate
|
||||
select exchange)
|
||||
.ToList();
|
||||
foreach (var open in openInfos)
|
||||
{
|
||||
if (tradeAmount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (open.TradeAmount > tradeAmount)
|
||||
{
|
||||
var newTrade = open.Clone();
|
||||
newTrade.id = 0;
|
||||
newTrade.TradeAmount = open.TradeAmount - tradeAmount;
|
||||
newTrade.TradePrice = open.TradePrice / open.TradeAmount * newTrade.TradeAmount;
|
||||
newTrade.ServiceFee = open.ServiceFee / open.TradeAmount * newTrade.TradeAmount;
|
||||
DbContext.Exchange_Option_Trade.Add(newTrade);
|
||||
open.TradePrice = open.TradePrice / open.TradeAmount * tradeAmount;
|
||||
open.TradeAmount = tradeAmount;
|
||||
tradeAmount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tradeAmount = tradeAmount - open.TradeAmount;
|
||||
}
|
||||
open.ExerciseDate = close.TradeDate;
|
||||
open.ExercisePrice = singlePrice * open.TradeAmount;
|
||||
open.ExerciseServiceFee = singleServiceFee * open.TradeAmount;
|
||||
open.TradeStatus = "已平仓";
|
||||
DbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
using YLErp.Abstract.DataProviders;
|
||||
using YLErp.BLL;
|
||||
using YLErp.Modules.VolatilityModule;
|
||||
|
||||
namespace YLErp.Modules.ExchangeOptionTradeModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 场内期权波动率查询
|
||||
/// </summary>
|
||||
public class ExchangeOptionVolQueryService : YLBaseService
|
||||
{
|
||||
public ExchangeOptionVolQueryService(OptUserInfo userInfo) : base(userInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取场内期权保存的波动率
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public double? GetSavedVol(string optionCode, DateTime valueDate)
|
||||
{
|
||||
var (volValue, useFlag) = InnerGetSavedVol(optionCode, valueDate);
|
||||
return useFlag == ExchangeOptionVolUseFlag.FixedValue ? volValue : null;
|
||||
}
|
||||
|
||||
private (double? volValue, ExchangeOptionVolUseFlag useFlag) InnerGetSavedVol(string optionCode, DateTime valueDate)
|
||||
{
|
||||
valueDate = valueDate.Date;
|
||||
|
||||
var data = DbContext.exchange_option_vol
|
||||
.Where(v => v.OptionCode == optionCode && v.ValueDate <= valueDate)
|
||||
.OrderByDescending(v => v.ValueDate)
|
||||
.Select(n => new { n.Volatility, n.UseFlag })
|
||||
.FirstOrDefault();
|
||||
|
||||
return data != null ? (data.Volatility, data.UseFlag) : (null, ExchangeOptionVolUseFlag.SystemOrImpliedVol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取场内期权波动率
|
||||
/// </summary>
|
||||
/// <param name="valueDate">nullable时使用当前交易日期</param>
|
||||
/// <param name="optionCode"></param>
|
||||
/// <param name="underlyingPrice"></param>
|
||||
/// <param name="userGroup"></param>
|
||||
/// <returns></returns>
|
||||
public (double? volValue, ExchangeOptionVolResultType volType) GetVolValue(ExchangeOptionVolRequest request)
|
||||
{
|
||||
if (request is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.OptionCode))
|
||||
{
|
||||
throw new ServiceException("场内期权代码 不能为空");
|
||||
}
|
||||
|
||||
var valueDate = request.ValueDate ?? valuedateBLL.ValueDate;
|
||||
|
||||
//从数据库中获取保存的场内期权波动率值
|
||||
var (volValue, useFlag) = InnerGetSavedVol(request.OptionCode, valueDate);
|
||||
if (useFlag == ExchangeOptionVolUseFlag.FixedValue)
|
||||
{
|
||||
return (volValue, ExchangeOptionVolResultType.SavedFixVol);
|
||||
}
|
||||
|
||||
//特殊:光子只需要保存的波动率,故而返回null
|
||||
if (PS.Config.Is光大光子)
|
||||
{
|
||||
return (null, ExchangeOptionVolResultType.SavedFixVol);
|
||||
}
|
||||
|
||||
//根据配置获取系统或隐含波动率
|
||||
return GetSystemOrImpliedVol(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据配置获取系统或隐含波动率
|
||||
/// </summary>
|
||||
private (double? volValue, ExchangeOptionVolResultType volType) GetSystemOrImpliedVol(ExchangeOptionVolRequest request)
|
||||
{
|
||||
var valueDate = request.ValueDate ?? valuedateBLL.ValueDate;
|
||||
|
||||
var isImpliedVol = PS.Config.ErpElement.ExchangeOptionVolType == Configuration.Enums.ExchangeOptionVolType.ImpliedVol;
|
||||
var volResultType = isImpliedVol ? ExchangeOptionVolResultType.ImpliedVol : ExchangeOptionVolResultType.UnderlyingVol;
|
||||
|
||||
//取场内期权合约信息
|
||||
var exchangeOption = DataCacheProvider.GetExchangeListOptionDataSource().GetData(request.OptionCode);
|
||||
if (exchangeOption == null)
|
||||
{
|
||||
return (null, volResultType);
|
||||
}
|
||||
|
||||
//取场内期权标的信息
|
||||
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(exchangeOption.UnderlyingCode);
|
||||
if (underlying == null)
|
||||
{
|
||||
return (null, volResultType);
|
||||
}
|
||||
|
||||
//取场内期权标的价格
|
||||
double underlyingPrice;
|
||||
if (request.UnderlyingPrice == null)
|
||||
{
|
||||
if (request.UnderlyingPriceProvider?.Value == null)
|
||||
{
|
||||
throw new ServiceException("缺少标的价格提供接口");
|
||||
}
|
||||
|
||||
underlyingPrice = request.UnderlyingPriceProvider.Value.GetPrice(underlying.UnderlyingCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
underlyingPrice = request.UnderlyingPrice.Value;
|
||||
}
|
||||
|
||||
if (isImpliedVol)
|
||||
{
|
||||
if (request.ExchangeOptionPriceProvider?.Value == null)
|
||||
{
|
||||
throw new ServiceException("缺少场内期权价格提供接口");
|
||||
}
|
||||
|
||||
var exOptionPrice = request.ExchangeOptionPriceProvider.Value.GetPrice(exchangeOption.ContractCode);
|
||||
|
||||
var tempTrade = new trade
|
||||
{
|
||||
BuySell = "买入",
|
||||
TradeType = "场内期权",
|
||||
UnderlyingCode = underlying.UnderlyingCode,
|
||||
UnderlyingId = underlying.id,
|
||||
TradeDate = valueDate,
|
||||
StartDate = valueDate,
|
||||
ExerciseDate = exchangeOption.MaturityDate,
|
||||
MaturityDate = underlying.MaturityDate,
|
||||
TradePrice = exOptionPrice,
|
||||
TradeStatus = "确认成交",
|
||||
ExerciseMode = exchangeOption.ExerciseMode,
|
||||
OptionType = exchangeOption.OptionType,
|
||||
Strike = exchangeOption.Strike,
|
||||
Notional = 1,
|
||||
UnderlyingInstrumentType = underlying.UnderlyingInstrumentType,
|
||||
ExchangeOptionCode = exchangeOption.ContractCode,
|
||||
AssetId = 0,
|
||||
id = -1,
|
||||
UnderlyingAssetClass = underlying.UnderlyingType,
|
||||
|
||||
//用于反算隐含波动率
|
||||
StructureType = "场内期权",
|
||||
TradeSinglePrice = exOptionPrice
|
||||
};
|
||||
|
||||
var volValue = VolatilityHelper.GetImpliedVol(valueDate, tempTrade, null, underlyingPrice, false);
|
||||
|
||||
return (volValue, ExchangeOptionVolResultType.ImpliedVol);
|
||||
}
|
||||
else
|
||||
{
|
||||
var req = new SingleVolReq
|
||||
{
|
||||
VolType = VolatilityHelper.GetUnderlyingVolType(request.VolType),
|
||||
Strike = exchangeOption.Strike,
|
||||
SpotPrice = underlyingPrice,
|
||||
TradeDate = valueDate,
|
||||
ExerciseDate = exchangeOption.MaturityDate,
|
||||
IsMoneynessOption = "否",
|
||||
//CallPut = trade.CallPut;
|
||||
UnderlyingId = underlying.id,
|
||||
UnderlyingCode = underlying.UnderlyingCode,
|
||||
UnderlyingName = underlying.UnderlyingName,
|
||||
UnderlyingTypeId = underlying.UnderlyingTypeId,
|
||||
UserGroup = request.UserGroup
|
||||
};
|
||||
|
||||
double? volValue = null;
|
||||
|
||||
try
|
||||
{
|
||||
volValue = SingleVolService.GetSingleVol(req, 0);
|
||||
}
|
||||
catch { }
|
||||
|
||||
return (volValue, ExchangeOptionVolResultType.UnderlyingVol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 场内期权波动率查询
|
||||
/// </summary>
|
||||
public class ExchangeOptionVolRequest
|
||||
{
|
||||
public ExchangeOptionVolRequest()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 必需, 场内期权代码
|
||||
/// </summary>
|
||||
public string OptionCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 估值日期,为null时取系统交易日期
|
||||
/// </summary>
|
||||
public DateTime? ValueDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 必需,场内期权价格提供,用于计算隐含波动率
|
||||
/// </summary>
|
||||
public Lazy<IPriceProvider> ExchangeOptionPriceProvider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标的价格, savedVol无效时用于取隐含波动率或曲面波动率,为null时使用IUnderlyingPriceProvider获取
|
||||
/// </summary>
|
||||
public double? UnderlyingPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取标的价格的接口,UnderlyingPrice为null时使用此接口
|
||||
/// </summary>
|
||||
public Lazy<IPriceProvider> UnderlyingPriceProvider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户组,用于取曲面波动率
|
||||
/// </summary>
|
||||
public string UserGroup { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 波动率类型,未传入时TradeVol模式下使用交易Mid波动率,Volsurface模式下使用配置的结算波动率
|
||||
/// </summary>
|
||||
public string VolType { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 场内期权波动率结果类型
|
||||
/// </summary>
|
||||
public enum ExchangeOptionVolResultType
|
||||
{
|
||||
/// <summary>
|
||||
/// 保存的固定波动率
|
||||
/// </summary>
|
||||
SavedFixVol,
|
||||
|
||||
/// <summary>
|
||||
/// 曲面波动率
|
||||
/// </summary>
|
||||
UnderlyingVol,
|
||||
|
||||
/// <summary>
|
||||
/// 隐含波动率
|
||||
/// </summary>
|
||||
ImpliedVol
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
namespace YLErp.Modules.ExchangeOptionTradeModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 场内期权波动率保存服务
|
||||
/// </summary>
|
||||
public class ExchangeOptionVolSaveService : YLBaseService
|
||||
{
|
||||
public ExchangeOptionVolSaveService(OptUserInfo userInfo) : base(userInfo)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存场内期权波动率
|
||||
/// </summary>
|
||||
public int SaveExchangeOptionVol(string optionCode, DateTime valueDate, double volValue, ExchangeOptionVolUseFlag useFlag = ExchangeOptionVolUseFlag.FixedValue)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(optionCode))
|
||||
{
|
||||
throw new ArgumentException("参数不能为空值", nameof(optionCode));
|
||||
}
|
||||
|
||||
if (useFlag == ExchangeOptionVolUseFlag.FixedValue && volValue < 0)
|
||||
{
|
||||
throw new ArgumentException("请设置合理的场内期权波动率", nameof(volValue));
|
||||
}
|
||||
|
||||
valueDate = valueDate.Date;
|
||||
|
||||
var record = DbContext.exchange_option_vol.FirstOrDefault(x => x.OptionCode == optionCode && x.ValueDate == valueDate);
|
||||
|
||||
if (record == null)
|
||||
{
|
||||
record = new ExchangeOptionVol()
|
||||
{
|
||||
OptionCode = optionCode,
|
||||
ValueDate = valueDate,
|
||||
Volatility = volValue
|
||||
};
|
||||
|
||||
DbContext.exchange_option_vol.Add(record);
|
||||
}
|
||||
else if (useFlag == ExchangeOptionVolUseFlag.FixedValue)
|
||||
{
|
||||
record.Volatility = volValue;
|
||||
}
|
||||
|
||||
record.UseFlag = useFlag;
|
||||
record.OptId = UserId;
|
||||
record.OptDate = OptDate;
|
||||
return DbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user