using YLErp.Commons; using YLErp.Enums; using YLErp.Modules.CalculationModule; using YLErp.Modules.SystemModule; namespace YLErp.Modules.PricingModule { public class HistoricalBacktestService : YLBaseService { public HistoricalBacktestService(OptUserInfo userInfo) : base(userInfo) { } /// /// 结西价格 /// /// /// public static List AnalysisPrice(Stream stream) { List dc = new List(); dc.Add(new ExcelHelper.DataColumnModel("代码", nameof(HistoricalBacktestPriceModel.UnderlyingCode))); dc.Add(new ExcelHelper.DataColumnModel("日期", nameof(HistoricalBacktestPriceModel.TimeSeries), (currentValue, obj) => { DateTime time = default(DateTime); if (!string.IsNullOrWhiteSpace(currentValue?.ToString()) && DateTime.TryParse(currentValue?.ToString(), out time)) { return time; } return time; })); dc.Add(new ExcelHelper.DataColumnModel("最新标的价格", nameof(HistoricalBacktestPriceModel.Price), (currentValue, obj) => { double price = double.NaN; if (!string.IsNullOrWhiteSpace(currentValue?.ToString()) && double.TryParse(currentValue?.ToString(), out price)) { return price; } return price; })); var tempList = new ExcelHelper().ExcelToListT(dc.ToArray(), stream); var result = tempList.Aggregate((X, Y) => { X.Value.AddRange(Y.Value); return X; }).Value; result.ForEach(O => O.UnderlyingName = DataCacheProvider.GetUnderlyingDataSource().GetData(O.UnderlyingCode)?.UnderlyingName); return result; } private double CalculateTTMDays(DateTime from, DateTime to, int varietyid = 0, SettlementTypeEnum settlementType = SettlementTypeEnum.ClosePrice) { if (PS.Config.Is润和) { from = DateTime.Today; } var ttmDays = 0d; if (PS.Config.Is厦门象屿 && settlementType == SettlementTypeEnum.ReferencePrice) { ttmDays = TradeCalcHelper.CalculateTTMDaysForXiangYu(from, to, varietyid, PS.Config.ErpElement.PrecisionOfMinuteInQuote); } else { ttmDays = TradeCalcHelper.CalculateTTMDays(from, to, varietyid, PS.Config.ErpElement.PrecisionOfMinuteInQuote); } return ttmDays; } public List Execute(int templateId, List priceInfos) { List result = new List(); var obj = new SysUserConfigService(UserInfo).GetConfigInfos(templateId); if (!string.IsNullOrWhiteSpace(obj?.ConfigData)) { List trades = null; try { var codes = priceInfos.Select(O => O.UnderlyingCode).ToArray(); var data = JsonHelper.DeserializeIgnoreNull>(obj.ConfigData); if (data == null//模板信息为空 || data.Any(O => O.datas == null)//模板内容为空 || data.Any(O => O.datas.Any(B => B.trade == null))//模板中有为空的交易 || !data.Any(O => O.datas.Any(B => codes.Contains(B.trade.UnderlyingCode))))//模板中不包含已上传价格标的的交易; { throw new ServiceException("模板匹配错误"); } trades = data.Aggregate( (X, Y) => { X.datas.AddRange(Y.datas); return X; }).datas.Select(O => O.trade).ToList(); var service = new PriceCalcService(UserInfo); foreach (var item in priceInfos) { var r = new HistoricalBacktestRes(item); var calcTrades = trades.Where(O => O.UnderlyingCode == item.UnderlyingCode && O.ExerciseDate >= item.TimeSeries).ToList(); if (calcTrades.Count >= 0) { var um = DataCacheProvider.GetUnderlyingDataSource().GetData(item.UnderlyingCode); calcTrades.ForEach(O => { O.UnderlyingPrice = item.Price; O.ValueDate = item.TimeSeries.Date; O.TTMDays = CalculateTTMDays(O.ValueDate.Value, O.ExerciseDate.Value, um.UnderlyingTypeId); }); var priceResults = service.CalcOptionPrice(calcTrades, false, CalcScenarioEnum.ScenarioCalc); r.delta = priceResults.Sum(O => O.calcResult.Delta); r.deltaInLots = r.delta / um.ContractSize; r.deltaCash = r.delta * item.Price; r.gamma = priceResults.Sum(O => O.calcResult.Gamma); r.theta = priceResults.Sum(O => O.calcResult.Theta); r.rho = priceResults.Sum(O => O.calcResult.Rho * 100); r.vega = priceResults.Sum(O => O.calcResult.Vega); } result.Add(r); } } catch (ServiceException) { throw; } catch (Exception ex) { LogFactory.GetLogger("HistoricalBacktestService").Error(ex); throw new ServiceException("计算错误,请查看日志"); } } return result; } } }