133 lines
6.3 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|