200 lines
7.7 KiB
C#
200 lines
7.7 KiB
C#
using Qdp.Foundation.Implementations;
|
|
using Qdp.Pricing.Base.Utilities;
|
|
using YLErp.Models;
|
|
using YLErp.Modules;
|
|
using YLErp.Modules.CalculationModule;
|
|
|
|
namespace YLErp.BLL
|
|
{
|
|
public class trade_asian_optionBLL
|
|
{
|
|
/// <summary>
|
|
/// 计算亚式期权Floating类型交易的浮动行权价
|
|
/// </summary>
|
|
public static double? GetAsianStrikePrice(DateTime valueDate, trade trade)
|
|
{
|
|
var baseReq = AsianOptionFixingService.GetRequest(valueDate, trade);
|
|
var strikeReq = new AsianOptionStrikeRequest(baseReq)
|
|
{
|
|
IsMoneynessOption = trade.IsMoneynessOptionData,
|
|
SpotPrice = trade.SpotPrice,
|
|
Strike = trade.Strike,
|
|
};
|
|
tradeBLL.SetFieldsByTradeType(trade);
|
|
return GetAsianStrikePrice(strikeReq, trade.trade_asian_option);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取亚式期权行权价
|
|
/// </summary>
|
|
public static double? GetAsianStrikePrice(AsianOptionStrikeRequest request, trade_asian_option asianOption)
|
|
{
|
|
if (request is null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (asianOption is null)
|
|
{
|
|
using (var db = DbContextFactory.GetYLDbContext())
|
|
{
|
|
asianOption = request.TradeId > 0 ? db.trade_asian_option.AsNoTracking().FirstOrDefault(n => n.TradeId == request.TradeId) : null;
|
|
}
|
|
|
|
if (asianOption is null)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if ("Floating".Equals(asianOption.StrikeType, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
var fixings = AsianOptionFixingService.GetFixingString(request, asianOption);
|
|
|
|
if (string.IsNullOrWhiteSpace(fixings))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var fixingValues = fixings.Split(QdpConsts.Semilicon).Select(x =>
|
|
{
|
|
var splits = x.Split(QdpConsts.Comma);
|
|
return Tuple.Create(splits[0].ToDate(), double.Parse(splits[1]));
|
|
}).ToDictionary(x => x.Item1, x => x.Item2);
|
|
if ("GeometricAverage".Equals(asianOption.PayoffType))
|
|
{
|
|
var n = fixingValues.Count;
|
|
return Math.Pow(fixingValues.Select(x => x.Value).Aggregate(func: (result, item) => result * item), 1.0 / n);
|
|
}
|
|
else if ("ArithmeticAverage".Equals(asianOption.PayoffType)
|
|
|| "DiscreteArithmeticAverage".Equals(asianOption.PayoffType)
|
|
|| "EnhancedArithmeticAverage".Equals(asianOption.PayoffType))
|
|
{
|
|
return fixingValues.Select(x => x.Value).Average();
|
|
}
|
|
}
|
|
|
|
return request.IsMoneynessOption ? (request.SpotPrice * request.Strike) : request.Strike;
|
|
}
|
|
|
|
//TODO:除权除息
|
|
|
|
/// <summary>
|
|
/// 计算亚式期权Fix类型交易的浮动行权价
|
|
/// </summary>
|
|
public static double? GetAsianFinalPrice(trade trade, DateTime? valueDate = null)
|
|
{
|
|
if (trade is null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (valueDate == null)
|
|
{
|
|
valueDate = valuedateBLL.ValueDate;
|
|
}
|
|
|
|
tradeBLL.SetFieldsByTradeType(trade);
|
|
|
|
var asianOption = trade.trade_asian_option;
|
|
|
|
if (asianOption is null)
|
|
{
|
|
using (var db = DbContextFactory.GetYLDbContext())
|
|
{
|
|
trade.trade_asian_option = asianOption = db.trade_asian_option.AsNoTracking().FirstOrDefault(n => n.TradeId == trade.id);
|
|
}
|
|
|
|
if (asianOption is null)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if ("Fixed".Equals(asianOption.StrikeType, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
var fixings = AsianOptionFixingService.GetFixingString(valueDate.Value, trade);
|
|
|
|
if (string.IsNullOrWhiteSpace(fixings))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var fixingValues = fixings.Split(QdpConsts.Semilicon).Select(x =>
|
|
{
|
|
var splits = x.Split(QdpConsts.Comma);
|
|
return Tuple.Create(splits[0].ToDate(), double.Parse(splits[1]));
|
|
}).ToDictionary(x => x.Item1, x => x.Item2);
|
|
if ("GeometricAverage".Equals(asianOption.PayoffType))
|
|
{
|
|
var n = fixingValues.Count;
|
|
return Math.Pow(fixingValues.Select(x => x.Value).Aggregate(func: (result, item) => result * item), 1.0 / n);
|
|
}
|
|
else if ("ArithmeticAverage".Equals(asianOption.PayoffType)
|
|
|| "DiscreteArithmeticAverage".Equals(asianOption.PayoffType))
|
|
{
|
|
return fixingValues.Select(x => x.Value).Average();
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取亚式期权 均价起算日之后的均价 未到均价起算日则返回Null
|
|
/// </summary>
|
|
public static double? GetAsianAveragePrice(trade trade)
|
|
{
|
|
if (trade.trade_asian_option == null)
|
|
{
|
|
tradeBLL.SetFieldsByTradeType(trade);
|
|
}
|
|
|
|
if (null != trade.trade_asian_option)
|
|
{
|
|
var fixings = AsianOptionFixingService.GetFixingString(valuedateBLL.ValueDate, trade);
|
|
|
|
if (!string.IsNullOrWhiteSpace(fixings))
|
|
{
|
|
var fixingValues = string.IsNullOrEmpty(fixings)
|
|
? new Dictionary<Date, double>() :
|
|
fixings.Split(QdpConsts.Semilicon)
|
|
.Select(x =>
|
|
{
|
|
var splits = x.Split(QdpConsts.Comma);
|
|
return Tuple.Create(splits[0].ToDate(), double.Parse(splits[1]));
|
|
}).ToDictionary(x => x.Item1, x => x.Item2);
|
|
if ("GeometricAverage".Equals(trade.trade_asian_option.PayoffType))
|
|
{
|
|
var n = fixingValues.Count;
|
|
return Math.Pow(fixingValues.Select(x => x.Value).Aggregate(func: (result, item) => result * item), 1.0 / n);
|
|
}
|
|
else if ("ArithmeticAverage".Equals(trade.trade_asian_option.PayoffType) || "DiscreteArithmeticAverage".Equals(trade.trade_asian_option.PayoffType))
|
|
{
|
|
return fixingValues.Select(x => x.Value).Average();
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public class AsianOptionStrikeRequest : AsianFixingRequest
|
|
{
|
|
public AsianOptionStrikeRequest(FixingRequestBase baseReq) : base(baseReq)
|
|
{
|
|
}
|
|
|
|
public AsianOptionStrikeRequest(DateTime valueDate, int tradeId, string instrumentType, string underlyingCode, DateTime exerciseDate, SettlementTypeEnum settlementType)
|
|
: base(valueDate, tradeId, instrumentType, underlyingCode, exerciseDate, settlementType)
|
|
{
|
|
}
|
|
|
|
public bool IsMoneynessOption { get; set; }
|
|
|
|
public double? Strike { get; set; }
|
|
|
|
public double? SpotPrice { get; set; }
|
|
}
|
|
}
|