Files
zszq-trs/YLErpDAL/Modules/EodModule/QueryModule/DongZhengEodTradePositionExportService.cs
T
2024-05-09 14:06:26 +08:00

453 lines
20 KiB
C#

using BaseOUDAL;
using YLErp.Abstract.DataProviders;
using YLErp.BLL;
using YLErp.Helpers;
using YLErp.Model;
using YLErp.Modules.CalculationModule;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.EodModule.SettlementModule;
using YLErp.Office;
using YLErp.QdpModule;
namespace YLErp.Modules.EodModule.QueryModule
{
/// <summary>
/// 东证日终存续交易导出服务
/// </summary>
public class DongZhengEodTradePositionExportService : YLBaseService
{
public DongZhengEodTradePositionExportService(OptUserInfo optUser) : base(optUser)
{
}
public void ExportDongZhengZipFile(DateTime valueDate)
{
if (QdpCalendarHelper.GetNonHoliday(valueDate) != valueDate)
{
throw new ServiceException($"所选日期'{valueDate:yyyy-MM-dd}'不是交易日!");
}
if (!DbContext.eodStatus.Any(n => n.ValueDate == valueDate && n.Status == "已收盘"))
{
throw new ServiceException($"所选日期'{valueDate:yyyy-MM-dd}'未收盘!");
}
List<eod_position_dz> eods = GetEodPosition(valueDate);
List<client_dz> clients = GetClients(valueDate);
var dateStr = valueDate.ToString("yyyyMMdd");
var fileName = $"RH_Otc_Option_List.{dateStr}";
var zipFileName = $"{fileName}.zip";
var targetPath = Path.Combine("F:");
if (!Directory.Exists(targetPath))
{
targetPath = Path.Combine("D:\\list\\wait", dateStr);
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
}
else
{
targetPath = Path.Combine("F:\\list\\wait", dateStr);
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
}
var marketZipFile = Path.Combine(targetPath, zipFileName);
if (File.Exists(marketZipFile))
{
File.Delete(marketZipFile);
}
var excelFileName = $"{fileName}.xlsx";
var targetFileName = Path.Combine(targetPath, excelFileName);
var path = Path.Combine(targetPath, targetFileName);
if (File.Exists(path))
{
File.Delete(path);
}
var modelDict = new Dictionary<string, object>();
if (eods != null)
{
modelDict.Add("存续交易", eods);
}
if (clients != null)
{
modelDict.Add("客户信息", clients);
}
var sourcePath = OtcAppContext.MapPath("~/App_Docs/导出模板");
var sourceFileName = Path.Combine(sourcePath, "东证RH_Otc_Option_List.xlsx");
var pdffile = ExcelTemplate.GeneratePDFFromExeclTemplate(sourcePath, sourceFileName, modelDict, targetPath, targetFileName, shouldDeleteSheet: true, needToPdf: false);
ZipHelper.zipOnlyFile(pdffile, marketZipFile, "Dzrh@2022");
File.Delete(targetFileName);
}
private List<eod_position_dz> GetEodPosition(DateTime valueDate)
{
using (var basedb = new ErpBaseContext())
{
EodPriceProvider eodPrice = new EodPriceProvider(valueDate, isDiviendPrice: false);
eodPrice.Initialize();
double riskFreeRate = (valuedateBLL.SystemDate.RiskFreeRate / 100).Normalize();
IEodVolProvider eodVolProvider = EodVolProviderFactory.GetEodVolProvider(valueDate, "持仓");
List<trade> otcTrades = OtcTrades(valueDate);
var eodTradeQuery = DbContext.eod_trade.Where(et => et.ValueDate == valueDate && et.TradeId > 0 && et.TradeType != "结构化交易" && et.ClientId > 0 && ConsTrade.NeedMarginTradeStatusList.Contains(et.TradeStatus));
var query = from trade in eodTradeQuery
join tradeOrigin in DbContext.trade on trade.TradeId equals tradeOrigin.id
join po in DbContext.eod_trade_position.Where(x => x.ValueDate == valueDate) on trade.TradeId equals po.TradeId into position
from po in position.DefaultIfEmpty()
where (tradeOrigin.TradeType != "结构化交易" && tradeOrigin.IsGroup != 1 || tradeOrigin.IsGroup == 1 && tradeOrigin.TradeType == "结构化交易")
&& (tradeOrigin.IsGroup != 2 || tradeOrigin.IsGroup == 2 && tradeOrigin.TradeType == "收益互换")
&& tradeOrigin.ValidState != ConsGlobal.InValid
select new eod_position_dz
{
TradeId = tradeOrigin.id,
TradeType = tradeOrigin.IsGroup == 1 ? tradeOrigin.StructureType : tradeOrigin.TradeType,
ClientId = tradeOrigin.ClientId,
TradeNumber = tradeOrigin.TradeNumber,
TradeDate = tradeOrigin.TradeDate,
ExerciseDate = tradeOrigin.ExerciseDate,
PrincipalRate = tradeOrigin.PrincipalRate ?? 0,
BasisUnderlyingCode = tradeOrigin.BasisUnderlyingCode,
BasisGap = tradeOrigin.BasisGap ?? 0,
Lots = tradeOrigin.Lots ?? 0,
ParticipationRate = tradeOrigin.ParticipationRate ?? 0,
NoRiskRate = tradeOrigin.NoRiskRate ?? 0,
UnderlyingCode = trade.UnderlyingCode,
UnderlyingPrice = null,
ValueDate = valueDate,
TradeJson = trade.TradeJson,
PvDouble = 0,
PnlDouble = 0,
InstrumentType = tradeOrigin.UnderlyingInstrumentType,
IsGroup = tradeOrigin.IsGroup,
SettlementType = tradeOrigin.SettlementType,
Margin = po == null ? 0 : po.Margin,
Pv = po == null ? 0 : PS.Config.IsPVRounded ? po.RoundedPv : po.Pv,
};
var queryList = query.ToList();
var underlyingDataSource = DataCacheProvider.GetUnderlyingDataSource();
var varietyDataSource = DataCacheProvider.GetVarietyDataSource();
var clients = DataCacheProvider.GetClientDataSource();
var varietyTypeList = (from i in basedb.DictionaryItems join d in basedb.Dictionaries on i.DictId equals d.Id where d.Name == "品种类型" select i).ToList();
var assetTypeList = (from i in basedb.DictionaryItems join d in basedb.Dictionaries on i.DictId equals d.Id where d.Name == "资产类型" select i).ToList();
GetUpDownLimitPrices(otcTrades, eodPrice, out IPriceProvider upLimitPrices, out IPriceProvider downLimitPrices);
foreach (var x in queryList)
{
var um = underlyingDataSource.GetData(x.UnderlyingCode);
if (um != null)
{
if (um.IsSynthetic())
{
var sy = underlyingDataSource.GetSyntheticUnderlying(x.UnderlyingCode);
if (sy != null)
{
x.SyntheticUnderlyingTipsInfo = sy.UnderlyingTipsInfo;
}
}
var va = varietyDataSource.GetData(um.UnderlyingTypeId);
if (va != null)
{
x.underingName = um.MarketCode != null ? va.VarietyCode + "." + um.MarketCode : va.VarietyCode;
x.varietyType = formatDictItem(varietyTypeList, va.AssetType);
x.assType = formatDictItem(assetTypeList, va.AssetType, "O");
}
}
if (x.TradeType == "收益互换")
{
x.toolType = "SW";
}
else if (x.TradeType == "远期" || x.TradeType == "掉期")
{
x.toolType = "FW";
}
else
{
x.toolType = "OP";
}
if (eodPrice.TryGetPrice(x.UnderlyingCode, x.SettlementType, out var price))
{
x.UnderlyingPrice = price;
}
var client = clients.GetData(x.ClientId ?? 0);
if (client != null)
{
x.ClientName = client.Name;
x.clientNumber = client.Number;
x.ClientType = client.CustomerNature2 != null && !client.CustomerNature2.Contains("产业客户") ? "其他客户" : "产业客户";
//增加内部客户属性 进行赋值
x.IsInsided = client.IsInsided;
}
x.dic = x.trade.MetaDic;
if (x.TradeType == "现金流交易")
{
x.trade.OriginalNotional = null;
}
x.buyType = x.BuySell == "买入" ? "买" : "卖";
x.isEnd = "否";
x.tradeType2 = x.OptionType == "看涨" ? "C" : x.OptionType == "看跌" ? "P" : "0";
var td = otcTrades.FirstOrDefault(t => t.id == x.TradeId);
if (td.TradeType != "自定义交易")
{
var upValue = CalcLiveOtcTradeValueR(valueDate, td, upLimitPrices, eodVolProvider, riskFreeRate);
var downValue = CalcLiveOtcTradeValueR(valueDate, td, downLimitPrices, eodVolProvider, riskFreeRate);
x.MaximumLoss = Math.Min(PS.Config.IsPVRounded ? upValue.RoundedPv : upValue.Pv, PS.Config.IsPVRounded ? downValue.RoundedPv : downValue.Pv) + x.TradePrice;
}
}
//去除内部客户交易
queryList = queryList.Where(l => l.IsInsided != 1).ToList();
return queryList;
}
}
private List<client_dz> GetClients(DateTime valueDate, IEnumerable<int> clienIds = null)
{
using (var baseDb = new ClientDBContext())
{
var clientQuery = from client in baseDb.client.Where(n => n.ProcessStatus == "已开户" && n.IsInsided != 1)
select new client_dz
{
id = client.id,
ProtocolSignDate = client.ProtocolSignDate,
LicenseCode = client.LicenseCode,
Number = client.Number,
Name = client.Name,
ClientType = client.CustomerNature2
};
var creditList = DbContext.credit.Where(t => t.ProcessStatus == "已审批" && (!t.CreditDeadLine.HasValue || t.CreditDeadLine >= valueDate) && (!t.CreditStartDate.HasValue || t.CreditStartDate <= valueDate));
if (clienIds != null)
{
clientQuery = clientQuery.Where(t => clienIds.Contains(t.id));
}
var list = clientQuery.ToList();
foreach (var item in list)
{
item.ClientType = item.ClientType != null && !item.ClientType.Contains("产业客户") ? "其他客户" : "产业客户";
var credit = creditList?.FirstOrDefault(x => x.ClientId == item.id);
item.isCredit = credit != null ? "是" : "否";
item.CreditNumber = credit != null ? credit.Credit : null;
}
return list;
}
}
private static string formatDictItem(List<DictionaryItem> dictItemMap, string name, string defaultValue = "")
{
if (name == null || dictItemMap == null) { return defaultValue; }
var obj = dictItemMap.FirstOrDefault(O => O.Name == name);
return obj == null ? defaultValue : obj.ShortName;
}
private TradeValueResult CalcLiveOtcTradeValueR(DateTime valueDate, trade td, IPriceProvider eodPrice, IEodVolProvider volProvider, double riskFreeRate)
{
var underlyings = new underlying_manager[] { new underlying_manager { UnderlyingCode = td.UnderlyingCode } };
var spotPrice = eodPrice.GetPrice(td.UnderlyingCode);
switch (td.TradeType)
{
case ConsGlobal.TradeType.Forward:
{
if (PS.Config.ErpElement.ForwardTradePriceModel == Configuration.Enums.ForwardTradePriceModel.STANDARD && !string.IsNullOrWhiteSpace(td.BasisUnderlyingCode))
{
var BasiseodPrice = eodPrice.GetPrice(td.BasisUnderlyingCode);
spotPrice -= BasiseodPrice;
}
return ForwardradeCalcService.CalcValue(td, spotPrice);
}
case ConsGlobal.TradeType.PayoffSwap:
return PayoffSwapCalcService.CalcValue(td, valueDate, eodPrice, true);
default:
{
var req = new OptionValueCalcRequest(riskFreeRate)
{
correlations = null,//不计算彩虹等多标的期权暂时不需要
engineName = null,
preciseTimeMode = false, //日终一定是false
isEodCalc = true,
pricingRequest = QdpPricingRequest.BASIC_GREEKS,
spotPrices = new[] { spotPrice },
calcScenario = Enums.CalcScenarioEnum.EodSettlement,
};
if (td.TradeType != ConsGlobal.TradeType.CashFlow)
{
var vol = volProvider.GetVol(td, spotPrice) ?? ConsGlobal.DefaultVol;
req.vols = new[] { vol };
}
return OptionCalculatorV2.GetOptionValueResult(valueDate, td, req, out underlyings);
}
}
}
/// <summary>
/// 获取涨跌20%停价格字典
/// </summary>
private void GetUpDownLimitPrices(List<trade> trade, EodPriceProvider eodPrice, out IPriceProvider upLimitPrices, out IPriceProvider downLimitPrices)
{
HashSet<string> _underlyingCodeSet;
_underlyingCodeSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
void setUnderlyingCode(trade td)
{
if (td?.UnderlyingCode == null)
{
return;
}
_underlyingCodeSet.Add(td.UnderlyingCode);
switch (td.TradeType)
{
case "彩虹期权":
if (td.trade_rainbow_option != null)
{
_underlyingCodeSet.Add(td.trade_rainbow_option.UnderlyingAssetCode2);
}
break;
case "价差期权":
if (td.trade_spread_option != null)
{
var codes = td.trade_spread_option.UnderlyingAssetCodes();
foreach (var code in codes)
{
_underlyingCodeSet.Add(code);
}
}
break;
case "结构化交易":
if (td.SubTrades != null)
{
foreach (var std in td.SubTrades)
{
setUnderlyingCode(std);
}
}
break;
}
}
foreach (var td in trade)
{
setUnderlyingCode(td);
}
var upLimitPrices2 = new ManualPriceProvider();
var downLimitPrices2 = new ManualPriceProvider();
//根据涨跌幅限制以及当日结算价计算涨停价以及跌停价
foreach (var code in _underlyingCodeSet)
{
if (eodPrice.TryGetPrice(code, SettlementTypeEnum.ClosePrice, out var price))
{
var limit = price * 0.2;
var upprice = price + limit;
var downprice = price - limit;
upLimitPrices2.SetPrice(code, upprice);
downLimitPrices2.SetPrice(code, downprice);
}
}
upLimitPrices = upLimitPrices2;
downLimitPrices = downLimitPrices2;
}
TradeCashDataProvider _tradeCashProvider;
private List<trade> OtcTrades(DateTime valueDate)
{
//如果前一天是假日,要显示包含假日的交易
var preday = BLL.valuedateBLL.GetNonHolidayDefore(valueDate.AddDays(-1));
var predicate = PredicateBuilder.Create<trade>(t => t.TradeDate <= valueDate && t.ValidState != ConsGlobal.InValid && t.ClientId > 0
&& t.TradeType != "结构化交易" && t.ExerciseDate > preday && (!ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus) || t.UnWindDate > preday));
var list = new EodSettleDataQueryService(UserInfo)
.GetOtcTrades(valueDate, predicate, out _tradeCashProvider);
var hisDataProvider = new TradeHisDataProvider(valueDate).Initialize();
foreach (var item in list)
{
var noRiskRate = hisDataProvider.GetNoRiskRate(item.id);
var dividendRate = hisDataProvider.GetDividendRate(item.id);
//如果修改过无风险利率或分红率,且和eodTrade中不匹配,则移除该交易来自EodTrade的标记;
if (((noRiskRate ?? 0) > 0 && noRiskRate.GetValueOrDefault() != item.NoRiskRate.GetValueOrDefault()) ||
((dividendRate ?? 0) > 0 && dividendRate.GetValueOrDefault() != item.DividendRate.GetValueOrDefault()))
{
item.MetaDic.Remove("from_eod_trade");
}
item.NoRiskRate = noRiskRate ?? item.NoRiskRate ?? BLL.valuedateBLL.RiskFreeRate;
item.DividendRate = dividendRate ?? item.DividendRate;
if (item.DividendRate == null)
{
item.DividendRate = DataCacheProvider.GetUnderlyingDataSource().GetData(item.UnderlyingCode)?.DividendRate ?? item.NoRiskRate;
}
}
return list;
}
}
public class eod_position_dz : eod_position
{
public string clientNumber { set; get; }
public string ClientType { get; set; }
public string buyType { get; set; }
public string isEnd { get; set; }
public string tradeType2 { get; set; }
public string varietyType { get; set; }
public string assType { get; set; }
public string toolType { get; set; }
public string underingName { get; set; }
/// <summary>
/// 最大亏损
/// </summary>
public double? MaximumLoss { set; get; }
/// <summary>
/// 内部客户
/// </summary>
public int? IsInsided { get; set; }
}
public class client_dz
{
public int id { get; set; }
public DateTime? ProtocolSignDate { get; set; }
public string LicenseCode { get; set; }
public string Number { set; get; }
public string Name { set; get; }
public string ClientType { get; set; }
public string isCredit { set; get; }
public double? CreditNumber { set; get; }
}
}