801 lines
46 KiB
C#
801 lines
46 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|