Files
zszq-trs/YLErpDAL/BLL/MarginCalculation/GuoXinJinYangMarginCalculation.cs
T
2024-05-09 14:06:26 +08:00

801 lines
46 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Qdp.Foundation.Implementations;
using YLErp.Abstract.DataProviders;
using YLErp.BLL.Calculation;
using YLErp.Enums;
using YLErp.Model.Enum;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.MarginModule;
using YLErp.QdpModule;
namespace YLErp.BLL.MarginCalculation
{
public class GuoXinJinYangMarginCalculation : MarginCalculationBase
{
public static readonly GuoXinJinYangMarginCalculation Instance;
static GuoXinJinYangMarginCalculation()
{
Instance = new GuoXinJinYangMarginCalculation();
}
public GuoXinJinYangMarginCalculation()
{
}
public override List<trade_span> RunMarginCalculation(RunMarginCalculationReq req)
{
if (req?.tradeList == null || !req.tradeList.Any())
{
return new List<trade_span>();
}
var calcTradeList = req.tradeList.ToList();
var resultMap = new Dictionary<int, trade_span>();
var helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
helper.SetFieldsByTradeType();
var mpProvider = helper.GetMarginParamProvider(MarginParamTypeEnum.MarginRate | MarginParamTypeEnum.UpDownLimit);
helper.GetUpDownLimitPrices(out var upLimitPrices, out var downLimitPrices);
helper.GetTradVolRateDic(out var tradeVolRateDic);
//获取执行价格,敲出 ,敲入价格
//获取有敲出敲入 点位交易
IPriceProvider knockInPricesDic = new Modules.DataProviderModule.ManualPriceProvider();
IPriceProvider knockOutPricesDic = new Modules.DataProviderModule.ManualPriceProvider();
var prices = new Dictionary<string, IPriceProvider>();
prices.Add("up", upLimitPrices);
prices.Add("down", downLimitPrices);
prices.Add("normal", req.PriceProvider);
var TradeStockEqvNotional = req.tradeList.GroupBy(l => l.ClientId).Select(l => new { clientId = l.Key, maxStockEqvNotional = l.Max(g => g.StockEqvNotional) });
var clientList = new List<int?>();
//获取 超过阈值客户
using (var db = new YLContext())
{
foreach (var s in TradeStockEqvNotional)
{
var clients = db.MarginCalculationThreshold.Where(l => l.ClientId == s.clientId && l.MarginCalcuThreshold < s.maxStockEqvNotional && l.TakeEffectDate <= req.settleDate).OrderByDescending(l => l.TakeEffectDate).Select(l => l.ClientId).FirstOrDefault();
if (clients != null) clientList.Add(clients);
}
}
//获取每笔 交易 的 敲出 敲出点位
var barPriceDic = KnockInandKnockOutPriceByTradeList(req.tradeList, req.settleDate, clientList);
if (barPriceDic.Count > 0)
{
var listPrice = barPriceDic.Select(l => new { key = l.Key, value = double.TryParse(l.Value?.ToString(), out var a) ? a : 0 }).Where(l => l.value < upLimitPrices.GetPrice(l.key.Split(',')[1]) && l.value > downLimitPrices.GetPrice(l.key.Split(',')[1])).ToList();
if (listPrice.Count > 0)
{
var listDicprice = listPrice.GroupBy(l => new { ucode = (l.key.Split(',')[1]), price = l.value }).Select(l => l.Key).ToList();
for (var i = 0; i < listDicprice.Count; i++)
{
var barPrices = new ManualPriceProvider();
barPrices.SetPrice(listDicprice[i].ucode, listDicprice[i].price);
prices.Add("barPrice," + listDicprice[i].ucode + "," + i, barPrices);
}
}
}
var volRates = new[] { null, tradeVolRateDic };
var loops = prices.ToList().SelectMany(n => volRates.Select(m => new
{
pricekey = n.Key,
priceProvider = n.Value,
addVolRateDic = m
})).ToArray();
var pVJsons = new List<PVJson>();
foreach (var loop in loops)
{
var calcReq = helper.GetCalculateRisksForTradesReq(priceProvider: loop.priceProvider, addVolRateDic: loop.addVolRateDic, overrideVols: null, pricekey: loop.pricekey);
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(calcReq);
if (tradeRiskResult.Results == null || tradeRiskResult.Results.Count < 1)
{
continue;
}
var key = $"{loop.pricekey}_{(loop.addVolRateDic == null ? 0 : 1)}";
foreach (var item in tradeRiskResult.Results)
{
var client = helper.GetClient(item.Trade.ClientId);
var clientRatio = client?.Ratio ?? 1.0;
var clientRatio1 = client?.Ratio1 ?? 1.0;
var contains = resultMap.TryGetValue(item.Trade.id, out var tempTradeSpan);
if (!contains)
{
resultMap[item.Trade.id] = tempTradeSpan = helper.CreateTradeSpan(item.Trade);
}
var pv = item.ValueResult.Pv;
if (!helper.GetSpecialMargin(item.Trade, pv, out var value))
{
if (req.CalcMarginType == CalcMarginTypeEnum.InitialMargin)
{
value = double.IsNaN(pv) ? 0 : pv * clientRatio1;
}
else
{
value = double.IsNaN(pv) ? 0 : pv * clientRatio;
}
}
var pVJson = new PVJson();
int VarietyId = 0;
using (var db = new YLContext())
{
var Variety = db.underlying_manager.AsNoTracking().Where(t => t.id == item.Trade.UnderlyingId).FirstOrDefault();
if (Variety != null) { VarietyId= Variety.UnderlyingTypeId; }
}
//var v item.Trade.UnderlyingId;
switch (key)
{
case "up_1":
pVJson.TradeId = item.Trade.id;
pVJson.VarietyId = VarietyId;
pVJson.Name = "up_1";
pVJson.ClientId = item.Trade.ClientId;
pVJson.Value = value;
pVJsons.Add(pVJson);
break;
case "up_0":
pVJson.TradeId = item.Trade.id;
pVJson.VarietyId = VarietyId;
pVJson.ClientId = item.Trade.ClientId;
pVJson.Name = "up_0";
pVJson.Value = value;
pVJsons.Add(pVJson); break;
case "normal_0":
pVJson.TradeId = item.Trade.id;
pVJson.VarietyId = VarietyId;
pVJson.ClientId = item.Trade.ClientId;
pVJson.Name = "normal_0";
pVJson.Value = value;
pVJsons.Add(pVJson); break;
case "normal_1":
pVJson.TradeId = item.Trade.id;
pVJson.VarietyId = VarietyId;
pVJson.ClientId = item.Trade.ClientId;
pVJson.Name = "normal_1";
pVJson.Value = value;
pVJsons.Add(pVJson); break;
case "down_1":
pVJson.TradeId = item.Trade.id;
pVJson.VarietyId = VarietyId;
pVJson.ClientId = item.Trade.ClientId;
pVJson.Name = "down_1";
pVJson.Value = value;
pVJsons.Add(pVJson); break;
case "down_0":
pVJson.TradeId = item.Trade.id;
pVJson.VarietyId = VarietyId;
pVJson.ClientId = item.Trade.ClientId;
pVJson.Name = "down_0";
pVJson.Value = value;
pVJsons.Add(pVJson); break;
default:
pVJson.TradeId = item.Trade.id;
pVJson.VarietyId = VarietyId;
pVJson.ClientId = item.Trade.ClientId;
pVJson.Name = key;
pVJson.Value = value;
pVJsons.Add(pVJson); break;
}
if (contains)
{
//tempTradeSpan.SetWorstCastClientPayable();
tempTradeSpan.WorstCastClientPayable = pVJsons.Max(l => l.Value);
if (client != null)
{
var value2 = (double)tempTradeSpan.WorstCastClientPayable;
if (client.MarginOptionType == (int)MarginOptionEnum.单向追保)
{
value2 = item.Trade.BuySell == "卖出" ? 0 : Math.Max(value2, 0);
}
tempTradeSpan.WorstCastClientPayable = value2;
}
}
}
}
pVJsons.GroupBy(l => l.TradeId).ToList().ForEach(tId =>
{
resultMap[tId.Key].PVJsonList = pVJsons.Where(l => l.TradeId == tId.Key).ToList();
//resultMap[tId.Key].WorstCastClientPayable = pVJsons.Max(l => l.Value);
resultMap[tId.Key].PVJsons = JsonHelper.ToJson(resultMap[tId.Key].PVJsonList);
});
return resultMap.Values.ToList();
}
public override List<trade_span> CalcClientMargin(CalcClientMarginReq req)
{
var clientSpanNews = new List<ClientSpan>();
var runMargin = new RunMarginCalculationReq(req.UserInfo);
runMargin.settleDate = req.settleDate;
var helper = new RunMarginCalculationHelper(runMargin, _underlyingDataProvider);
using (var db = new YLContext())
{
var tradeIds = req.tradeSpans.Select(t => t.TradeId).ToList();
var tradeList = db.trade.AsNoTracking().Where(t => tradeIds.Contains(t.id)).ToList();
var underlyingIdList = tradeList.Select(t => t.UnderlyingId).ToList();
var underlyingList = db.underlying_manager.AsNoTracking().Where(t => underlyingIdList.Contains(t.id)).ToList();
var tradeSpanInfo = (from tradeSpan in req.tradeSpans
join trade in tradeList on tradeSpan.TradeId equals trade.id
join um in underlyingList on trade.UnderlyingId equals um.id
where tradeSpan.ValueDate == req.settleDate
select new { trade, tradeSpan, um.UnderlyingTypeId}).ToList();
var clientGroups = tradeSpanInfo.GroupBy(t => t.trade.ClientId);
foreach (var clientGroup in clientGroups)
{
var varietyGroups = clientGroup.GroupBy(t => t.UnderlyingTypeId).Select(t => new ClientSpan
{
VarietyId = t.Key,
ClientId = clientGroup.Key,
ValueDate = req.settleDate,
OptId = req.userId,
OptName = req.userName,
OptDate = DateTime.Now,
SpanType = req.SpanType,
PVJsonList = t.SelectMany(l => l.tradeSpan.PVJsonList.Select(x => new ClientPVJson { Name = x.Name, Value = x.Value, VarietyId = x.VarietyId })).ToList()
}).ToList();
foreach (var item in varietyGroups)
{
if (item.PVJsonList != null && item.PVJsonList.Any())
{
var sumPVModel = item.PVJsonList.GroupBy(l => new { l.Name, l.VarietyId }).Select(x => new { PvName = x.Key.Name, sumPv = -x.Sum(l => l.Value) });
var minModel = sumPVModel.OrderBy(l => l.sumPv).FirstOrDefault();
item.WorstCastClientPayable = minModel.sumPv;
#region 更新tradeSpan,使得每笔交易的持仓预付金和客户预付金计算用的Spv组保持一致
var tradeIdList = clientGroup.Where(x => x.UnderlyingTypeId == item.VarietyId).Select(x => x.tradeSpan.TradeId);
var tradeSpansUpdate = db.trade_span.Where(x => tradeIdList.Contains(x.TradeId) && x.ClientId == item.ClientId && x.ValueDate == req.settleDate).ToList();
var tradeSpansReq = req.tradeSpans.Where(x => tradeIdList.Contains(x.TradeId) && x.ClientId == item.ClientId && x.ValueDate == req.settleDate).ToList();
if (item.PVJsonList.Any(l => l.Name == minModel.PvName))
{
tradeSpansUpdate.ForEach(x =>
{
if (x.PVJsons != null)
{
x.PVJsonList = JsonHelper.Deserialize<List<PVJson>>(x.PVJsons);
if (x.PVJsonList != null && x.PVJsonList.Any(l => l.Name == minModel.PvName))
{
x.WorstCastClientPayable = x.PVJsonList.FirstOrDefault(l => l.Name == minModel.PvName).Value;
}
}
});
tradeSpansReq.ForEach(x =>
{
if (x.PVJsons != null)
{
x.PVJsonList = JsonHelper.Deserialize<List<PVJson>>(x.PVJsons);
if (x.PVJsonList != null && x.PVJsonList.Any(l => l.Name == minModel.PvName))
{
x.WorstCastClientPayable = x.PVJsonList.FirstOrDefault(l => l.Name == minModel.PvName).Value;
}
}
});
}
#endregion
}
}
var clientSpan = new ClientSpan
{
ClientId = clientGroup.Key,
ValueDate = req.settleDate,
DeltaMargin = tradeSpanInfo.Where(g => g.trade.ClientId == clientGroup.Key).Sum(g => g.tradeSpan.DeltaMargin * -1),
//负数代表客户应缴预付金,正数代表客户应收预付金
WorstCastClientPayable = varietyGroups.Sum(g => g.WorstCastClientPayable),
OptId = req.userId,
OptName = req.userName,
OptDate = DateTime.Now,
SpanType = req.SpanType,
AdditionalWorstCastClientPayable = req.clientAdditionalMarginDic != null && req.clientAdditionalMarginDic.TryGetValue(clientGroup.Key, out var dd) ? dd : 0
};
if (!HasTwoSideMargin(clientGroup.Key))
{
double? worstCastClientPayable = 0;
foreach (var vg in varietyGroups)
{
if (vg.WorstCastClientPayable < 0)
{
worstCastClientPayable += vg.WorstCastClientPayable;
}
else
{
var tradeIdList = clientGroup.Where(l=>l.UnderlyingTypeId == vg.VarietyId).Select(x => x.tradeSpan.TradeId);
var tradeSpansUpdate = db.trade_span.Where(x => tradeIdList.Contains(x.TradeId) && x.ClientId == vg.ClientId && x.ValueDate == req.settleDate).ToList();
var tradeSpansReq = req.tradeSpans.Where(x => tradeIdList.Contains(x.TradeId) && x.ClientId == vg.ClientId && x.ValueDate == req.settleDate).ToList();
tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = 0);
tradeSpansReq.ForEach(x => x.WorstCastClientPayable = 0);
}
}
clientSpan.WorstCastClientPayable = worstCastClientPayable;
//foreach (var item in varietyGroups)
//{
// var tradeIdList = clientGroup.Select(x => x.tradeSpan.TradeId);
// var tradeSpansUpdate = db.trade_span.Where(x => tradeIdList.Contains(x.TradeId) && x.ClientId == item.ClientId && x.ValueDate == req.settleDate).ToList();
// var tradeSpansReq = req.tradeSpans.Where(x => tradeIdList.Contains(x.TradeId) && x.ClientId == item.ClientId && x.ValueDate == req.settleDate).ToList();
// tradeSpansUpdate.ForEach(x => x.WorstCastClientPayable = 0);
// tradeSpansReq.ForEach(x => x.WorstCastClientPayable = 0);
//}
}
clientSpan.PVJsonList = varietyGroups.SelectMany(l => l.PVJsonList.GroupBy(x => new { x.Name, x.VarietyId }).Select(x => new ClientPVJson { Name = x.Key.Name, Value = -x.Sum(a => a.Value), VarietyId = x.Key.VarietyId }));
clientSpan.PVJsons = JsonHelper.ToJson(clientSpan.PVJsonList);
clientSpanNews.Add(clientSpan);
}
//span类型为实时删除所有实时计算的交易的预付金信息
if (req.SpanType == ClientSpan.SpanType_RealTime)
{
if (req.RefreshClientIds != null)
{
db.BulkDelete<ClientSpan>($"{nameof(ClientSpan.ClientId)} in @ids", new { ids = req.RefreshClientIds });
}
else
{
db.BulkDelete<ClientSpan>($"{nameof(ClientSpan.SpanType)}=@SpanType", new { req.SpanType });
}
}
else
{
if (req.ClientIds != null)
{
var sql = $"{nameof(ClientSpan.ClientId)} in @ids and {nameof(ClientSpan.ValueDate)}=@settleDate and {nameof(ClientSpan.SpanType)}={req.SpanType} and {nameof(ClientSpan.ModifiedFlag)}=0";
db.BulkDelete<ClientSpan>(sql, new { req.settleDate, ids = req.ClientIds });
}
else
{
var sql = $"{nameof(ClientSpan.ValueDate)}=@settleDate and {nameof(ClientSpan.SpanType)}={req.SpanType} and {nameof(ClientSpan.ModifiedFlag)}=0";
db.BulkDelete<ClientSpan>(sql, new { req.settleDate });
}
var clientSpanOldsWithFlag = db.client_span.Where(t => t.ValueDate == req.settleDate && t.SpanType == req.SpanType && t.ModifiedFlag)
.Select(n => new { n.ValueDate, n.ClientId }).ToList();
//筛选出可以修改的clientSpan
clientSpanNews = clientSpanNews.Where(c => !clientSpanOldsWithFlag.Any(t => t.ValueDate == c.ValueDate && t.ClientId == c.ClientId)).ToList();
}
if (clientSpanNews.Count > 0)
{
MySqlBulkExtensions.BulkInsert(db, clientSpanNews);
}
db.SaveChanges();
return req.tradeSpans;
}
}
public override double GetTradeMargin(GetTradeMarginReq req)
{
var trade = req.trade;
using (var db = new YLContext())
{
if (trade.TradeType == "结构化交易")
{
trade.SubTrades = db.trade.Where(x => x.ParentTradeId == trade.id).ToList();
}
}
var tradeMargin = RunMarginCalculation(req.GetRunMarginCalculationReq());
if (null != tradeMargin && tradeMargin.FirstOrDefault() != null)
{
var margin = tradeMargin.FirstOrDefault().WorstCastClientPayable ?? 0.0;
return margin;
}
return 0.0;
}
public Dictionary<string, double?> KnockInandKnockOutPriceByTradeList(List<trade> listTrade, DateTime settleDate, List<int?> clientList)
{
var observationStatus = new List<string>() { "已敲入", "已敲出", "观察中" };
var dicPrice = new Dictionary<string, double?>();
foreach (var t in listTrade)
{
//过滤没超过阈值客户
if (!clientList.Contains(t.ClientId))
{
continue;
}
switch (t.TradeType)
{
case "障碍期权":
{
var barrier = t.trade_barrier_option?.Clone() ?? new trade_barrier_option();
if (string.IsNullOrEmpty(barrier.ObservationDates))
{
barrier.LatestObservationDate = settleDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(barrier.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= settleDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
barrier.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
barrier.LatestObservationDate = null;
}
}
if (observationStatus.Contains(barrier.KnockInOutStatusCn))
{
if (barrier.LatestObservationDate == settleDate)
{
var ObservationStatus = barrier.KnockInOutStatusCn;
var konckInOutDate = barrier.KnockInOutDate;
if (barrier.BarrierPrice != null)
{
var BarrierLow = t.IsMoneynessOption == "是" ? barrier.BarrierPrice * t.SpotPrice : barrier.BarrierPrice;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
}
if (barrier.UpperBarrierPrice != null)
{
var BarrierHigh = t.IsMoneynessOption == "是" ? barrier.UpperBarrierPrice * t.SpotPrice : barrier.UpperBarrierPrice;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", BarrierHigh);
}
}
}
}
break;
case "双鲨期权":
{
var doubleSharkFin = t.trade_double_sharkfin_option?.Clone() ?? new trade_double_sharkfin_option();
if (string.IsNullOrEmpty(doubleSharkFin.ObservationDates))
{
doubleSharkFin.LatestObservationDate = settleDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(doubleSharkFin.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= settleDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
doubleSharkFin.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
doubleSharkFin.LatestObservationDate = null;
}
}
if (observationStatus.Contains(doubleSharkFin.KnockInOutStatusCn))
{
if (doubleSharkFin.LatestObservationDate == settleDate)
{
var ObservationStatus = doubleSharkFin.KnockInOutStatusCn;
var konckInOutDate = doubleSharkFin.KnockInOutDate;
var BarrierLow = t.IsMoneynessOption == "是" ? doubleSharkFin.BarrierLow * t.SpotPrice : doubleSharkFin.BarrierLow;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
var BarrierHigh = t.IsMoneynessOption == "是" ? doubleSharkFin.BarrierHigh * t.SpotPrice : doubleSharkFin.BarrierHigh;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", BarrierHigh);
}
}
}
break;
case "凤凰期权":
{
var tradeautocall = t.trade_autocall?.Clone() ?? new trade_autocall();
using (var db = new YLContext())
{
tradeautocall.HappenedObservations = db.autocall_observation.AsNoTracking().Where(o => o.TradeId == t.id && o.EndDate <= DateTime.MaxValue).ToList();
}
if (string.IsNullOrEmpty(tradeautocall.ObservationDates))
{
tradeautocall.LatestObservationDate = settleDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(tradeautocall.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= settleDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
tradeautocall.LatestObservationDate = latestObservationDate.DateTime;
}
}
if (string.IsNullOrEmpty(tradeautocall.KOObservationDates))
{
tradeautocall.LatestKOObservationDate = settleDate;
tradeautocall.LatestKOBarrier = tradeautocall.KOBarrier;
if (tradeautocall.LatestKOBarrier != null)
{
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "LatestKOBarrier", tradeautocall.LatestKOBarrier);
}
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(tradeautocall.KOObservationDates);
var koObservationDates = customizedResults.Item1;
var customizedKOBarriers = customizedResults.Item2;
var latestKOObservationDate = koObservationDates.Where(x => x.DateTime >= settleDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestKOObservationDate != null)
{
tradeautocall.LatestKOObservationDate = latestKOObservationDate.DateTime;
if (customizedKOBarriers == null || !customizedKOBarriers.Any())
{
tradeautocall.LatestKOBarrier = tradeautocall.KOBarrier;
}
else
{
tradeautocall.LatestKOBarrier = customizedKOBarriers[GetDateIndex(koObservationDates, latestKOObservationDate)];
}
if (tradeautocall.LatestKOBarrier != null)
{ dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "LatestKOBarrier", tradeautocall.LatestKOBarrier); }
}
}
if (observationStatus.Contains(tradeautocall.KnockInOutStatusCn))
{
if (tradeautocall.LatestObservationDate == settleDate || tradeautocall.LatestKOObservationDate == settleDate)
{
var ObservationStatus = tradeautocall.KnockInOutStatusCn;
var konckInOutDate = tradeautocall.KnockInOutDate;
var BarrierLow = t.IsMoneynessOption == "是" ? tradeautocall.KIBarrier * t.SpotPrice : tradeautocall.KIBarrier;
var BarrierHigh = t.IsMoneynessOption == "是" ? tradeautocall.KOBarrier * t.SpotPrice : tradeautocall.KOBarrier;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", BarrierHigh);
}
}
}
break;
case "雪球期权":
{
var snowball = t.trade_snowball?.Clone() ?? new trade_snowball();
if (string.IsNullOrEmpty(snowball.ObservationDates))
{
snowball.LatestObservationDate = settleDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(snowball.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= settleDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
snowball.LatestObservationDate = latestObservationDate.DateTime;
}
}
if (string.IsNullOrEmpty(snowball.KOObservationDates))
{
snowball.LatestKOObservationDate = settleDate;
if (snowball.LatestKOBarrier != null)
{
snowball.LatestKOBarrier = snowball.KOBarrier;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "LatestKOBarrier", snowball.LatestKOBarrier);
}
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(snowball.KOObservationDates);
var koObservationDates = customizedResults.Item1;
var customizedKOBarriers = customizedResults.Item2;
var latestKOObservationDate = koObservationDates.Where(x => x.DateTime >= settleDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestKOObservationDate != null)
{
snowball.LatestKOObservationDate = latestKOObservationDate.DateTime;
if (customizedKOBarriers == null || !customizedKOBarriers.Any())
{
snowball.LatestKOBarrier = snowball.KOBarrier;
}
else
{
snowball.LatestKOBarrier = customizedKOBarriers[GetDateIndex(koObservationDates, latestKOObservationDate)];
}
if (snowball.LatestKOBarrier != null)
{
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "LatestKOBarrier", snowball.LatestKOBarrier);
}
}
}
if (observationStatus.Contains(snowball.KnockInOutStatusCn))
{
if (snowball.LatestObservationDate == settleDate)
{
var ObservationStatus = snowball.KnockInOutStatusCn;
var konckInOutDate = snowball.KnockInOutDate;
var BarrierLow = t.IsMoneynessOption == "是" ? snowball.KIBarrier * t.SpotPrice : snowball.KIBarrier;
var BarrierHigh = t.IsMoneynessOption == "是" ? snowball.KOBarrier * t.SpotPrice : snowball.KOBarrier;
if (!dicPrice.TryGetValue(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", out var a))
{
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
}
if (!dicPrice.TryGetValue(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", out var b))
{
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", BarrierHigh);
}
}
if (snowball.LatestKOObservationDate == settleDate)
{
var ObservationStatus = snowball.KnockInOutStatusCn;
var konckInOutDate = snowball.KnockInOutDate;
if (ConsGlobal.CallPut.IsCall(t.OptionType)) //向下敲入向上敲出
{
var BarrierHigh = t.IsMoneynessOption == "是" ? snowball.KOBarrier * t.SpotPrice : snowball.KOBarrier;
var BarrierLow = t.IsMoneynessOption == "是" ? snowball.KIBarrier * t.SpotPrice : snowball.KIBarrier;
if (!dicPrice.TryGetValue(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", out var a))
{
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
}
if (!dicPrice.TryGetValue(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", out var b))
{
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", BarrierHigh);
}
}
else //向上敲入向下敲出
{
var BarrierLow = t.IsMoneynessOption == "是" ? snowball.KOBarrier * t.SpotPrice : snowball.KOBarrier;
var BarrierHigh = t.IsMoneynessOption == "是" ? snowball.KIBarrier * t.SpotPrice : snowball.KIBarrier;
if (!dicPrice.TryGetValue(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", out var a))
{
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
}
if (!dicPrice.TryGetValue(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", out var b))
{
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", BarrierHigh);
}
}
}
}
}
break;
case "二元期权":
{
var binary = t.trade_binary_option?.Clone() ?? new trade_binary_option();
if (t.ExerciseModeCn == "欧式")
{
break;
}
if (string.IsNullOrEmpty(binary.ObservationDates))
{
binary.LatestObservationDate = settleDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(binary.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= settleDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
binary.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
binary.LatestObservationDate = null;
}
}
if (binary.LatestObservationDate == settleDate)
{
if (t.Strike != null)
{
var BarrierLow = t.IsMoneynessOption == "是" ? t.Strike * t.SpotPrice : t.Strike;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
}
if (binary.UpperBarrier != null)
{
var BarrierHigh = t.IsMoneynessOption == "是" ? binary.UpperBarrier * t.SpotPrice : binary.UpperBarrier;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", BarrierHigh);
}
}
}
break;
case "气囊结构":
{
var airbag = t.trade_airbag ?? new trade_airbag();
var BarrierLow = t.IsMoneynessOption == "是" ? t.trade_airbag.Barrier * t.SpotPrice : t.trade_airbag.Barrier;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
//没有观察日,只计算敲入敲出
}
break;
case "区间累积期权":
{
var rangeaccrual = t.trade_rangeaccrual?.Clone() ?? new trade_rangeaccrual();
if (string.IsNullOrEmpty(rangeaccrual.ObservationDates))
{
rangeaccrual.LatestObservationDate = settleDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(rangeaccrual.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= settleDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
rangeaccrual.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
rangeaccrual.LatestObservationDate = null;
}
}
if (rangeaccrual.LatestObservationDate == settleDate)
{
if (t.Strike != null)
{
var BarrierLow = t.IsMoneynessOption == "是" ? t.Strike * t.SpotPrice : t.Strike;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
}
}
}
break;
case "累计期权":
{
var accumulator = t.trade_accumulator_option?.Clone() ?? new trade_accumulator_option();
DateTime? LatestObservationDate = settleDate;
if (!string.IsNullOrEmpty(accumulator.KOObservationDates))
{
var observationDates = QdpHelper.ParseObservationDate(accumulator.KOObservationDates);
var latestObservationDate = observationDates.Where(x => x.DateTime >= settleDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
LatestObservationDate = latestObservationDate.DateTime;
}
else
{
LatestObservationDate = null;
}
}
if (accumulator.KnockOutDate.HasValue)
{
var konckInOutDate = accumulator.KnockOutDate;
if (ConsGlobal.CallPut.IsCall(t.OptionType))
{
if (t.Strike != null)
{
var BarrierLow = t.IsMoneynessOption == "是" ? t.Strike * t.SpotPrice : t.Strike;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
}
if (accumulator.KOBarrier != null)
{
var BarrierHigh = t.IsMoneynessOption == "是" ? accumulator.KOBarrier * t.SpotPrice : accumulator.KOBarrier;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", BarrierHigh);
}
}
else
{
if (t.Strike != null)
{
var BarrierLow = t.IsMoneynessOption == "是" ? t.Strike * t.SpotPrice : t.Strike;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierLow", BarrierLow);
}
if (accumulator.KOBarrier != null)
{
var BarrierHigh = t.IsMoneynessOption == "是" ? accumulator.KOBarrier * t.SpotPrice : accumulator.KOBarrier;
dicPrice.Add(t.id + "," + t.UnderlyingCode + "," + "BarrierHigh", BarrierHigh);
}
}
}
}
break;
}
}
return dicPrice;
}
private int GetDateIndex(Date[] source, Date value)
{
var index = 0;
foreach (var item in source)
{
if (item.DateTime == value.DateTime)
{
return index;
}
index++;
}
return -1;
}
}
}