170 lines
6.1 KiB
C#
170 lines
6.1 KiB
C#
using Qdp.Pricing.Base.Implementations;
|
|
using Qdp.Pricing.Library.Equity.Engines.Analytical;
|
|
|
|
namespace YLErp.Modules.VolatilityModule
|
|
{
|
|
/// <summary>
|
|
/// 交易波动率提供(适用于UseTradeVol)
|
|
/// </summary>
|
|
public class TradeVolitalityProvider
|
|
{
|
|
protected readonly DateTime _valueDate;
|
|
|
|
Dictionary<int, InnerTradeVolatility> _dicData;
|
|
|
|
public TradeVolitalityProvider(DateTime valueDate)
|
|
{
|
|
_valueDate = valueDate.Date;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 如果设为true程序内部将不会再进行数据初始化,
|
|
/// 这样做的目的是为了少量数据获取时避免初始化带来的性能损失
|
|
/// </summary>
|
|
public bool Initialized { get; set; }
|
|
|
|
private void Initialize()
|
|
{
|
|
if (_dicData != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lock (this)
|
|
{
|
|
if (_dicData != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (Initialized)
|
|
{
|
|
_dicData = new Dictionary<int, InnerTradeVolatility>();
|
|
}
|
|
else
|
|
{
|
|
//只取3个月以内的
|
|
var startDate = _valueDate.AddMonths(-3);
|
|
|
|
using var db = DbContextFactory.GetYLDbContext();
|
|
var query1 = from a in db.TradeVolatility
|
|
where a.ValueDate > startDate && a.ValueDate <= _valueDate
|
|
group a by a.TradeId into g
|
|
select new { TradeId = g.Key, ValueDate = g.Max(n => n.ValueDate) };
|
|
|
|
var query2 = from a in query1
|
|
join b in db.TradeVolatility on a equals new { b.TradeId, b.ValueDate }
|
|
select new InnerTradeVolatility
|
|
{
|
|
TradeId = b.TradeId,
|
|
ValueDate = b.ValueDate,
|
|
NumOfSmoothingDays = b.NumOfSmoothingDays,
|
|
TradePositionVolatility = b.TradePositionVolatility,
|
|
TradeCloseVolatility = b.TradeCloseVolatility,
|
|
IsFromTradeAdd = b.IsFromTradeAdd
|
|
};
|
|
|
|
_dicData = query2.ToDictionary(n => n.TradeId, m => m);
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool TryGetVol(int tradeId, DateTime tradeExerciseDate, out double vol)
|
|
{
|
|
Initialize();
|
|
|
|
if (!_dicData.TryGetValue(tradeId, out var tradeVol) && tradeId > 0)
|
|
{
|
|
using var db = DbContextFactory.GetYLDbContext();
|
|
_dicData[tradeId] = tradeVol = db.TradeVolatility
|
|
.Where(v => v.TradeId == tradeId && v.ValueDate <= _valueDate)
|
|
.OrderByDescending(v => v.ValueDate)
|
|
.Select(b => new InnerTradeVolatility
|
|
{
|
|
TradeId = b.TradeId,
|
|
ValueDate = b.ValueDate,
|
|
NumOfSmoothingDays = b.NumOfSmoothingDays,
|
|
TradePositionVolatility = b.TradePositionVolatility,
|
|
TradeCloseVolatility = b.TradeCloseVolatility,
|
|
IsFromTradeAdd = b.IsFromTradeAdd
|
|
}).FirstOrDefault();
|
|
}
|
|
|
|
if (tradeVol == null)
|
|
{
|
|
vol = 0;
|
|
return false;
|
|
}
|
|
|
|
if (tradeVol.ResultVol.HasValue)
|
|
{
|
|
vol = tradeVol.ResultVol.Value;
|
|
return true;
|
|
}
|
|
|
|
if (_valueDate < tradeVol.ValueDate)
|
|
{
|
|
vol = tradeVol.TradePositionVolatility ?? 0;
|
|
}
|
|
else if (_valueDate > tradeExerciseDate)
|
|
{
|
|
vol = tradeVol.TradeCloseVolatility ?? 0;
|
|
}
|
|
else
|
|
{
|
|
var daycountMode = PS.Config.ErpElement.SmoothingDaycountMode == Configuration.Enums.SmoothingDaycountMode.CalendarDay
|
|
? Qdp.Pricing.Base.Enums.DayCountMode.CalendarDay
|
|
: Qdp.Pricing.Base.Enums.DayCountMode.TradingDay;
|
|
|
|
//新增交易当天的持仓波动率需要划掉一天,修改后的持仓波动率不需要再划一天
|
|
vol = AnalyticalOptionTradeVolInterp.tradeVolLinearInterp(
|
|
new Qdp.Foundation.Implementations.Date(_valueDate),
|
|
tradeVol.TradePositionVolatility ?? 0,
|
|
tradeVol.TradeCloseVolatility ?? 0,
|
|
new Qdp.Foundation.Implementations.Date(tradeVol.ValueDate),
|
|
new Qdp.Foundation.Implementations.Date(tradeExerciseDate),
|
|
tradeVol.NumOfSmoothingDays ?? 0,
|
|
daycountMode,
|
|
CalendarImpl.Get("chn"),
|
|
includeStartDate: tradeVol.IsFromTradeAdd);
|
|
}
|
|
|
|
tradeVol.ResultVol = vol;
|
|
|
|
return true;
|
|
}
|
|
|
|
class InnerTradeVolatility
|
|
{
|
|
public int TradeId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 操作系统日
|
|
/// </summary>
|
|
public DateTime ValueDate { get; set; }
|
|
|
|
/// <summary>
|
|
/// 持仓波动率
|
|
/// </summary>
|
|
public double? TradePositionVolatility { get; set; }
|
|
|
|
/// <summary>
|
|
/// 目标波动率
|
|
/// </summary>
|
|
public double? TradeCloseVolatility { get; set; }
|
|
|
|
/// <summary>
|
|
/// 平滑天数
|
|
/// </summary>
|
|
public int? NumOfSmoothingDays { get; set; }
|
|
|
|
/// <summary>
|
|
/// 是否是新增交易时添加的波动率记录
|
|
/// </summary>
|
|
public bool IsFromTradeAdd { get; set; }
|
|
|
|
public double? ResultVol { get; set; }
|
|
}
|
|
}
|
|
}
|