Files
zszq-trs/YLErpDAL/Modules/EodModule/SettlementModule/FangDunSettlementService.cs
T
2024-05-09 14:06:26 +08:00

363 lines
18 KiB
C#

using YLErp.Modules.CalculationModule;
namespace YLErp.Modules.EodModule.SettlementModule
{
/// <summary>
/// 方顿日终数据接口服务
/// </summary>
public class FangDunSettlementService : YLBaseService
{
public FangDunSettlementService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// 获取方顿日终数据1
/// </summary>
public List<ResponseTrade> 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;
}
/// <summary>
/// 转换成Response
/// </summary>
private List<ResponseTrade> HanderlResponseTradeData(DateTime valueDate, List<HandleTrade> handleTrades)
{
var responseTrades = new List<ResponseTrade>();
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;
}
/// <summary>
/// 交易类型 转换简称
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 日期转换int
/// </summary>
private static int ConvertDateToInt(DateTime? dt)
{
if (dt == null) return 0;
return dt.Value.Year * 10000 + dt.Value.Month * 100 + dt.Value.Day;
}
}
/// <summary>
/// 方顿日终数据接口1请求
/// </summary>
public class FangDunEodData1Request
{
public DateTime ValueDate { get; set; }
}
}