416 lines
25 KiB
C#
416 lines
25 KiB
C#
//using System;
|
||
//using System.Collections.Generic;
|
||
//using System.Linq;
|
||
//using YLErp.BLL.Calculation.V2;
|
||
//using YLErp.BLL.Eod;
|
||
//using YLErp.DBModels;
|
||
//using YLErp.DBModels.Consts;
|
||
//using YLErp.Model;
|
||
//using CalculatorHelper = YLErp.BLL.Calculation.CalculatorHelperOld;
|
||
|
||
//namespace YLErp.BLL.MarginCalculationBak
|
||
//{
|
||
// /// <summary>
|
||
// /// 渤海荣盛
|
||
// /// </summary>
|
||
// public class BHRSMarginCalculation : MarginCalculationBase
|
||
// {
|
||
// // 定义一个静态变量来保存类的实例
|
||
// public static readonly BHRSMarginCalculation Instance;
|
||
|
||
// static BHRSMarginCalculation()
|
||
// {
|
||
// Instance = new BHRSMarginCalculation();
|
||
// }
|
||
|
||
// // 定义私有构造函数,使外界不能创建该类实例
|
||
// private BHRSMarginCalculation()
|
||
// {
|
||
// }
|
||
|
||
// public override bool MarginCalcNeedSpecial
|
||
// {
|
||
// get
|
||
// {
|
||
// return true;
|
||
// }
|
||
// }
|
||
|
||
// public override List<trade_span> RunMarginCalculation(int userId, string userName, List<trade> tradeList, DateTime settleDate, Dictionary<int, double> priceDict, bool hasOptionInfo = false, bool isEodSettle = false, bool forSingleTrade = true, string volType = "交易", bool forOtherSide = false)
|
||
// {
|
||
// List<trade_span> tradeSpans = new List<trade_span>();
|
||
// if (tradeList != null && tradeList.Count > 0)
|
||
// {
|
||
// if (!(priceDict?.Count > 0))
|
||
// {
|
||
// var codes = tradeList.Select(O => O.UnderlyingCode).ToArray();
|
||
// priceDict = base.GetSettlePrice(codes, settleDate);
|
||
// }
|
||
// if (priceDict.Count == 0)
|
||
// {
|
||
// //如果价格没有传入也没从数据库获取到,就直接返回,没必要往下运行了。但不应该报错;
|
||
// return tradeSpans;
|
||
// }
|
||
// var tempStockTradeList = tradeList.Where(t => t.UnderlyingInstrumentType == ConsGlobal.InstrumentType.Stock).ToList();
|
||
// if (tempStockTradeList.Any())
|
||
// {
|
||
// var stockTradeSpanlist = StockMarginCalculation(userId, userName, tempStockTradeList, settleDate, priceDict, hasOptionInfo, isEodSettle);
|
||
// if (stockTradeSpanlist.Count > 0)
|
||
// {
|
||
// tradeSpans.AddRange(stockTradeSpanlist);
|
||
// }
|
||
// }
|
||
// var tempFutureTradeList = tradeList.Where(t => t.UnderlyingInstrumentType == ConsGlobal.InstrumentType.CommodityFutures).ToList();
|
||
// if (tempFutureTradeList.Any())
|
||
// {
|
||
// if (forSingleTrade)
|
||
// {
|
||
// var futureTradeSpanlist = FutureMarginCalculationForSingleTrade(userId, userName, tempFutureTradeList, settleDate, priceDict, hasOptionInfo, isEodSettle, volType);
|
||
// if (futureTradeSpanlist.Count > 0)
|
||
// {
|
||
// tradeSpans.AddRange(futureTradeSpanlist);
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// var futureTradeSpanlist = FutureMarginCalculation(userId, userName, tempFutureTradeList, settleDate, priceDict, hasOptionInfo, isEodSettle, volType);
|
||
// if (futureTradeSpanlist.Count > 0)
|
||
// {
|
||
// tradeSpans.AddRange(futureTradeSpanlist);
|
||
// }
|
||
// }
|
||
|
||
// }
|
||
// }
|
||
// return tradeSpans;
|
||
// }
|
||
|
||
// /// <summary>
|
||
// /// 股票类期权计算保证金
|
||
// /// </summary>
|
||
// public List<trade_span> StockMarginCalculation(int userId, string userName, List<trade> tradeList, DateTime settleDate, Dictionary<int, double> priceDict, bool hasOptionInfo = false, bool isEodSettle = false)
|
||
// {
|
||
// List<trade_span> tradeSpans = new List<trade_span>();
|
||
// if (tradeList != null && tradeList.Count > 0)
|
||
// {
|
||
// using (YLContext db = new YLContext())
|
||
// {
|
||
// var marginRation = valuedateBLL.SystemDate.MarginRatio ?? 0.15;
|
||
// var clientIds = tradeList.Select(t => t.ClientId).ToList();
|
||
// var clientList = (from client in db.client
|
||
// join clientlevel in db.clientlevel
|
||
// on client.LevelId equals clientlevel.id into tempClientlevel
|
||
// from clientlevelTT in tempClientlevel.DefaultIfEmpty()
|
||
// where clientIds.Contains(client.id)
|
||
// select new
|
||
// {
|
||
// client,
|
||
// clientlevel = clientlevelTT
|
||
// }).ToList();
|
||
|
||
// if (clientList != null)
|
||
// {
|
||
// tradeList.ForEach(t =>
|
||
// {
|
||
// var client = clientList.FirstOrDefault(c => c.client.id == t.ClientId);
|
||
// if (client != null)
|
||
// {
|
||
// var clientRatio = client.clientlevel == null ? 1.0 : (client.clientlevel.Ratio ?? 1.0);
|
||
// //如果是股票去名义本金,如果是期货取:份额 * 即期价格
|
||
// var value = (t.StockEqvNotional ?? (t.Notional * t.SpotPrice ?? 0.0)) * marginRation * (t.BuySell == "买入" ? 1 : (PS.Config.ErpElement.TwoSideMargin && client.client.HasTwoSideMargin == 1 ? -1 : 0)) * clientRatio;
|
||
// var twoSideMargin = (t.StockEqvNotional ?? (t.Notional * t.SpotPrice ?? 0.0)) * marginRation * (t.BuySell == "买入" ? 1 : -1) * clientRatio;
|
||
// if (t.TradeType == "自定义交易")
|
||
// {
|
||
// var eodTradeRiskManual = db.eod_trade_risk_manual.Where(x => x.ValueDate <= settleDate && x.TradeId == t.id).OrderByDescending(x => x.ValueDate).FirstOrDefault();
|
||
// //收盘时如果自定义交易还活着且没有维护当日风险,并且收的时系统日期当日的盘,抛出exception
|
||
// if (isEodSettle && !ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus) && settleDate == valuedateBLL.SystemDate.ValueDate)
|
||
// {
|
||
// if (eodTradeRiskManual == null || eodTradeRiskManual.ValueDate != settleDate)
|
||
// {
|
||
// var error = $"TradeNumber:{t.TradeNumber}在{settleDate.ToString("yyyy-MM-dd")}需先进行交易风险维护";
|
||
// throw new Exception(error);
|
||
// }
|
||
// }
|
||
|
||
// value = eodTradeRiskManual?.Margin ?? 0;
|
||
// twoSideMargin = eodTradeRiskManual?.Margin ?? 0;
|
||
// }
|
||
// tradeSpans.Add(new trade_span
|
||
// {
|
||
// TradeId = t.id,
|
||
// OptDate = DateTime.Now,
|
||
// OptId = userId,
|
||
// OptName = userName,
|
||
// ClientId = client.client.id,
|
||
// UnderlyingId = t.UnderlyingId,
|
||
// UnderlyingCode = t.UnderlyingCode,
|
||
// ValueDate = settleDate,
|
||
// Spv1 = value,
|
||
// Spv2 = value,
|
||
// Spv3 = value,
|
||
// Spv4 = value,
|
||
// WorstCastClientPayable = value,
|
||
// TwoSideMargin = twoSideMargin
|
||
// });
|
||
// }
|
||
// });
|
||
// }
|
||
// }
|
||
// }
|
||
// return tradeSpans;
|
||
// }
|
||
|
||
// /// <summary>
|
||
// /// 商品期权计算保证金 OLD
|
||
// /// </summary>
|
||
// public List<trade_span> FutureMarginCalculation(int userId, string userName, List<trade> futureTradeList, DateTime settleDate, Dictionary<int, double> priceDict, bool hasOptionInfo = false, bool isEodSettle = false, string volType = "交易")
|
||
// {
|
||
// //
|
||
// List<trade_span> tradeSpans = new List<trade_span>();
|
||
// using (YLContext db = new YLContext())
|
||
// {
|
||
// if (!hasOptionInfo)
|
||
// {
|
||
// tradeBLL.SetFieldsByTradeType(futureTradeList);
|
||
// }
|
||
|
||
// var futureManualTradeList = futureTradeList.Where(x => x.TradeType == "自定义交易");
|
||
// var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(userId + "", settleDate, futureTradeList, priceDict, ValueCalculator.BASIC_GREEKS, null, isEodSettle, volType, isUseTradeVol: PS.Config.IsTradeVol, PreciseTimeMode: !isEodSettle);
|
||
// logger.Info($"商品期货保证金计算,交易入:[{futureTradeList.Count}条],返回[{tradeRiskResult.Results.Count}],错误:{tradeRiskResult.ErrorMessage}");
|
||
// //计算保证金包含错误信息时弹出错误信息
|
||
// if (!string.IsNullOrWhiteSpace(tradeRiskResult.ErrorMessage))
|
||
// {
|
||
// throw new Exception(tradeRiskResult.ErrorMessage);
|
||
// }
|
||
// var vegaCoefficient = valuedateBLL.SystemDate.FutureMarginVegaCoefficient ?? 3;
|
||
// var omegaCoefficient = valuedateBLL.SystemDate.FutureMarginOmegaCoefficient ?? 2.5;
|
||
// var alphaRate = valuedateBLL.SystemDate.FutureMarginAlphaRate ?? 1;
|
||
// //客户对应等级系数
|
||
// var clientIds = futureTradeList.Select(t => t.ClientId).ToList();
|
||
// var clientList = (from client in db.client
|
||
// join clientlevel in db.clientlevel
|
||
// on client.LevelId equals clientlevel.id into tempClientlevel
|
||
// from clientlevelTT in tempClientlevel.DefaultIfEmpty()
|
||
// where clientIds.Contains(client.id)
|
||
// select new
|
||
// {
|
||
// client,
|
||
// clientlevel = clientlevelTT
|
||
// }).ToList();
|
||
|
||
// if (tradeRiskResult.Results.Count > 0)
|
||
// {
|
||
// var underlyingCodeLookup = futureTradeList.ToLookup(t => new { t.UnderlyingId, t.ClientId });
|
||
|
||
// foreach (var item in underlyingCodeLookup)
|
||
// {
|
||
// var tempTrades = item.ToList();
|
||
// var tradeIds = tempTrades.Select(t => t.id).ToList();
|
||
// var tempVariety = _underlyingDataProvider.GetVariety(item.Key.UnderlyingId);
|
||
// var closePrice = priceDict.ContainsKey(item.Key.UnderlyingId) ? priceDict[item.Key.UnderlyingId] : 0.0;
|
||
// var optionValueList = tradeRiskResult.Results.Where(t => tradeIds.Contains(t.Trade.id) && t.ValueResult != null && t.Trade != null && !double.IsNaN(t.ValueResult.Delta) && !double.IsNaN(t.ValueResult.Vega) && !double.IsNaN(t.ValueResult.Gamma)).ToList();
|
||
|
||
// //未设置相关保证金系数默认为1.0
|
||
// var client = clientList.FirstOrDefault(c => c.client.id == item.Key.ClientId);
|
||
// var clientRatio = client == null ? 1.0 : (client.clientlevel == null ? 1.0 : (client.clientlevel.Ratio ?? 1.0));
|
||
|
||
// if (optionValueList.Any() && tempVariety != null)
|
||
// {
|
||
// var optionValueListWithOutManual = optionValueList.Where(x => x.Trade.TradeType != "自定义交易");
|
||
// var deltaMerge = 0.0;
|
||
// var deltaLong = optionValueListWithOutManual.Sum(t => (t.ValueResult.Delta) * (t.Trade.BuySell == "卖出" ? 1 : 0));
|
||
// var deltaShort = optionValueListWithOutManual.Sum(t => (t.ValueResult.Delta) * (t.Trade.BuySell == "买入" ? 1 : 0));
|
||
// if (deltaLong * deltaShort == 0)
|
||
// {
|
||
// deltaMerge = Math.Abs(deltaShort);
|
||
// }
|
||
// else if (deltaLong * deltaShort < 0)
|
||
// {
|
||
// if (Math.Abs(deltaLong) >= Math.Abs(deltaShort))
|
||
// {
|
||
// deltaMerge = 0;
|
||
// }
|
||
// else
|
||
// {
|
||
// deltaMerge = Math.Abs(deltaShort) - Math.Abs(deltaLong);
|
||
// }
|
||
// }
|
||
// else
|
||
// {
|
||
// deltaMerge = Math.Abs(deltaShort);
|
||
// }
|
||
// var vegaMerge = Math.Max(optionValueListWithOutManual.Sum(t => Math.Abs(t.ValueResult.Vega) * EodOperationBase.GetSign(t.Trade.BuySell)), 0);
|
||
// var gammaMerge = Math.Max(optionValueListWithOutManual.Sum(t => Math.Abs(t.ValueResult.Gamma) * EodOperationBase.GetSign(t.Trade.BuySell)), 0);
|
||
// //保证金 = SUM((DELTA值 * 数量 * 标的资产收盘价)场内期权保证金率 + Vega值 * 数量 * 0.01 * 3 + Gamma金额 * vol / 16 * 2.5 场内期权保证金率)
|
||
// var value = ((deltaMerge * closePrice) * (tempVariety.Margin)
|
||
// + vegaMerge * 0.01 * vegaCoefficient
|
||
// + gammaMerge * Math.Pow(closePrice, 2) * 0.01 * (optionValueListWithOutManual.First().ValueResult.Vol / 16) * omegaCoefficient * tempVariety.Margin
|
||
// ) * alphaRate * clientRatio;
|
||
|
||
// //如果非自定义交易的保证金为负,会将其算作0,再加上自定义交易的保证金,算出总和,会使得得到的保证金高于实际保证金(暂时理解为对客户有利,不做处理)
|
||
// if (futureManualTradeList.Any())
|
||
// {
|
||
// var manualTradeIds = futureManualTradeList.Select(x => x.id);
|
||
// var eodTradeRiskManuals = db.eod_trade_risk_manual.Where(x => manualTradeIds.Contains(x.id) && x.ValueDate <= settleDate).OrderByDescending(x => x.ValueDate);
|
||
|
||
// foreach (var riskManual in eodTradeRiskManuals)
|
||
// {
|
||
// var trade = futureManualTradeList.FirstOrDefault(x => x.id == riskManual.TradeId);
|
||
// if (trade != null)
|
||
// {
|
||
// value += riskManual.Margin * EodOperationBase.GetSign(trade.BuySell);
|
||
// }
|
||
// }
|
||
// value = Math.Max(value ?? 0, 0);
|
||
// }
|
||
|
||
// tradeSpans.Add(new trade_span
|
||
// {
|
||
// TradeId = tempTrades.First().id,//默认记录为第一条交易记录中
|
||
// OptDate = DateTime.Now,
|
||
// OptId = userId,
|
||
// OptName = userName,
|
||
// ClientId = item.Key.ClientId,
|
||
// ValueDate = settleDate,
|
||
// UnderlyingId = item.Key.UnderlyingId,
|
||
// UnderlyingCode = tempTrades.First().UnderlyingCode,
|
||
// Spv1 = value,
|
||
// Spv2 = value,
|
||
// Spv3 = value,
|
||
// Spv4 = value,
|
||
// WorstCastClientPayable = value,
|
||
// Comment = $"标的{tempTrades.First().UnderlyingCode} 合计计算:{string.Join(",", tempTrades.Select(t => t.id).ToList())}"
|
||
// });
|
||
// }
|
||
// else
|
||
// {
|
||
// var nanTradeValue = tradeRiskResult.Results.Where(t => tradeIds.Contains(t.Trade.id) && (double.IsNaN(t.ValueResult.Delta) || !double.IsNaN(t.ValueResult.Vega) || !double.IsNaN(t.ValueResult.Gamma))).Select(t => t.ValueResult).ToList();
|
||
// nanTradeValue.ForEach(optionValue =>
|
||
// {
|
||
// logger.Error($"交易ID:{item.Key.UnderlyingId},Delta:{optionValue.Delta},DeltaCash{optionValue.DeltaCash},Vega{optionValue.Vega},Gamma:{optionValue.Gamma},vol:{optionValue.Vol}");
|
||
// });
|
||
// }
|
||
// }
|
||
// }
|
||
// return tradeSpans;
|
||
// }
|
||
// }
|
||
|
||
// /// <summary>
|
||
// /// 商品期权计算保证金
|
||
// /// </summary>
|
||
// public List<trade_span> FutureMarginCalculationForSingleTrade(int userId, string userName, List<trade> futureTradeList, DateTime settleDate, Dictionary<int, double> priceDict, bool hasOptionInfo = false, bool isEodSettle = false, string volType = "交易")
|
||
// {
|
||
// //
|
||
// List<trade_span> tradeSpans = new List<trade_span>();
|
||
// using (YLContext db = new YLContext())
|
||
// {
|
||
// if (!hasOptionInfo)
|
||
// {
|
||
// tradeBLL.SetFieldsByTradeType(futureTradeList);
|
||
// }
|
||
|
||
// var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(userId + "", settleDate, futureTradeList, priceDict, ValueCalculator.BASIC_GREEKS, null, isEodSettle, volType, isUseTradeVol: PS.Config.IsTradeVol, PreciseTimeMode: !isEodSettle);
|
||
// logger.Info($"商品期货保证金计算,交易入:[{futureTradeList.Count}条],返回[{tradeRiskResult.Results.Count}],错误:{tradeRiskResult.ErrorMessage}");
|
||
// //计算保证金包含错误信息时弹出错误信息
|
||
// if (!string.IsNullOrWhiteSpace(tradeRiskResult.ErrorMessage))
|
||
// {
|
||
// throw new Exception(tradeRiskResult.ErrorMessage);
|
||
// }
|
||
// var vegaCoefficient = valuedateBLL.SystemDate.FutureMarginVegaCoefficient ?? 3;
|
||
// var omegaCoefficient = valuedateBLL.SystemDate.FutureMarginOmegaCoefficient ?? 2.5;
|
||
// var alphaRate = valuedateBLL.SystemDate.FutureMarginAlphaRate ?? 1;
|
||
// //客户对应等级系数
|
||
// var clientIds = futureTradeList.Select(t => t.ClientId).ToList();
|
||
// var clientList = (from client in db.client
|
||
// join clientlevel in db.clientlevel
|
||
// on client.LevelId equals clientlevel.id into tempClientlevel
|
||
// from clientlevelTT in tempClientlevel.DefaultIfEmpty()
|
||
// where clientIds.Contains(client.id)
|
||
// select new
|
||
// {
|
||
// client,
|
||
// clientlevel = clientlevelTT
|
||
// }).ToList();
|
||
// if (tradeRiskResult.Results.Count > 0)
|
||
// {
|
||
|
||
// var underlyingCodeLookup = futureTradeList.ToLookup(t => new { t.UnderlyingId, t.ClientId });
|
||
|
||
// foreach (var item in tradeRiskResult.Results)
|
||
// {
|
||
// var tempVariety = _underlyingDataProvider.GetVariety(item.Trade.UnderlyingId);
|
||
// var closePrice = priceDict.ContainsKey(item.Trade.UnderlyingId) ? priceDict[item.Trade.UnderlyingId] : 0.0;
|
||
|
||
// //未设置相关保证金系数默认为1.0
|
||
// var client = clientList.FirstOrDefault(c => c.client.id == item.Trade.ClientId);
|
||
// var clientRatio = client == null ? 1.0 : (client.clientlevel == null ? 1.0 : (client.clientlevel.Ratio ?? 1.0));
|
||
|
||
// var deltaMerge = item.ValueResult.Delta;
|
||
// var vegaMerge = item.ValueResult.Vega;
|
||
// var gammaMerge = item.ValueResult.Gamma;
|
||
// //保证金 = SUM((DELTA值 * 数量 * 标的资产收盘价)场内期权保证金率 + Vega值 * 数量 * 0.01 * 3 + Gamma金额 * vol / 16 * 2.5 场内期权保证金率)
|
||
// var value = ((deltaMerge * closePrice) * (tempVariety.Margin ?? 0.0)
|
||
// + vegaMerge * 0.01 * vegaCoefficient
|
||
// + gammaMerge * Math.Pow(closePrice, 2) * 0.01 * (item.ValueResult.Vol / 16) * omegaCoefficient * (tempVariety.Margin ?? 0.0)
|
||
// ) * alphaRate * clientRatio;
|
||
|
||
// if (item.Trade.TradeType == "自定义交易")
|
||
// {
|
||
// var eodTradeRiskManual = db.eod_trade_risk_manual.Where(x => x.ValueDate <= settleDate && x.TradeId == item.Trade.id).OrderByDescending(x => x.ValueDate).FirstOrDefault();
|
||
// //收盘时如果自定义交易还活着且没有维护当日风险,并且收的时系统日期当日的盘,抛出exception
|
||
// if (isEodSettle && !ConsTrade.TradeCompleteStatus.Contains(item.Trade.TradeStatus) && settleDate == valuedateBLL.SystemDate.ValueDate)
|
||
// {
|
||
// if (eodTradeRiskManual == null || eodTradeRiskManual.ValueDate != settleDate)
|
||
// {
|
||
// var error = $"TradeNumber:{item.Trade.TradeNumber}在{settleDate.ToString("yyyy-MM-dd")}需先进行交易风险维护";
|
||
// throw new Exception(error);
|
||
// }
|
||
// }
|
||
|
||
// value = eodTradeRiskManual?.Margin ?? 0;
|
||
// }
|
||
|
||
// tradeSpans.Add(new trade_span
|
||
// {
|
||
// TradeId = item.Trade.id,//默认记录为第一条交易记录中
|
||
// OptDate = DateTime.Now,
|
||
// OptId = userId,
|
||
// OptName = userName,
|
||
// ClientId = item.Trade.ClientId,
|
||
// ValueDate = settleDate,
|
||
// UnderlyingId = item.Trade.UnderlyingId,
|
||
// UnderlyingCode = item.Trade.UnderlyingCode,
|
||
// Spv1 = value,
|
||
// Spv2 = value,
|
||
// Spv3 = value,
|
||
// Spv4 = value,
|
||
// WorstCastClientPayable = value,
|
||
// Comment = $"delta:{deltaMerge},closePrice:{closePrice},vega:{vegaMerge},gamma{gammaMerge},buySell:{item.Trade.BuySell}"
|
||
// });
|
||
// }
|
||
// }
|
||
// return tradeSpans;
|
||
// }
|
||
// }
|
||
|
||
// public override double GetTradeMargin(trade trade, double price, bool isInitialMargin = false, bool hasOptionInfo = false)
|
||
// {
|
||
// using (var db = new YLContext())
|
||
// {
|
||
// if (trade.TradeType == "结构化交易")
|
||
// {
|
||
// trade.SubTrades = db.trade.Where(x => x.ParentTradeId == trade.id).ToList();
|
||
// }
|
||
// }
|
||
|
||
// var tradeMargin = RunMarginCalculation(0, "系统", new List<trade> { trade }, isInitialMargin ? (trade.TradeDate ?? valuedateBLL.ValueDate) : valuedateBLL.ValueDate, new Dictionary<int, double> { { trade.UnderlyingId, price } }, hasOptionInfo: hasOptionInfo);
|
||
// if (null != tradeMargin)
|
||
// {
|
||
// return tradeMargin.FirstOrDefault()?.WorstCastClientPayable ?? 0.0;
|
||
// }
|
||
// return 0.0;
|
||
// }
|
||
// }
|
||
//}
|