Files
zszq-trs/YLErpDAL/Modules/PricingModule/HistoricalBacktestService.cs
2024-05-09 14:06:26 +08:00

133 lines
6.3 KiB
C#

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)
{
}
/// <summary>
/// 结西价格
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public static List<HistoricalBacktestPriceModel> AnalysisPrice(Stream stream)
{
List<ExcelHelper.DataColumnModel> dc = new List<ExcelHelper.DataColumnModel>();
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<HistoricalBacktestPriceModel>(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<HistoricalBacktestRes> Execute(int templateId, List<HistoricalBacktestPriceModel> priceInfos)
{
List<HistoricalBacktestRes> result = new List<HistoricalBacktestRes>();
var obj = new SysUserConfigService(UserInfo).GetConfigInfos(templateId);
if (!string.IsNullOrWhiteSpace(obj?.ConfigData))
{
List<OtcOptionTradeFull> trades = null;
try
{
var codes = priceInfos.Select(O => O.UnderlyingCode).ToArray();
var data = JsonHelper.DeserializeIgnoreNull<List<VueTemplateModel>>(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;
}
}
}