227 lines
11 KiB
C#
227 lines
11 KiB
C#
using Qdp.Pricing.Base.Implementations;
|
||
using System.Data;
|
||
using YLErp.BLL.Calculation;
|
||
using YLErp.Commons;
|
||
using YLErp.Model.Enum;
|
||
using YLErp.Models;
|
||
using YLErp.Modules;
|
||
using YLErp.Modules.CalculationModule;
|
||
using YLErp.Modules.DataProviderModule;
|
||
using YLErp.Modules.MarginModule;
|
||
|
||
|
||
namespace YLErp.BLL.MarginCalculation
|
||
{
|
||
public class XingYeMarginCalculation : MarginCalculationBase
|
||
{
|
||
// 定义一个静态变量来保存类的实例
|
||
public static readonly XingYeMarginCalculation Instance;
|
||
|
||
static XingYeMarginCalculation()
|
||
{
|
||
Instance = new XingYeMarginCalculation();
|
||
}
|
||
|
||
// 定义私有构造函数,使外界不能创建该类实例
|
||
protected XingYeMarginCalculation()
|
||
{
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 完整预付金公式:
|
||
/// </summary>
|
||
/// <param name="req"></param>
|
||
/// <param name="td"></param>
|
||
/// <param name="dt"></param>
|
||
/// <param name="tradeRiskResult"></param>
|
||
/// <returns></returns>
|
||
public static double TradeMargin(RunMarginCalculationReq req, trade td)
|
||
{
|
||
var sourcePath = OtcAppContext.MapPath("~/App_Docs");
|
||
var sourceFileName = Path.Combine(sourcePath, "Delta调整系数表.xlsx");
|
||
DataTable dt = new ExcelHelper().ExcelToDataTable(sourceFileName, "", true);
|
||
UnderlyingDataProvider _underlyingDataProvider = new UnderlyingDataProvider();
|
||
var reqConv = new CalculateRisksForTradesReq
|
||
{
|
||
valueDate = req.settleDate,
|
||
tradeList = new List<trade> { td },
|
||
priceProvider = req.PriceProvider,
|
||
pricingRequest = PricingRequest.Pv | PricingRequest.Delta | PricingRequest.Gamma,
|
||
addVolRateDic = null,
|
||
volType = req.volType,
|
||
isUseTradeVol = PS.Config.IsTradeVol,
|
||
PreciseTimeMode = req.CalcMarginType != Enums.CalcMarginTypeEnum.EodMargin,
|
||
isAddVolPercent = true,
|
||
overrideVolsForTrade = null,
|
||
isMarginCalc = true
|
||
};
|
||
|
||
if (req.CalcMarginType == Enums.CalcMarginTypeEnum.EodMargin)
|
||
{
|
||
reqConv.calcScenario = Enums.CalcScenarioEnum.EodSettlement;
|
||
}
|
||
|
||
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(reqConv);
|
||
|
||
double ITM = 0;
|
||
double Margin_part = 0;
|
||
double Margin_part1 = 0;
|
||
double Margin_part2 = 0;
|
||
double maxMarginRate = 0;
|
||
new EodPriceProvider(req.settleDate, false).TryGetEodPrice(td.UnderlyingCode, out var eodPrice);
|
||
double Delta = -1;
|
||
double coefficient = 0;
|
||
var udm = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
|
||
var udmA = new underlying_manager();
|
||
var udmB = new underlying_manager();
|
||
var helper = new RunMarginCalculationHelper(req, _underlyingDataProvider);
|
||
var mpProvider = helper.GetMarginParamProvider(MarginParamTypeEnum.MarginRate | MarginParamTypeEnum.UpDownLimit);
|
||
mpProvider.TryGetMarginRate(td.UnderlyingCode, out var marginRate);
|
||
|
||
if (eodPrice == null)
|
||
{
|
||
eodPrice = new EodPrice();
|
||
eodPrice.SettlePrice = td.SpotPrice ?? 0;
|
||
}
|
||
|
||
if (td.TradeType == "收益互换")
|
||
{
|
||
Delta = 1;
|
||
ITM = 0;
|
||
}
|
||
else
|
||
{
|
||
if (td.OptionType == "看涨")
|
||
{
|
||
ITM = (eodPrice.SettlePrice - (td.IsMoneynessOption == "是" ? (td.Strike.Value * td.SpotPrice.Value) : td.Strike.Value));
|
||
ITM = ITM > 0 ? ITM : 0;
|
||
}
|
||
else
|
||
{
|
||
ITM = ((td.IsMoneynessOption == "是" ? (td.Strike.Value * td.SpotPrice.Value) : td.Strike.Value) - eodPrice.SettlePrice);
|
||
ITM = ITM > 0 ? ITM : 0;
|
||
}
|
||
Delta = Math.Round((tradeRiskResult.Results.Where(x => x.Trade.id == td.id).FirstOrDefault().ValueResult.Delta / td.Notional), 2);
|
||
}
|
||
|
||
if (td.TradeType == "收益互换" || (td.ExerciseMode == "European" && string.IsNullOrEmpty(td.StructureType)))
|
||
{
|
||
//预付金_part1 = ((ABS(Delta) * VLOOKUP(ABS(ROUND(Delta,2)), Delta调整系数表, 2, FALSE)
|
||
//* 标的结算价 * ABS(标的规模) * 交易所预付金率) + 实值部分 * ABS(标的规模) )
|
||
DataRow[] drs2 = dt.Select("Delta='" + Math.Abs(Delta) + "'", "Delta desc");//维持系数
|
||
if (drs2.Count() > 0)
|
||
coefficient = Convert.ToDouble(drs2[0]["维持系数"]);
|
||
Margin_part1 = (Math.Abs(Delta) * coefficient
|
||
* SettlePrice(req.settleDate, td) * Math.Abs(td.TradeAmount) * marginRate);
|
||
}
|
||
else if (udm.CommodityCode == "组合标的" && td.TradeType == "收益互换")
|
||
{
|
||
//1*I2101-1*I2009
|
||
var UnderlyingCode = td.trade_swap.GetUnderlyingCode == null ? td.trade_swap.PayUnderlyingCode : td.trade_swap.GetUnderlyingCode;
|
||
var UnderlyingCodeS = UnderlyingCode.Split(new char[] { '-', '+' }).ToList(); //多字节切割
|
||
//new EodPriceProvider(req.settleDate, false).TryGetEodPrice(UnderlyingCodeS[0].Split('*')[1], out eodPriceA);
|
||
//new EodPriceProvider(req.settleDate, false).TryGetEodPrice(UnderlyingCodeS[1].Split('*')[1], out eodPriceB);
|
||
//udmA = DataCacheProvider.GetUnderlyingDataSource().GetData(UnderlyingCodeS[0].Split('*')[1]);
|
||
//udmB = DataCacheProvider.GetUnderlyingDataSource().GetData(UnderlyingCodeS[1].Split('*')[1]);
|
||
|
||
foreach (var code in UnderlyingCodeS)
|
||
{
|
||
if (code.Contains("*"))
|
||
{
|
||
udm = DataCacheProvider.GetUnderlyingDataSource().GetData(code.Split('*')[1]);
|
||
if (udm.MarginRate != null)
|
||
{
|
||
maxMarginRate = maxMarginRate > udm.MarginRate.Value ? maxMarginRate : udm.MarginRate.Value;
|
||
}
|
||
}
|
||
}
|
||
//预付金_part1 = (标的A收盘价 - 标的B收盘价) * ABS(标的规模) * 交易所预付金率 * 0.9
|
||
Margin_part1 = (eodPrice.ClosePrice) * Math.Abs(td.TradeAmount) * maxMarginRate * 0.9;
|
||
}
|
||
else if (udm.CommodityCode == "组合标的" && td.ExerciseMode == "European")
|
||
{
|
||
var UnderlyingCode = td.trade_swap.GetUnderlyingCode == null ? td.trade_swap.PayUnderlyingCode : td.trade_swap.GetUnderlyingCode;
|
||
var UnderlyingCodeS = UnderlyingCode.Split(new char[] { '-', '+' }).ToList(); //多字节切割
|
||
//new EodPriceProvider(req.settleDate, false).TryGetEodPrice(UnderlyingCodeS[0].Split('*')[1], out eodPriceA);
|
||
//new EodPriceProvider(req.settleDate, false).TryGetEodPrice(UnderlyingCodeS[1].Split('*')[1], out eodPriceB);
|
||
//udmA = DataCacheProvider.GetUnderlyingDataSource().GetData(UnderlyingCodeS[0].Split('*')[1]);
|
||
//udmB = DataCacheProvider.GetUnderlyingDataSource().GetData(UnderlyingCodeS[1].Split('*')[1]);
|
||
|
||
foreach (var code in UnderlyingCodeS)
|
||
{
|
||
if (code.Contains("*"))
|
||
{
|
||
udm = DataCacheProvider.GetUnderlyingDataSource().GetData(code.Split('*')[1]);
|
||
if (udm.MarginRate != null)
|
||
{
|
||
maxMarginRate = maxMarginRate > udm.MarginRate.Value ? maxMarginRate : udm.MarginRate.Value;
|
||
}
|
||
}
|
||
}
|
||
//预付金_part1 = (标的A收盘价 + 标的B收盘价)/2 * ABS(标的规模) * 交易所预付金率
|
||
Margin_part1 = ((eodPrice.ClosePrice) / 2) * Math.Abs(td.TradeAmount) * maxMarginRate;
|
||
}
|
||
//预付金_part2 = 期权实值部门 * ABS(标的规模)
|
||
|
||
Margin_part2 = ITM * Math.Abs(td.TradeAmount);
|
||
|
||
Margin_part = Margin_part2 + Margin_part1;
|
||
return Margin_part;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 标的结算价的公式为:
|
||
/// If 期权类别 = “亚式”:
|
||
/// If 当前估值日期 <= 亚式采价起始日:
|
||
/// 标的结算价 = 当日收盘价
|
||
/// Else:
|
||
/// 标的结算价 = (标的前结算价*(已采价期-1) + 当日收盘价* (剩余天数+1))/(已采价期+剩余天数)
|
||
/// Elseif 期权类别 = “价差欧式” OR 期权类别 = “价差互换” OR "欧式":
|
||
/// 标的结算价 = 当日结算价
|
||
/// </summary>
|
||
/// <param name="req"></param>
|
||
/// <param name="td"></param>
|
||
/// <returns></returns>
|
||
private static double SettlePrice(DateTime settleDate, trade td)
|
||
{
|
||
EodPrice eodPrice = null;
|
||
double settlePrice = 0;
|
||
new EodPriceProvider(settleDate, false).TryGetEodPrice(td.UnderlyingCode, out eodPrice);
|
||
if (eodPrice == null)
|
||
{
|
||
eodPrice = new EodPrice();
|
||
eodPrice.SettlePrice = td.SpotPrice ?? 0;
|
||
}
|
||
var udm = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
|
||
if (td.TradeType == "亚式期权")
|
||
{
|
||
if (settleDate <= td.trade_asian_option.AveragingPeriodStartDate)
|
||
{
|
||
return eodPrice.ClosePrice;
|
||
}
|
||
else
|
||
{
|
||
TimeSpan sp = Convert.ToDateTime(settleDate).Subtract(td.trade_asian_option.AveragingPeriodStartDate.Value);
|
||
TimeSpan sp1 = Convert.ToDateTime(td.ExerciseDate.Value).Subtract(settleDate);
|
||
return (eodPrice.SettlePrice * (sp.Days - 1) + eodPrice.ClosePrice * (sp1.Days + 1)) / (sp.Days + sp1.Days);
|
||
}
|
||
}
|
||
else if (udm.CommodityCode == "组合标的" && td.ExerciseMode == "European")
|
||
{
|
||
return eodPrice.SettlePrice;
|
||
}
|
||
else if (udm.CommodityCode == "组合标的" && td.TradeType == "收益互换")
|
||
{
|
||
return eodPrice.SettlePrice;
|
||
}
|
||
else if (td.ExerciseMode == "European")
|
||
{
|
||
return eodPrice.SettlePrice;
|
||
}
|
||
else
|
||
return settlePrice;
|
||
}
|
||
}
|
||
}
|