using YLErp.Modules.CalculationModule; namespace YLErp.Modules.EodModule.SettlementModule { /// /// 方顿日终数据接口服务 /// public class FangDunSettlementService : YLBaseService { public FangDunSettlementService(OptUserInfo userInfo) : base(userInfo) { } /// /// 获取方顿日终数据1 /// public List GetEodData1(FangDunEodData1Request req) { var handleTrades = (from tp in DbContext.eod_trade_position.Where(l => l.ValueDate == req.ValueDate && l.TradeId > 0) join tr in DbContext.eod_trade_risk.Where(l => l.ValueDate == req.ValueDate) on tp.TradeId equals tr.TradeId join x in DbContext.trade.Where(t => t.ValidState != "InValid" && (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2) on tp.TradeId equals x.id join tbo in DbContext.trade_barrier_option on tp.TradeId equals tbo.TradeId into tbo from tbo2 in tbo.DefaultIfEmpty() join tao in DbContext.trade_asian_option on tp.TradeId equals tao.TradeId into tao from tao2 in tao.DefaultIfEmpty() join ta in DbContext.trade_autocall on tp.TradeId equals ta.TradeId into ta from ta2 in ta.DefaultIfEmpty() join ts in DbContext.trade_snowball on tp.TradeId equals ts.TradeId into ts from ts2 in ts.DefaultIfEmpty() select new HandleTrade { tradeModel = x, trade_Asian_Option = tao2, TraderId = tp.TradeId, UnderlyingCode = tp.UnderlyingCode, TradeType = tp.TradeType, ordid = x.ParentTradeId == 0 ? x.TradeNumber : DbContext.trade.FirstOrDefault(c => (c.id == x.ParentTradeId && c.TradeType == "结构化交易")).TradeNumber, groupid = "10038801", sub_ordid = x.ParentTradeId == 0 ? "0" : x.TradeNumber.Substring(x.TradeNumber.IndexOf("-") + 1), effective_date_from = x.TradeDate, effective_date_to = x.ExerciseDate, ClientId = x.ClientId, ordname = tp.UnderlyingCode + "-" + (x.OptionType == "看涨" ? "Call" : "Put"), contract_type_cls = x.TradeType, long_short_position_cls = x.BuySell == "买入" ? "L" : "S", put_call_cls = x.OptionType == "看涨" ? "C" : "P", settlement_type_cls = "C", exercise_type_cls = x.ExerciseMode == "European" ? "1" : "2", strike_price = x.Strike, settlement_currency = "CNY", pricing_currency = "CNY", start_date = x.TradeDate, maturity_date = x.ExerciseDate, premium_amt = x.TradePrice, premium_date = x.PremiumPayDate, participation_rate = x.ParticipationRate, levelpercentage = 0, calendar_type_cls = "2", counterparty_name = x.ClientName, businessday_convention_cls = "2", calcrules_cls = "4", single_multi_cls = "1", weight_calc_cls = "1", additionalproduct_type = x.TradeType == "香草期权" ? "普通期权" : "奇异期权", dis_rate = x.DividendRate, underlying_stkcode = tp.UnderlyingCode, caihua_setype0_cls = "5", initial_spot = x.SpotPrice, weight_rate = 1, div_rate = x.DividendRate, vol_rate = tr.Vol, fund_rate = x.DividendRate, barrierType = tbo2.BarrierType, barrier_value = tbo2.BarrierPrice, rebate_rate = tbo2.Rebate, IsMoneynessOption = x.IsMoneynessOption, KOBarrier = ta2.KOBarrier, KIBarrier = ta2.KIBarrier, coupon_rate = ts2.KORebate, observationdate_list = x.ObservationDateStr, obsfreq = "每日",//todo 每日 PayoffType = tao2.PayoffType, notional = tp.Amount * x.SpotPrice, margin = x.MarginRate, float_profit_loss = tp.PositionPnL, accu_profit_loss = tp.ClosedPnL, npv = tp.Pv, delta = tr.Delta, gamma = tr.Gamma, theta = tr.Theta, vega = tr.Vega, rho = tr.Rho * 100, settle_date = x.SettlementDate.ToString(), volume = tp.Amount, cashdelta = tr.DeltaCash, current_value = (x.TradeSinglePrice), market_value = (tp.Amount * x.TradeSinglePrice) ?? 0, pnl = tp.DailyPnL, stress_test_value = (tr.DeltaCash * 21.68 / 100 + tr.Vega * 0.1),// 单退 underlying_stk_qty = tp.Amount, underlying_royalty_price = x.TradeSinglePrice, }).ToList(); var responseTrade = HanderlResponseTradeData(req.ValueDate, handleTrades); return responseTrade; } /// /// 转换成Response /// private List HanderlResponseTradeData(DateTime valueDate, List handleTrades) { var responseTrades = new List(); foreach (var item in handleTrades) { var responseTrade = new ResponseTrade(); responseTrade.ordid = item.ordid; responseTrade.groupid = item.groupid; responseTrade.sub_ordid = item.sub_ordid; responseTrade.sac_ordid = item.sac_ordid; responseTrade.contract_type_cls = GetTradeTypeAbbreviation(item); responseTrade.long_short_position_cls = item.long_short_position_cls; responseTrade.put_call_cls = item.put_call_cls; responseTrade.settlement_type_cls = item.settlement_type_cls; responseTrade.exercise_type_cls = item.exercise_type_cls; responseTrade.strike_price = item.strike_price; responseTrade.settlement_currency = item.settlement_currency; responseTrade.pricing_currency = item.pricing_currency; responseTrade.premium_amt = item.premium_amt; responseTrade.participation_rate = item.participation_rate; responseTrade.levelpercentage = item.levelpercentage; responseTrade.calendar_type_cls = item.calendar_type_cls; responseTrade.counterparty_name = item.counterparty_name; responseTrade.counterparty_sac_ordid = item.counterparty_sac_ordid; responseTrade.businessday_convention_cls = item.businessday_convention_cls; responseTrade.calcrules_cls = item.calcrules_cls; responseTrade.single_multi_cls = item.single_multi_cls; responseTrade.weight_calc_cls = item.weight_calc_cls; responseTrade.additionalproduct_type = item.additionalproduct_type; responseTrade.dis_rate = item.dis_rate; responseTrade.underlying_stkcode = item.underlying_stkcode; responseTrade.underlying_caihua_trade_market = GetUnderlyingCaihuaTradeMarket(item.underlying_caihua_trade_market); responseTrade.caihua_setype0_cls = item.caihua_setype0_cls; responseTrade.initial_spot = item.initial_spot; responseTrade.weight_rate = item.weight_rate; responseTrade.div_rate = item.div_rate; responseTrade.vol_rate = item.vol_rate; responseTrade.fund_rate = item.fund_rate; responseTrade.barrier_type_cls = item.barrier_type_cls; responseTrade.barrier_value = item.barrier_value; responseTrade.rebate_rate = item.rebate_rate; responseTrade.knockout_price = item.knockout_price; responseTrade.knockin_price = item.knockin_price; responseTrade.coupon_rate = item.coupon_rate; responseTrade.observationdate_list = item.observationdate_list; responseTrade.observe_start_date = item.observe_start_date; responseTrade.observe_end_date = item.observe_end_date; responseTrade.obsfreq = item.obsfreq; responseTrade.avg_type_cls = item.avg_type_cls; responseTrade.discrete_type_cls = item.discrete_type_cls; responseTrade.notional = item.notional; responseTrade.margin = item.margin; var nowPrice = item.cashdelta / item.delta; //亚试 responseTrade.accu_underlying_price_asian = AsianOptionCalcHelper.GetAveragePrice(item.tradeModel, item.trade_Asian_Option, nowPrice, valueDate, out var fixingsCount); responseTrade.accu_past_count_asian = fixingsCount; responseTrade.float_profit_loss = item.float_profit_loss; responseTrade.accu_profit_loss = item.accu_profit_loss; responseTrade.npv = item.npv; responseTrade.delta = item.delta; responseTrade.gamma = item.gamma; responseTrade.theta = item.theta; responseTrade.vega = item.vega; responseTrade.rho = item.rho; responseTrade.settle_date = item.settle_date; responseTrade.product_code = item.product_code; responseTrade.volume = item.volume; responseTrade.cashdelta = item.cashdelta; responseTrade.current_value = item.current_value; responseTrade.market_value = item.market_value; responseTrade.pnl = item.pnl; using (var db = DbContextFactory.GetYLDbContext()) { //多退 if (db.trade.Any(t => t.ParentTradeId == item.tradeModel.id)) { var ids = db.trade.Where(t => t.ParentTradeId == item.tradeModel.id).Select(l => l.id).ToArray(); var list = db.eod_trade_risk.Where(t => ids.Contains(t.TradeId)).Select(l => new { l.Vega, l.DeltaCash }); double vega = 0; double deltaCash = 0; list.ForEachAsync(t => { vega += t.Vega; deltaCash += t.DeltaCash; }); responseTrade.stress_test_value = (deltaCash * 21.68 / 100 + vega * 0.1); } else { responseTrade.stress_test_value = item.stress_test_value; } } responseTrade.underlying_stk_qty = item.underlying_stk_qty; responseTrade.underlying_multiplier = item.underlying_multiplier; responseTrade.underlying_royalty_price = item.underlying_royalty_price; responseTrade.effective_date_from = ConvertDateToInt(item.effective_date_from); responseTrade.effective_date_to = ConvertDateToInt(item.effective_date_to); responseTrade.maturity_date = ConvertDateToInt(item.maturity_date); responseTrade.premium_date = ConvertDateToInt(item.premium_date); responseTrade.start_date = ConvertDateToInt(item.start_date); responseTrade.ordname = item.ordname + "-" + Convert.ToDateTime(item.tradeModel.ExerciseDate).ToString("MMdd") + "M-" + item.tradeModel.Strike + "K" + (item.trade_Asian_Option != null ? ("-" + (Convert.ToDateTime(item.trade_Asian_Option?.AveragingPeriodStartDate).ToString("MMdd") ?? Convert.ToDateTime(item.effective_date_from).ToString("MMdd"))) + "OB" : ""); DoubleIsNan(responseTrade); responseTrades.Add(responseTrade); } return responseTrades; } private void DoubleIsNan(ResponseTrade rt) { var t = rt.GetType(); foreach (System.Reflection.PropertyInfo p in rt.GetType().GetProperties()) { if (p.PropertyType.IsValueType && p.PropertyType.FullName.Contains("Double")) { if (p.GetValue(rt) != null) { if (p.GetValue(rt)?.ToString() == "NAN" || !((Double)p.GetValue(rt)).IsNormalize()) { p.SetValue(rt, null); } } } } } public string GetUnderlyingCaihuaTradeMarket(string TradeMarketName) { var strCode = ""; switch (TradeMarketName) { case "上海证券交易所": strCode = "001002"; break; case "深圳证券交易所": strCode = "001003"; break; case "上海期货交易所": strCode = "001008"; break; case "上海国际能源交易所": strCode = "001061"; break; case "上海黄金交易所": strCode = "001015"; break; case "中国金融期货交易所": strCode = "001009"; break; case "郑州商品交易所": strCode = "001017"; break; case "大连商品交易所": strCode = "001016"; break; } return strCode; } /// /// 交易类型 转换简称 /// /// /// public string GetTradeTypeAbbreviation(HandleTrade ht) { var strType = ""; switch (ht.tradeModel.TradeType) { case "香草期权": strType = "VNL"; break; case "障碍期权": //if (t.trade_barrier_option.BarrierType.Contains("双障碍敲")) //{ // //二元障碍期权 // strType = "BIB"; //} //else //{ strType = "BRR"; //} break; case "多触碰点障碍期权": //todo strType = "ACL"; break; case "亚式期权": var type = ht.PayoffType ?? ""; if (type.Contains("Enhanced")) { strType = "ESA";//增强亚式 } else { strType = "ASN";//亚式 } break; case "二元期权": if (ht.tradeModel.ExerciseMode == "European") { strType = "DGT"; } else { //一触即发期权 strType = "TRN"; } break; case "结构化交易": strType = "STG"; break; case "凤凰期权": strType = "PHX"; break; case "雪球期权": strType = "SNB"; break; case "区间累计期权": strType = "RAL"; break; default: strType = "UNK"; break; } return strType; } /// /// 日期转换int /// private static int ConvertDateToInt(DateTime? dt) { if (dt == null) return 0; return dt.Value.Year * 10000 + dt.Value.Month * 100 + dt.Value.Day; } } /// /// 方顿日终数据接口1请求 /// public class FangDunEodData1Request { public DateTime ValueDate { get; set; } } }