804 lines
42 KiB
C#
804 lines
42 KiB
C#
using YLErp.BLL.Calculation;
|
|
using YLErp.Configuration;
|
|
using YLErp.DBModels.Enums;
|
|
using YLErp.DBModels.Helpers;
|
|
using YLErp.Enums;
|
|
using YLErp.Model;
|
|
using YLErp.Modules;
|
|
using YLErp.Modules.CalculationModule;
|
|
using YLErp.Modules.TradeModule;
|
|
using YLErp.QdpModule;
|
|
|
|
namespace YLErp.BLL.MarginCalculation
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public static class MarginDefault
|
|
{
|
|
/// <summary>
|
|
/// 计算日终预付金
|
|
/// </summary>
|
|
public static List<trade_span> RunMarginCalculation(RunMarginCalculationReq req)
|
|
{
|
|
var result = new List<trade_span>();
|
|
var eodTradeids = new YLContext().eod_trade_risk_manual.Where(x => x.ValueDate == req.settleDate && x.Margin != null && string.IsNullOrEmpty(x.VolType)).Select(x => x.TradeId);
|
|
var tempTradeList = req.tradeList.Where(O => eodTradeids.Contains(O.id)).ToList();
|
|
if (tempTradeList.Any() && PS.Config.Company != CompanyEnum.广期资本)
|
|
{
|
|
result = EodtraderiskmanualCalculation(req.Clone(tempTradeList));
|
|
}
|
|
tempTradeList = req.tradeList.Where(O => O.TradeType == "现金流交易" && !eodTradeids.Contains(O.id)).ToList();
|
|
if (tempTradeList.Any())
|
|
{
|
|
result.AddRange(cashflowMarginCalculation(req.Clone(tempTradeList)));
|
|
}
|
|
tempTradeList = req.tradeList.Where(O => O.TradeType != "现金流交易" && O.MarginType != MarginTypeEnum.DEFAULT && !eodTradeids.Contains(O.id)).ToList();
|
|
if (tempTradeList.Any())
|
|
{
|
|
result.AddRange(SingleMarginCalculation(req.Clone(tempTradeList)));
|
|
}
|
|
//if(PS.Config.ErpElement.SecuritiesEnvironment ){
|
|
// tempTradeList = req.tradeList.Where(O => O.TradeType == "收益互换" && !eodTradeids.Contains(O.id)).ToList();
|
|
// if (tempTradeList.Any())
|
|
// {
|
|
// result.AddRange(SwapTradeMarginCalculation(req.Clone(tempTradeList)));
|
|
// }
|
|
//}
|
|
tempTradeList = req.tradeList.Where(O => O.TradeType != "现金流交易" && O.MarginType == MarginTypeEnum.DEFAULT && !eodTradeids.Contains(O.id)).ToList();
|
|
if (PS.Config.Company == CompanyEnum.广期资本)
|
|
{
|
|
tempTradeList = req.tradeList.Where(O => O.TradeType != "现金流交易" && O.MarginType == MarginTypeEnum.DEFAULT).ToList();
|
|
}
|
|
if (tempTradeList.Any())
|
|
{
|
|
switch (PS.Config.Company)
|
|
{
|
|
case CompanyEnum.渤海:
|
|
case CompanyEnum.安粮:
|
|
result.AddRange(BHRSMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.申万:
|
|
result.AddRange(SYWGMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.方顿:
|
|
result.AddRange(FDMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.茂川资本:
|
|
result.AddRange(MaoChuanMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.宏源:
|
|
result.AddRange(HongYuanMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.中财资本:
|
|
result.AddRange(ZhongCaiMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.上期资本:
|
|
result.AddRange(SQMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.伴兴:
|
|
result.AddRange(BXMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.海通:
|
|
result.AddRange(HaiTongMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.瑞达:
|
|
result.AddRange(RDMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.兴证:
|
|
result.AddRange(XingZhengMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.弘业:
|
|
result.AddRange(HongYeMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.广期资本:
|
|
result.AddRange(GQMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.中金:
|
|
result.AddRange(ZhongJinMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.厦门象屿:
|
|
result.AddRange(XMXYMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.国海:
|
|
result.AddRange(GuoHaiMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.润和:
|
|
case CompanyEnum.中基石化:
|
|
result.AddRange(DongZhengRunHeMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.华安:
|
|
result.AddRange(HuaAnMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.浙期:
|
|
result.AddRange(ZheQiMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.国投:
|
|
result.AddRange(GuoTouMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.湘财:
|
|
result.AddRange(XiangCaiMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.中粮:
|
|
result.AddRange(ZhongLiangMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.长江:
|
|
result.AddRange(ChangJiangMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.国信金阳:
|
|
result.AddRange(GuoXinJinYangMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.东吴:
|
|
result.AddRange(DongWuMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.格林大华:
|
|
#if DEBUG
|
|
result.AddRange(GLDHMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
#endif
|
|
case CompanyEnum.国泰君安:
|
|
case CompanyEnum.光大光子:
|
|
case CompanyEnum.兴业商贸:
|
|
result.AddRange(GTJAMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.广发商贸:
|
|
result.AddRange(GFSMMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
case CompanyEnum.招证:
|
|
result.AddRange(ZhaoZhengMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
default:
|
|
result.AddRange(DefaultMarginCalculation.Instance.RunMarginCalculation(req.Clone(tempTradeList)));
|
|
break;
|
|
}
|
|
}
|
|
foreach (var ret in result)
|
|
{
|
|
var trade = tempTradeList.FirstOrDefault(o => o.id == ret.TradeId);
|
|
if (trade != null && trade.TradeType == "现金流交易")
|
|
{
|
|
ret.WorstCastClientPayable = 0;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static List<trade_span> cashflowMarginCalculation(RunMarginCalculationReq runMarginCalculationReq)
|
|
{
|
|
List<trade_span> result = new List<trade_span>();
|
|
runMarginCalculationReq.tradeList.ForEach(O =>
|
|
{
|
|
result.Add(new trade_span()
|
|
{
|
|
TradeId = O.id,
|
|
OptDate = DateTime.Now,
|
|
OptId = runMarginCalculationReq.userId,
|
|
OptName = runMarginCalculationReq.userName,
|
|
ClientId = O.ClientId,
|
|
UnderlyingId = O.UnderlyingId,
|
|
UnderlyingCode = O.UnderlyingCode,
|
|
ValueDate = runMarginCalculationReq.settleDate,
|
|
Spv1 = 0,
|
|
Spv2 = 0,
|
|
Spv3 = 0,
|
|
Spv4 = 0,
|
|
Spv5 = 0,
|
|
Spv6 = 0,
|
|
Spv7 = 0,
|
|
Spv8 = 0,
|
|
Spv = 0,
|
|
WorstCastClientPayable = 0,
|
|
TwoSideMargin = 0
|
|
});
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 收益互换预付金计算
|
|
/// </summary>
|
|
/// <param name="req"></param>
|
|
/// <returns></returns>
|
|
private static List<trade_span> SwapTradeMarginCalculation(RunMarginCalculationReq req)
|
|
{
|
|
var result = new List<trade_span>();
|
|
var clientIds = req.tradeList.Where(t => t.ParentTradeId == 0).Select(t => t.ClientId).Distinct().ToList();
|
|
//增加clientId=0,默认为全部
|
|
clientIds.Add(0);
|
|
//获取客户互换预付金预警设置
|
|
var marginRateList = new YLContext().client_marginrate.Where(t => clientIds.Contains(t.ClientId) && t.ValueDate <= req.settleDate).ToList();
|
|
|
|
//期权详情
|
|
tradeBLL.SetFieldsByTradeType(req.tradeList);
|
|
|
|
foreach (var trade in req.tradeList)
|
|
{
|
|
//剔除多空组合子交易
|
|
if (trade.ParentTradeId > 0) continue;
|
|
client_marginrate clientMarginRateSet = null;
|
|
var extendService = new TradeExtendService(req.UserInfo);
|
|
extendService.SetTradeExtend(new[] { trade });
|
|
//盈亏
|
|
var profitAndLoss = 0.0;
|
|
//计息开始日
|
|
var swapStartDate = (trade.StartDate ?? trade.TradeDate).Value.AddDays(trade.trade_swap.IncludeFirstDay ? 1 : 0);
|
|
//初始预付金比例
|
|
var initMarginRate = (trade.trade_swap.GetMarginRate ?? 0) - (trade.trade_swap.PayMarginRate ?? 0);
|
|
var initMargin = Math.Max(initMarginRate, 0) * trade.StockEqvNotional;
|
|
//利息收入 收取 - 支付
|
|
var interestIncome = PayoffSwapCalcService.GetExtraAmountBySwapRate(trade.ClientId, trade.TradeDate, trade.trade_swap.GetSwapTimeAndRate, swapStartDate, req.settleDate, trade.trade_swap.AnnualDays ?? 0, trade.StockEqvNotional)
|
|
- PayoffSwapCalcService.GetExtraAmountBySwapRate(trade.ClientId, trade.TradeDate, trade.trade_swap.PaySwapTimeAndRate, swapStartDate, req.settleDate, trade.trade_swap.AnnualDays ?? 0, trade.StockEqvNotional);
|
|
profitAndLoss += interestIncome;
|
|
|
|
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(trade.UnderlyingCode);
|
|
var costTradePrice = 0.0;
|
|
//是否开仓是收取手续费
|
|
if (!trade.trade_swap.IsTradePriceWhenOpen)
|
|
{
|
|
costTradePrice += (trade.trade_swap.GetSingleFee ?? 0) * (trade.trade_swap.GetNotional ?? 0) / underlying.ContractSize;
|
|
costTradePrice += (trade.trade_swap.GetUnAnnualRate ?? 0) * trade.StockEqvNotional;
|
|
|
|
costTradePrice -= (trade.trade_swap.PaySingleFee ?? 0) * (trade.trade_swap.PayNotional ?? 0) / underlying.ContractSize;
|
|
costTradePrice -= (trade.trade_swap.PayUnAnnualRate ?? 0) * trade.StockEqvNotional;
|
|
}
|
|
profitAndLoss += costTradePrice;
|
|
|
|
//多空组合
|
|
if (SwapTypeEnum.多空组合.ToString().Equals(trade.trade_swap.SwapType))
|
|
{
|
|
//标的盈亏
|
|
if (trade.get_trade_swap_details != null && trade.get_trade_swap_details.Count > 0)
|
|
{
|
|
trade.get_trade_swap_details.ForEach(a =>
|
|
{
|
|
profitAndLoss += (req.PriceProvider.GetPrice(a.UnderlyingCode) - (a.SpotPrice ?? 0.0)) * (a.Notional ?? 0.0) * ("空头".Equals(a.LongShort) ? -1.0 : 1.0) * (a.IsForGet ? 1 : -1);
|
|
});
|
|
}
|
|
//预警线
|
|
if (marginRateList.Any(a => a.Type.Equals("多空组合") && (a.ClientId == trade.ClientId || a.ClientId == 0)))
|
|
{
|
|
clientMarginRateSet = marginRateList.Where(a => a.Type.Equals("多空组合") && (a.ClientId == trade.ClientId || a.ClientId == 0)).OrderByDescending(a => a.ClientId).ThenByDescending(a => a.ValueDate).FirstOrDefault();
|
|
}
|
|
}
|
|
else
|
|
{//普通 +收取盈亏 -支付盈亏
|
|
profitAndLoss +=
|
|
PayoffSwapCalcService.GetInitialAmountSwapGet(trade, trade.trade_swap, trade.trade_swap.GetSpotPrice ?? 0, req.PriceProvider.GetPrice(trade.trade_swap.GetUnderlyingCode), trade.StockEqvNotional, req.settleDate, null)
|
|
- PayoffSwapCalcService.GetInitialAmountSwapPay(trade, trade.trade_swap, trade.trade_swap.PaySpotPrice ?? 0, req.PriceProvider.GetPrice(trade.trade_swap.PayUnderlyingCode), trade.StockEqvNotional, req.settleDate, null);
|
|
|
|
if (underlying != null && underlying.Variety != null)
|
|
{
|
|
if (marginRateList.Any(a => a.Type.Equals("品种") && (a.ClientId == trade.ClientId || a.ClientId == 0) && a.VarietyId == underlying.Variety.id))
|
|
{
|
|
clientMarginRateSet = marginRateList.Where(a => a.Type.Equals("品种") && (a.ClientId == trade.ClientId || a.ClientId == 0) && a.VarietyId == underlying.Variety.id).OrderByDescending(a => a.ClientId).ThenByDescending(a => a.ValueDate).FirstOrDefault();
|
|
}
|
|
}
|
|
}
|
|
|
|
//维持预付金
|
|
var WorstCastClientPayable = initMargin - profitAndLoss;
|
|
//持仓预付金
|
|
var positionMargin = initMargin;
|
|
|
|
var margin = 0.0;
|
|
//追保计算 未设置预警线 则取初始预付金比例
|
|
if (WorstCastClientPayable <= (clientMarginRateSet == null ? initMarginRate : clientMarginRateSet.WarningLine) * trade.StockEqvNotional)
|
|
{
|
|
margin = initMargin - WorstCastClientPayable;
|
|
//追保暂时只算单方向
|
|
positionMargin = initMargin + Math.Max(margin, 0);
|
|
}
|
|
|
|
result.Add(new trade_span()
|
|
{
|
|
TradeId = trade.id,
|
|
OptDate = DateTime.Now,
|
|
OptId = req.userId,
|
|
OptName = req.userName,
|
|
ClientId = trade.ClientId,
|
|
UnderlyingId = trade.UnderlyingId,
|
|
UnderlyingCode = trade.UnderlyingCode,
|
|
ValueDate = req.settleDate,
|
|
Spv1 = positionMargin,
|
|
Spv2 = positionMargin,
|
|
Spv3 = positionMargin,
|
|
Spv4 = positionMargin,
|
|
Spv5 = positionMargin,
|
|
Spv6 = positionMargin,
|
|
Spv7 = positionMargin,
|
|
Spv8 = positionMargin,
|
|
Spv = positionMargin,
|
|
WorstCastClientPayable = positionMargin,
|
|
Margin = margin
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static List<trade_span> SingleMarginCalculation(RunMarginCalculationReq req)
|
|
{
|
|
var result = new List<trade_span>();
|
|
double value = 0;
|
|
foreach (var trade in req.tradeList)
|
|
{
|
|
bool isSingleMargin = false;
|
|
switch (trade.MarginType)
|
|
{
|
|
case MarginTypeEnum.FIXED:
|
|
if (req.CalcMarginType == CalcMarginTypeEnum.InitialMargin)
|
|
{
|
|
value = (trade.StockEqvNotional == 0 ? TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor) : trade.StockEqvNotional) * trade.MarginRate;
|
|
}
|
|
else
|
|
{
|
|
if (PS.Config.ErpElement.EodFixedMarginUseSpotPrice)
|
|
{
|
|
value = (trade.StockEqvNotional == 0 ? TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor) : trade.StockEqvNotional) * trade.PositionMarginRate;
|
|
}
|
|
else
|
|
{
|
|
value = (trade.StockEqvNotional == 0 || (trade.SpotPrice ?? 0) == 0 ? TradeHelper.GetStockEqvNotional(trade.Notional * req.PriceProvider.GetPrice(trade.UnderlyingCode), trade.ParticipationRate, trade.AnnualizeFactor) : trade.StockEqvNotional * req.PriceProvider.GetPrice(trade.UnderlyingCode) / (trade.SpotPrice ?? 0)) * trade.PositionMarginRate;
|
|
}
|
|
}
|
|
break;
|
|
case MarginTypeEnum.FLOAT:
|
|
value = (trade.StockEqvNotional == 0 ? TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor) : trade.StockEqvNotional) * trade.MarginRate;
|
|
if (req.CalcMarginType != CalcMarginTypeEnum.InitialMargin)
|
|
{
|
|
if (trade.TradeType == "远期")
|
|
{
|
|
var eodpriceProvider = new YLErp.Modules.DataProviderModule.EodPriceProvider(req.settleDate);
|
|
var spotPrice = eodpriceProvider.GetPrice(trade.UnderlyingCode, SettlementTypeEnum.ClosePrice);//收盘价
|
|
TradeValueResult curValue = ForwardradeCalcService.CalcValue(trade, spotPrice);
|
|
var tradePrice = (trade.TradePrice * trade.Notional / trade.OriginalNotional) ?? 0;
|
|
double pnl = 0;
|
|
pnl = curValue.Pv + tradePrice * (trade.BuySell == "买入" ? -1 : 1);
|
|
value += pnl;
|
|
if (value < 0)
|
|
{ value = 0; }
|
|
|
|
}
|
|
else
|
|
{
|
|
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(
|
|
valueDate: req.settleDate,
|
|
tradeList: new[] { trade },
|
|
calcScenario: req.GetCalcScenario(),
|
|
priceProvider: req.PriceProvider,
|
|
pricingRequest: QdpPricingRequest.PV_ONLY,
|
|
addVolRateDic: null,
|
|
volType: req.volType, isUseTradeVol: PS.Config.IsTradeVol,
|
|
preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin);
|
|
if (!string.IsNullOrWhiteSpace(tradeRiskResult.ErrorMessage))
|
|
{
|
|
LogFactory.GetLogger<MarginCalculationBase>().Error("Pv计算失败:" + tradeRiskResult.ErrorMessage);
|
|
}
|
|
var tradePrice = (trade.TradePrice * trade.Notional / trade.OriginalNotional) ?? 0;
|
|
double pnl = 0;
|
|
if (trade.BuySell == "买入")
|
|
{
|
|
pnl = tradePrice - Math.Abs(tradeRiskResult.Results.First().ValueResult.Pv);
|
|
}
|
|
else
|
|
{
|
|
pnl = Math.Abs(tradeRiskResult.Results.First().ValueResult.Pv) - tradePrice;
|
|
}
|
|
value += pnl;
|
|
if (value < 0)
|
|
{ value = 0; }
|
|
}
|
|
}
|
|
|
|
break;
|
|
case MarginTypeEnum.FLOATP:
|
|
if (req.CalcMarginType == CalcMarginTypeEnum.InitialMargin)
|
|
{
|
|
value = (trade.StockEqvNotional == 0 ? TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor) : trade.StockEqvNotional) * trade.MarginRate;
|
|
}
|
|
else if (req.CalcMarginType != CalcMarginTypeEnum.InitialMargin)
|
|
{
|
|
value = (trade.StockEqvNotional == 0 ? TradeHelper.GetStockEqvNotional(trade.Notional * req.PriceProvider.GetPrice(trade.UnderlyingCode), trade.ParticipationRate, trade.AnnualizeFactor) : trade.StockEqvNotional) * trade.PositionMarginRate;
|
|
var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(
|
|
valueDate: req.settleDate,
|
|
tradeList: new[] { trade },
|
|
calcScenario: req.GetCalcScenario(),
|
|
priceProvider: req.PriceProvider,
|
|
pricingRequest: QdpPricingRequest.PV_ONLY,
|
|
addVolRateDic: null,
|
|
volType: req.volType, isUseTradeVol: PS.Config.IsTradeVol,
|
|
preciseTimeMode: req.CalcMarginType != CalcMarginTypeEnum.EodMargin);
|
|
if (!string.IsNullOrWhiteSpace(tradeRiskResult.ErrorMessage))
|
|
{
|
|
LogFactory.GetLogger<MarginCalculationBase>().Error("Pv计算失败:" + tradeRiskResult.ErrorMessage);
|
|
}
|
|
var tradePrice = (trade.TradePrice * trade.Notional / trade.OriginalNotional) ?? 0;
|
|
double pnl = 0;
|
|
if (trade.BuySell == "买入")
|
|
{
|
|
pnl = tradePrice - Math.Abs(tradeRiskResult.Results.First().ValueResult.Pv);
|
|
}
|
|
else
|
|
{
|
|
pnl = Math.Abs(tradeRiskResult.Results.First().ValueResult.Pv) - tradePrice;
|
|
}
|
|
value += pnl;
|
|
if (value < 0)
|
|
{ value = 0; }
|
|
}
|
|
break;
|
|
case MarginTypeEnum.XingYe:
|
|
value = XingYeMarginCalculation.TradeMargin(req, trade);
|
|
break;
|
|
case MarginTypeEnum.GuoTouLock:
|
|
if (trade.TradeType == "雪球期权" || trade.TradeType == "收益互换")
|
|
{
|
|
var initialMargin = (trade.InitialMargin ?? 0) * trade.StockEqvNotional / trade.OriginalStockEqvNotional.Value;
|
|
double[] lockvals = { initialMargin,
|
|
PS.Config.Company == CompanyEnum.湘财
|
|
? XiangCaiMarginCalculation.TradeMargin(req, trade)
|
|
: GuoTouMarginCalculation.TradeMargin(req, trade)
|
|
};
|
|
if (PS.Config.Company == CompanyEnum.湘财 && initialMargin < 0)
|
|
{// #OTC-5636 见备注
|
|
value = lockvals.Min();
|
|
}
|
|
else
|
|
{
|
|
value = lockvals.Max();
|
|
}
|
|
isSingleMargin = true;
|
|
}
|
|
break;
|
|
case MarginTypeEnum.GuoTouNoLock:
|
|
if (trade.TradeType == "雪球期权" || trade.TradeType == "收益互换")
|
|
{
|
|
double[] noLockvals = { 0,
|
|
PS.Config.Company == CompanyEnum.湘财
|
|
? XiangCaiMarginCalculation.TradeMargin(req, trade)
|
|
: GuoTouMarginCalculation.TradeMargin(req, trade)
|
|
};
|
|
value = noLockvals.Max();
|
|
isSingleMargin = true;
|
|
}
|
|
break;
|
|
default:
|
|
case MarginTypeEnum.NONE:
|
|
value = 0;
|
|
break;
|
|
}
|
|
|
|
result.Add(new trade_span()
|
|
{
|
|
TradeId = trade.id,
|
|
OptDate = DateTime.Now,
|
|
OptId = req.userId,
|
|
OptName = req.userName,
|
|
ClientId = trade.ClientId,
|
|
UnderlyingId = trade.UnderlyingId,
|
|
UnderlyingCode = trade.UnderlyingCode,
|
|
ValueDate = req.settleDate,
|
|
Spv1 = value,
|
|
Spv2 = value,
|
|
Spv3 = value,
|
|
Spv4 = value,
|
|
Spv5 = value,
|
|
Spv6 = value,
|
|
Spv7 = value,
|
|
Spv8 = value,
|
|
Spv = value,
|
|
WorstCastClientPayable = value,
|
|
TwoSideMargin = value,
|
|
IsSingleMargin = isSingleMargin
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static List<trade_span> EodtraderiskmanualCalculation(RunMarginCalculationReq req)
|
|
{
|
|
var result = new List<trade_span>();
|
|
List<int> reqids = req.tradeList.Select(x => x.id).ToList();
|
|
var eodTradeRiskManual = new YLContext().eod_trade_risk_manual.Where(x => reqids.Contains(x.TradeId) && x.ValueDate == req.settleDate && x.Margin != null && string.IsNullOrEmpty(x.VolType));
|
|
if (eodTradeRiskManual.Any())
|
|
{
|
|
var tradeRiskManuals = (from trade in req.tradeList
|
|
join riskManuals in eodTradeRiskManual on trade.id equals riskManuals.TradeId
|
|
select new { trade, riskManuals }).ToList();
|
|
foreach (var item in tradeRiskManuals)
|
|
{
|
|
double value = item.riskManuals.Margin ?? 0;
|
|
result.Add(new trade_span()
|
|
{
|
|
TradeId = item.trade.id,
|
|
OptDate = DateTime.Now,
|
|
OptId = req.userId,
|
|
OptName = req.userName,
|
|
ClientId = item.trade.ClientId,
|
|
UnderlyingId = item.trade.UnderlyingId,
|
|
UnderlyingCode = item.trade.UnderlyingCode,
|
|
ValueDate = req.settleDate,
|
|
Spv1 = value,
|
|
Spv2 = value,
|
|
Spv3 = value,
|
|
Spv4 = value,
|
|
Spv5 = value,
|
|
Spv6 = value,
|
|
Spv7 = value,
|
|
Spv8 = value,
|
|
Spv = value,
|
|
WorstCastClientPayable = value,
|
|
TwoSideMargin = value,
|
|
IsSingleMargin = true
|
|
});
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static List<trade_span> CalcClientMargin(CalcClientMarginReq req)
|
|
{
|
|
switch (PS.Config.Company)
|
|
{
|
|
case CompanyEnum.渤海:
|
|
return BHRSMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.安粮:
|
|
return BHRSMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.申万:
|
|
return SYWGMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.伴兴:
|
|
return BXMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.海通:
|
|
return HaiTongMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.瑞达:
|
|
return RDMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.兴证:
|
|
return XingZhengMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.宏源:
|
|
return HongYuanMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.中财资本:
|
|
return ZhongCaiMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.上期资本:
|
|
return SQMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.弘业:
|
|
return HongYeMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.广期资本:
|
|
return GQMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.方顿:
|
|
return FDMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.中金:
|
|
return ZhongJinMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.国海:
|
|
return GuoHaiMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.厦门象屿:
|
|
return XMXYMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.华安:
|
|
return HuaAnMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.浙期:
|
|
return ZheQiMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.润和:
|
|
case CompanyEnum.中基石化:
|
|
return DongZhengRunHeMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.国投:
|
|
return GuoTouMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.湘财:
|
|
return XiangCaiMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.中粮:
|
|
return ZhongLiangMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.长江:
|
|
return ChangJiangMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.国信金阳:
|
|
return GuoXinJinYangMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.东吴:
|
|
return DongWuMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.格林大华:
|
|
#if DEBUG
|
|
return GLDHMarginCalculation.Instance.CalcClientMargin(req);
|
|
#endif
|
|
case CompanyEnum.国泰君安:
|
|
case CompanyEnum.光大光子:
|
|
return GTJAMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.广发商贸:
|
|
return GFSMMarginCalculation.Instance.CalcClientMargin(req);
|
|
case CompanyEnum.招证:
|
|
return ZhaoZhengMarginCalculation.Instance.CalcClientMargin(req);
|
|
default:
|
|
return DefaultMarginCalculation.Instance.CalcClientMargin(req);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 这个方法不明白什么意思
|
|
/// 按照历史代码,国君应该一直返回的是false,但事实是根据收盘数据看2021年9月24日及以前返回的是true
|
|
/// </summary>
|
|
public static bool IsMarginCalcNeedSpecial(DateTime valueDate)
|
|
{
|
|
//国君商品类预付金需要算反向预付金,权益类不需要
|
|
if (PS.Config.IsGuoJun && (!PS.Config.ErpElement.IsStockMargin || PS.Config.ClientElement.TwoSideMargin) && valuedateBLL.TwoSideMarginValueDate.HasValue && valueDate >= valuedateBLL.TwoSideMarginValueDate)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
switch (PS.Config.Company)
|
|
{
|
|
case CompanyEnum.渤海:
|
|
case CompanyEnum.安粮:
|
|
case CompanyEnum.润和:
|
|
case CompanyEnum.中基石化:
|
|
return true;
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
public static double? GetInitialMarginRatio(trade trade)
|
|
{
|
|
switch (PS.Config.Company)
|
|
{
|
|
case CompanyEnum.方顿:
|
|
return FDMarginCalculation.Instance.GetInitialMarginRatio(trade);
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public static double? GetPositionMarginRatio(trade trade)
|
|
{
|
|
switch (PS.Config.Company)
|
|
{
|
|
case CompanyEnum.方顿:
|
|
return FDMarginCalculation.Instance.GetPositionMarginRatio(trade);
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public static double GetInitialMarginWithPreHandle(trade trade)
|
|
{
|
|
var tradeClone = trade.Clone();
|
|
tradeBLL.SetFieldsByTradeType(tradeClone);
|
|
var realTradeId = tradeClone.id;
|
|
tradeClone.id = 0;
|
|
tradeClone.VolType = "报价Bid";
|
|
tradeClone.TradeCloseVolatility = null;//不设置为null会影响计算结果
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(tradeClone.UnderlyingCode);
|
|
tradeClone.StockEqvNotional = tradeClone.OriginalStockEqvNotional ?? 0;
|
|
tradeClone.Notional = tradeClone.OriginalNotional ?? 0;
|
|
tradeClone.TradeAmount = underlying != null && underlying.CountRatio != 0 ? tradeClone.Notional / underlying.CountRatio : tradeClone.Notional;
|
|
if (!tradeClone.TTMDays.HasValue)
|
|
{
|
|
tradeClone.TTMDays = TradeCalcHelper.CalculateTTMDays(tradeClone.TradeDate.Value, tradeClone.ExerciseDate.Value,
|
|
underlying?.UnderlyingTypeId ?? 0, PS.Config.ErpElement.PrecisionOfMinuteInQuote);
|
|
}
|
|
return GetInitialMargin(tradeClone, realTradeId, true);
|
|
}
|
|
|
|
public static double GetInitialMargin(trade trade, int realTradeId, bool hasOptionInfo = false)
|
|
{
|
|
if (trade is null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(trade.UnderlyingCode);
|
|
trade.MaturityDate = um?.MaturityDate;
|
|
|
|
///关于交易id的多义性: 1.组合交易需要真实的交易id;2.考虑到波动率不能获取持仓波动率,将id赋值为0;3.定价页面结构化交易子交易id会赋值-1和-2
|
|
var req = new GetTradeMarginReq
|
|
{
|
|
realTradeId = realTradeId,
|
|
trade = trade,
|
|
price = trade.SpotPrice ?? 0,
|
|
hasOptionInfo = hasOptionInfo,
|
|
calcMarginType = CalcMarginTypeEnum.InitialMargin
|
|
};
|
|
return GetTradeMargin(req);
|
|
}
|
|
|
|
/// <summary>
|
|
/// isInitialMargin为true: 为初始预付金
|
|
/// isInitialMargin为false: 为实时预付金
|
|
/// </summary>
|
|
public static double GetTradeMargin(GetTradeMarginReq req)
|
|
{
|
|
if (req.trade.TradeType == "结构化交易")
|
|
{
|
|
var option = StructureOption_Code.StructureOptions.FirstOrDefault(o => o.Name == req.trade.StructureType || o.CnName == req.trade.StructureType);
|
|
//自由组合时不在变更StructureType字段值,保持原有结构化交易的内容;
|
|
if (option != null)
|
|
{
|
|
req.trade.StructureType = option.CnName;
|
|
}
|
|
}
|
|
double? tempInitialMargin = null;
|
|
if (req.calcMarginType != CalcMarginTypeEnum.InitialMargin && req.trade.CalcFlag == 1)
|
|
{
|
|
tempInitialMargin = req.trade.InitialMargin;
|
|
req.trade.InitialMargin = null;
|
|
}
|
|
try
|
|
{
|
|
if (req.trade.TradeType == "现金流交易")
|
|
{
|
|
return 0;
|
|
}
|
|
else if (req.trade.MarginType != MarginTypeEnum.DEFAULT)
|
|
{
|
|
var result = SingleMarginCalculation(req.GetRunMarginCalculationReq());
|
|
return (result.FirstOrDefault()?.WorstCastClientPayable) ?? 0;
|
|
}
|
|
else
|
|
{
|
|
switch (PS.Config.Company)
|
|
{
|
|
case CompanyEnum.渤海:
|
|
return BHRSMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.安粮:
|
|
return BHRSMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.申万:
|
|
return SYWGMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.茂川资本:
|
|
return MaoChuanMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.宏源:
|
|
return HongYuanMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.伴兴:
|
|
return BXMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.海通:
|
|
return HaiTongMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.瑞达:
|
|
return RDMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.兴证:
|
|
return XingZhengMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.弘业:
|
|
return HongYeMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.广期资本:
|
|
return GQMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.方顿:
|
|
return FDMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.国海:
|
|
return GuoHaiMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.华安:
|
|
return HuaAnMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.浙期:
|
|
return ZheQiMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.润和:
|
|
return DongZhengRunHeMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.国投:
|
|
return GuoTouMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.湘财:
|
|
return XiangCaiMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.中粮:
|
|
return ZhongLiangMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.长江:
|
|
return ChangJiangMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.国信金阳:
|
|
return GuoXinJinYangMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.东吴:
|
|
return DongWuMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.格林大华:
|
|
#if DEBUG
|
|
return GLDHMarginCalculation.Instance.GetTradeMargin(req);
|
|
#endif
|
|
case CompanyEnum.广发商贸:
|
|
return GFSMMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.国泰君安:
|
|
case CompanyEnum.上期资本:
|
|
case CompanyEnum.光大光子:
|
|
return GTJAMarginCalculation.Instance.GetTradeMargin(req);
|
|
case CompanyEnum.招证:
|
|
return ZhaoZhengMarginCalculation.Instance.GetTradeMargin(req);
|
|
default:
|
|
return DefaultMarginCalculation.Instance.GetTradeMargin(req);
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (req.calcMarginType == CalcMarginTypeEnum.InitialMargin && req.trade.CalcFlag == 1 && req.trade.InitialMargin == null)
|
|
{
|
|
req.trade.InitialMargin = tempInitialMargin;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|