339 lines
16 KiB
C#
339 lines
16 KiB
C#
//using BaseOUDAL;
|
|
//using System;
|
|
//using System.Collections.Generic;
|
|
//using System.Linq;
|
|
//using YLErp.BLL.Calculation;
|
|
//using YLErp.BLL.Calculation.V2;
|
|
//using YLErp.BLL.Eod;
|
|
//using YLErp.DBModels;
|
|
//using YLErp.DBModels.Consts;
|
|
//using YLErp.Model;
|
|
//using YLErp.Modules.DataCacheModule;
|
|
//using YLErp.Modules.TradeDalModule;
|
|
//using YLErp.Modules.VolatilityModule;
|
|
//using YLErp.QdpModule;
|
|
//using CalculatorHelper = YLErp.BLL.Calculation.CalculatorHelperOld;
|
|
|
|
//namespace YLErp.BLL.MarginCalculationBak
|
|
//{
|
|
// /// <summary>
|
|
// /// 方顿
|
|
// /// </summary>
|
|
// public class FDMarginCalculation : MarginCalculationBase
|
|
// {
|
|
// // 定义一个静态变量来保存类的实例
|
|
// public static readonly FDMarginCalculation Instance;
|
|
|
|
// static FDMarginCalculation()
|
|
// {
|
|
// Instance = new FDMarginCalculation();
|
|
// }
|
|
|
|
// // 定义私有构造函数,使外界不能创建该类实例
|
|
// private FDMarginCalculation()
|
|
// {
|
|
// }
|
|
|
|
// 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 (!(priceDict?.Count > 0))
|
|
// {
|
|
// var codes = tradeList.Select(O => O.UnderlyingCode).ToArray();
|
|
// priceDict = base.GetSettlePrice(codes, settleDate);
|
|
// }
|
|
// if (priceDict.Count == 0)
|
|
// {
|
|
// //如果价格没有传入也没从数据库获取到,就直接返回,没必要往下运行了。但不应该报错;
|
|
// return tradeSpans;
|
|
// }
|
|
// using (YLContext db = new YLContext())
|
|
// {
|
|
// if (!hasOptionInfo)
|
|
// {
|
|
// tradeBLL.SetFieldsByTradeType(tradeList);
|
|
// }
|
|
|
|
// var lastSettleDate = EodOperationBase.GetLastSettlementDate(settleDate, true);
|
|
// var tradeIds = tradeList.Select(t => t.id).ToList();
|
|
// var tradeMetaDatas = db.TradeMeta.Where(m => tradeIds.Contains(m.TradeId)).ToList().GroupBy(t => t.TradeId).ToDictionary(g => g.Key, g => g.ToDictionary(m => m.MetaKey, m => m.MetaValue));
|
|
// var positionMaginRatioDic = db.TradeMeta.Where(m => tradeIds.Contains(m.TradeId) && m.MetaKey == ConsTradeMetaKey.PositionMarginRate)
|
|
// .ToList().ToDictionary(m => m.TradeId, m => DataConvert.ToDouble(m.MetaValue));
|
|
|
|
// new TradeDalService(new OptUserInfo(userId, userName)).SetSubTradeList(tradeList);
|
|
// var tradeRiskResult = CalculatorHelper.CalculateRisksForTrades(userId + "", settleDate, tradeList, priceDict, ValueCalculator.BASIC_PRICING, null, isEodSettle, volType, isUseTradeVol: PS.Config.IsTradeVol);
|
|
// logger.Info($"商品期货保证金计算,交易入:[{tradeList.Count}条],返回[{tradeRiskResult.Results.Count}],错误:{tradeRiskResult.ErrorMessage}");
|
|
|
|
// //客户对应等级系数
|
|
// 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 (!string.IsNullOrWhiteSpace(tradeRiskResult.ErrorMessage))
|
|
// {
|
|
// throw new ServiceException(tradeRiskResult.ErrorMessage);
|
|
// }
|
|
// if (tradeRiskResult.Results.Count > 0)
|
|
// {
|
|
// var lastTradeSpanList = db.trade_span.Where(s => s.ValueDate == lastSettleDate).ToList();
|
|
// foreach (var item in tradeRiskResult.Results)
|
|
// {
|
|
// var client = clientList.FirstOrDefault(c => c.client.id == item.Trade.ClientId);
|
|
|
|
// Dictionary<string, string> metaDics = null;
|
|
// if (tradeMetaDatas.ContainsKey(item.Trade.id))
|
|
// {
|
|
// metaDics = tradeMetaDatas[item.Trade.id];
|
|
// }
|
|
// #region 维持保证金率
|
|
// var positionMaginRatio = 0.0;
|
|
// if (metaDics != null && metaDics.ContainsKey(ConsTradeMetaKey.PositionMarginRate))
|
|
// {
|
|
// positionMaginRatio = DataConvert.ToDouble(metaDics[ConsTradeMetaKey.PositionMarginRate]);
|
|
// }
|
|
|
|
// #endregion
|
|
|
|
// #region 当前保证金额
|
|
// var cashDeposit = 0.0;
|
|
// var lastTradeSpan = lastTradeSpanList.FirstOrDefault(s => s.TradeId == item.Trade.id);
|
|
// if (lastTradeSpan != null)
|
|
// {
|
|
// cashDeposit = (lastTradeSpan.CashDeposit ?? 0) + (lastTradeSpan.Margin ?? 0);
|
|
// }
|
|
// else if (metaDics != null && metaDics.ContainsKey(ConsTradeMetaKey.InitialMarginMoney))
|
|
// {
|
|
// cashDeposit = DataConvert.ToDouble(metaDics[ConsTradeMetaKey.InitialMarginMoney]);
|
|
// }
|
|
|
|
// #endregion
|
|
|
|
// var value = Math.Abs(item.ValueResult.DeltaCash) * positionMaginRatio * (item.Trade.BuySell == "买入" ? 1 : (PS.Config.ErpElement.TwoSideMargin && client.client.HasTwoSideMargin == 1 ? -1 : 0));
|
|
// var twoSideMargin = Math.Abs(item.ValueResult.DeltaCash) * positionMaginRatio * (item.Trade.BuySell == "买入" ? 1 : -1);
|
|
|
|
// 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:yyyy-MM-dd}需先进行交易风险维护";
|
|
// throw new Exception(error);
|
|
// }
|
|
// }
|
|
|
|
// value = eodTradeRiskManual?.Margin ?? 0;
|
|
// twoSideMargin = eodTradeRiskManual?.Margin ?? 0;
|
|
// }
|
|
|
|
// #region 风险敞口
|
|
// var riskExposure = 0.0;
|
|
// if (item.Trade.BuySell == "买入")
|
|
// {
|
|
// //这个地方很诡异,GetAsianFinalPrice和ActualStrike使用了相同的逻辑取均价,不同的地方在于ActualStrike使用的是系统日期,但这样又会造成历史收盘的偏差
|
|
// riskExposure = Math.Max(0, (trade_asian_optionBLL.GetAsianFinalPrice(item.Trade, settleDate) - item.Trade.ActualStrike ?? 0) * (item.Trade.OptionType == "看涨" ? 1 : -1)) * item.Trade.Notional;
|
|
// }
|
|
// #endregion
|
|
// //是否需要追保
|
|
// var needMargin = (riskExposure - cashDeposit) > 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,
|
|
// TwoSideMargin = twoSideMargin,
|
|
// RiskExposure = riskExposure,
|
|
// CashDeposit = cashDeposit,
|
|
// Margin = needMargin ? (riskExposure - cashDeposit + Math.Max(value, 0)) : 0,
|
|
// Comment = $"DeltaCash:{item.ValueResult.DeltaCash},PositionMaginRatio:{positionMaginRatio}"
|
|
// });
|
|
// }
|
|
// }
|
|
// return tradeSpans;
|
|
// }
|
|
// }
|
|
|
|
// /// <summary>
|
|
// /// 获取初始保证金率
|
|
// /// </summary>
|
|
// /// <param name="trade"></param>
|
|
// /// <returns></returns>
|
|
// public double? GetInitialMarginRatio(trade trade)
|
|
// {
|
|
// if (trade == null)
|
|
// {
|
|
// return 0;
|
|
// }
|
|
// if (!trade.VarietyId.HasValue || trade.VarietyId <= 0)
|
|
// {
|
|
// return 0;
|
|
// }
|
|
// if (!trade.StockEqvNotional.HasValue)
|
|
// {
|
|
// return 0;
|
|
// }
|
|
// var variety = DataCacheManager.GetVarietyDataSource().GetData(trade.VarietyId ?? 0);
|
|
// if (variety == null)
|
|
// {
|
|
// return 0;
|
|
// }
|
|
|
|
// //OTC-8856 Start
|
|
// var UpLimitValue = variety.UpLimitValue;
|
|
// //var UpLimitValue =((Math.Abs(trade.Underlying.UpDownLimitValue) > 1e-5) ? trade.Underlying.UpDownLimitValue : variety.UpLimitValue);
|
|
// //End
|
|
|
|
// if (trade.StockEqvNotional <= 5000000)
|
|
// {
|
|
// return 2 * UpLimitValue;
|
|
// }
|
|
// else if (trade.StockEqvNotional <= 10000000)
|
|
// {
|
|
// return 2.5 * UpLimitValue;
|
|
// }
|
|
// else if (trade.StockEqvNotional <= 20000000)
|
|
// {
|
|
// return 3 * UpLimitValue;
|
|
// }
|
|
// return null;
|
|
// }
|
|
|
|
// /// <summary>
|
|
// /// 获取维持保证金率
|
|
// /// </summary>
|
|
// /// <param name="trade"></param>
|
|
// /// <returns></returns>
|
|
// public double? GetPositionMarginRatio(trade trade)
|
|
// {
|
|
// if (trade == null)
|
|
// {
|
|
// return 0;
|
|
// }
|
|
// if (!trade.VarietyId.HasValue || trade.VarietyId <= 0)
|
|
// {
|
|
// return 0;
|
|
// }
|
|
// if (!trade.StockEqvNotional.HasValue)
|
|
// {
|
|
// return 0;
|
|
// }
|
|
|
|
// //underlying_manager
|
|
|
|
|
|
// var variety = DataCacheManager.GetVarietyDataSource().GetData(trade.VarietyId ?? 0);
|
|
// if (variety == null)
|
|
// {
|
|
// return 0;
|
|
// }
|
|
// if (trade.StockEqvNotional <= 5000000)
|
|
// {
|
|
// return 1.5 * variety.UpLimitValue;
|
|
// }
|
|
// else if (trade.StockEqvNotional <= 10000000)
|
|
// {
|
|
// return 2 * variety.UpLimitValue;
|
|
// }
|
|
// else if (trade.StockEqvNotional <= 20000000)
|
|
// {
|
|
// return 2.5 * variety.UpLimitValue;
|
|
// }
|
|
// return null;
|
|
// }
|
|
|
|
// /// <summary>
|
|
// /// 获取初始保证金
|
|
// /// </summary>
|
|
// /// <param name="trade"></param>
|
|
// /// <returns></returns>
|
|
// public double GetInitialMargin(trade trade)
|
|
// {
|
|
// return DoInitialMarginCalculationV2(trade);
|
|
// }
|
|
|
|
// public double DoInitialMarginCalculationV2(trade trade)
|
|
// {
|
|
// if (trade.BuySell == "卖出")
|
|
// {
|
|
// return 0;
|
|
// }
|
|
|
|
// var underlying = DataCacheManager.GetUnderlyingDataSource().GetData(trade.UnderlyingId);
|
|
// underlying.QuotationDate = trade.TradeDate;
|
|
|
|
// var spotPrices = new double[] { trade.SpotPrice ?? 0 };
|
|
|
|
// string userGroup = UserBLL.GetUserGroup(trade.TraderId ?? 0);
|
|
// var volSurfaceData = VolatilityHelper.GetVol(underlying.QuotationDate.Value, "交易", underlying.UnderlyingCode, userGroup);
|
|
|
|
// var vol = OptionCalculator.GetInterpolatedVol(
|
|
// VolConstructionType.Normal,
|
|
// trade.OptId.ToString(),
|
|
// volSurfaceData,
|
|
// underlying.QuotationDate?.ToString("yyyy-MM-dd"),
|
|
// underlying.UnderlyingCode,
|
|
// trade.ExerciseDate?.ToString("yyyy-MM-dd"),
|
|
// trade.Strike ?? 0.0,
|
|
// isBuy: true,
|
|
// isCall: trade.CallPut == "Call",
|
|
// spotPrice: spotPrices[0],
|
|
// isMoneynessOption: trade.IsMoneynessOptionData,
|
|
// timeToMaturityDays: trade.TTMDays ?? double.NaN);
|
|
|
|
// if (!trade.NoRiskRate.HasValue)
|
|
// {
|
|
// trade.NoRiskRate = (valuedateBLL.SystemDate.RiskFreeRate ?? 0) * 0.01;
|
|
// }
|
|
|
|
// string fixing = null;
|
|
// //亚式期权
|
|
// if (trade.TradeType == "亚式期权" || trade.StructureType == "亚式熊市价差")
|
|
// {
|
|
// fixing = CalculatorHelper.GetFixingStringForAsianOption(trade, trade.TradeDate);
|
|
// }
|
|
// var optionValue = ValueCalculator.GetOptionValueResultV2(
|
|
// trade.OptId.ToString(),
|
|
// underlying,
|
|
// trade,
|
|
// new double[] { vol },
|
|
// spotPrices,
|
|
// fixing,
|
|
// commodityFuturesPreciseTimeMode: true);
|
|
// //保证金初始价值=期初期权价值+CashDelta(t)*保证金初始比例(保证金初始比例)
|
|
// return (trade.TradePrice ?? 0) + ((optionValue == null) ? 0 : Math.Abs(optionValue.DeltaCash)) * (trade.InitialMarginRatio ?? 0);
|
|
// }
|
|
|
|
// public override double GetTradeMargin(trade trade, double price, bool isInitialMargin = false, bool hasOptionInfo = false)
|
|
// {
|
|
// 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;
|
|
// }
|
|
// }
|
|
//}
|