从山证v2.3.0拷贝

This commit is contained in:
吴方海
2024-05-09 14:06:26 +08:00
parent 566ff33259
commit f9d8a256a6
4471 changed files with 1203456 additions and 9 deletions
@@ -0,0 +1,452 @@
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; }
}
}
@@ -0,0 +1,156 @@
namespace YLErp.Modules.EodModule.QueryModule
{
/// <summary>
/// 日终清算--了结信息流水
/// </summary>
public class EodCloseInfoQueryService : YLBaseService<EodSettleInfoQueryContext>
{
public EodCloseInfoQueryService(EodSettleInfoQueryContext context) : base(context)
{
}
public IEnumerable<EodCloseInfoField> GetEodCloseInfoList(DateTime valueDate, List<int> clientIdsOfInside = null)
{
valueDate = valueDate.Date;
var tradeQuery = DbContext.trade.AsQueryable();
if (clientIdsOfInside != null)
{
tradeQuery = tradeQuery.Where(a => !clientIdsOfInside.Contains(a.ClientId));
}
var query = from tc in DbContext.trade_cash
join td in tradeQuery on tc.TradeId equals td.id
//join tcSwap in DbContext.trade_cash_swap on tc.id equals tcSwap.TradeId into tcSwap_t
//from tcSwap in tcSwap_t.DefaultIfEmpty()
where tc.ValueDate == valueDate && tc.ValidState != ConsGlobal.InValid && !tc.IsDeleted
&& (tc.Action == ClientCashInCashOut._行权费 || tc.Action == ClientCashInCashOut._平仓费
|| tc.Action == ClientCashInCashOut._票息 && tc.IsLastAction)
&& td.ValidState != ConsGlobal.InValid && td.IsGroup != 2
select new
{
td.ClientId,
td.TradeNumber,
td.TradeType,
td.StructureType,
td.TradePrice,
td.BuySell,
td.TradeDate,
td.OptionType,
td.UnderlyingCode,
tcAction = tc.Action,
tcAmount = tc.Amount,
tc.UnwindPercentRate
};
var datas = query.ToArray();
var list = new List<EodCloseInfoField>(datas.Length);
var tradeNumberList = datas.Where(O => O.TradeType == "收益互换").Select(O => O.TradeNumber).ToHashSet();
var swapDict = (from t in DbContext.trade
join ts in DbContext.trade_swap
on t.id equals ts.TradeId
where tradeNumberList.Contains(t.TradeNumber)
select new
{
t.TradeNumber,
LongShort = ts.IsGetFloatingProfit ? ts.GetLongShort : ts.PayLongShort,
}).ToDictionary(K => K.TradeNumber, V => V.LongShort);
foreach (var n in datas)
{
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(n.UnderlyingCode);
var f = new EodCloseInfoField
{
TradeNumber = n.TradeNumber,
TradeType = n.TradeType,
StructureType = n.StructureType,
TradeSide = n.BuySell,
TradeDate = n.TradeDate.OtcFormatDate(),
CallPut = n.TradeType == "收益互换" && swapDict.ContainsKey(n.TradeNumber) ? swapDict[n.TradeNumber] : ConsGlobal.CallPut.IsCall(n.OptionType) ? "多头" : "空头",
UnderlyingCode = n.UnderlyingCode,
UnderlyingName = um?.UnderlyingName,
CloseFee = 0,
ClientNumber = null,
CloseProfit = CalculationModule.TradeCalcHelper.CalcWinLoss(tradeType: n.TradeType, buySell: n.BuySell, tradePrice: n.TradePrice ?? 0, tcUnwindPercent: n.UnwindPercentRate ?? 0, tcAmount: n.tcAmount)
};
if (_context.TryGetClientInfo(n.ClientId, out var clientInfo))
{
f.ClientNumber = clientInfo.Number;
}
list.Add(f);
}
return list;
}
}
/// <summary>
/// 日终清算--了结信息流水
/// </summary>
public class EodCloseInfoField
{
/// <summary>
/// 交易编号
/// </summary>
public string TradeNumber { get; set; }
/// <summary>
/// 子账户编码
/// </summary>
public string ClientNumber { get; set; }
/// <summary>
/// 交易类型
/// </summary>
public string TradeType { get; set; }
/// <summary>
/// 交易日期
/// </summary>
public string TradeDate { get; set; }
/// <summary>
/// 交易方向
/// </summary>
public string TradeSide { get; set; }
/// <summary>
/// 看涨看跌
/// </summary>
public string CallPut { get; set; }
/// <summary>
/// 标的代码
/// </summary>
public string UnderlyingCode { get; set; }
/// <summary>
/// 标的名称
/// </summary>
public string UnderlyingName { get; set; }
/// <summary>
/// 结构类型
/// </summary>
public string StructureType { get; set; }
/// <summary>
/// 平仓盈亏
/// </summary>
public double CloseProfit { get; set; }
/// <summary>
/// 手续费
/// </summary>
public double CloseFee { get; set; }
}
}
@@ -0,0 +1,92 @@
using System.Linq.Expressions;
using YLErp.Abstract;
using YLErp.Models;
using YLErp.Modules.ClientModule;
namespace YLErp.Modules.EodModule.QueryModule
{
/// <summary>
/// 日终结算信息查询上下文
/// </summary>
public class EodSettleInfoQueryContext : YLServiceContext, IDataSource<ClientMainInfo>
{
Dictionary<int, ClientMainInfo> _dic;
public EodSettleInfoQueryContext(OptUserInfo userInfo) : base(userInfo)
{
}
#region----IDataSource<ClientMainInfo>----
public int Count => _dic != null ? _dic.Count : 0;
public IQueryable<ClientMainInfo> AsQueryable(Expression<Func<ClientMainInfo, bool>> predicate = null)
{
InitClientDic();
var qry = _dic.Values.AsQueryable();
return predicate == null ? qry : qry.Where(predicate);
}
public ClientMainInfo GetData(int keyId)
{
TryGetClientInfo(keyId, out var clientInfo);
return clientInfo;
}
public void ResetDataSource()
{
_dic?.Clear();
}
#endregion
/// <summary>
/// 获取客户信息
/// </summary>
public bool TryGetClientInfo(int clientId, out ClientMainInfo clientInfo)
{
InitClientDic();
return _dic.TryGetValue(clientId, out clientInfo);
}
/// <summary>
///
/// </summary>
public List<int> GetClientIds()
{
InitClientDic();
return _dic.Keys.ToList();
}
public List<int> GetClientIdsOfInside()
{
var clientIds = GetClientIds();
using (var clientdb = DbContextFactory.GetClientDbContext(null))
{
if (clientIds.Any())
{
return clientdb.client.Where(a => clientIds.Contains(a.id) && a.IsInsided ==1).Select(a => a.id).ToList();
}
else
{
return new List<int>();
}
}
}
private void InitClientDic()
{
if (_dic == null)
{
_dic = ClientDataQueryService.GetClientsFromDB(x => x.ProcessStatus != "未提交").ToDictionary(n => n.id);
}
}
}
}
@@ -0,0 +1,745 @@
using System.Data;
using YLErp.Commons;
using YLErp.DBModels.Helpers;
using YLErp.Models;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.TradeModule;
namespace YLErp.Modules.EodModule.QueryModule
{
/// <summary>
/// 日终清算服务
/// </summary>
public class EodTradePositionApiService : YLBaseService<EodSettleInfoQueryContext>
{
public EodTradePositionApiService(EodSettleInfoQueryContext context) : base(context)
{
}
/// <summary>
/// 查询场外期权持仓列表
/// </summary>
public EodTradePositionResult GetEodPositions(EodSettleInfoRequest req, List<int> clientIdsOfInside = null)
{
var valueDate = req.ValueDate;
var result = new EodTradePositionResult
{
SwapPositions = new List<EodPayOffSwapPositionField>(),
OptionPositions = new List<EodOptionPositionField>(),
ForwardPositions = new List<EodForwardPositionField>()
};
var IsPVRounded = PS.Config.IsPVRounded;
valueDate = valueDate.Date;
var eodQuery = DbContext.eod_trade.AsQueryable();
if (clientIdsOfInside != null)
{
eodQuery = eodQuery.Where(a => !clientIdsOfInside.Contains(a.ClientId));
}
var query = from et in eodQuery
join t in DbContext.trade on et.TradeId equals t.id
join etp in DbContext.eod_trade_position on new { et.TradeId, et.ValueDate } equals new { etp.TradeId, etp.ValueDate } into etp_s
from etp in etp_s.DefaultIfEmpty()
join etr in DbContext.eod_trade_risk on new { et.TradeId, et.ValueDate } equals new { etr.TradeId, etr.ValueDate } into etr_s
from etr in etr_s.DefaultIfEmpty()
where et.ValueDate == valueDate && t.ClientId > 0
select new InnerPosition
{
TradeId = et.TradeId,
TradeJson = et.TradeJson,
CallPut = t.OptionType,
TradeAmount = etp == null ? 0 : etp.Amount,
PositionPv = etp == null ? 0 : IsPVRounded ? etp.RoundedPv : etp.Pv,
PositionPnl = etp == null ? 0 : IsPVRounded ? etp.RoundedPositionPnL : etp.PositionPnL,
ParentTradeId = t.ParentTradeId,
IsGroup = t.IsGroup,
DailyPnl = etp == null ? 0 : etp.DailyPnL,
Risk = etr == null ? null : new InnerPositionRisk
{
Delta = etr.Delta,
Gamma = etr.Gamma,
Theta = etr.Theta,
Rho = etr.Rho,
Vega = etr.Vega,
DeltaCash = etr.DeltaCash,
GammaCash = etr.GammaCash,
VegaCash = etr.VegaCash,
Vol = etr.Vol
}
};
//因为query还在读取中,所以不要用同一个dbcontext
var extendService = new TradeExtendService(OptUser);
var eodPriceProvider = new EodPriceProvider(valueDate).Initialize();
var posList = query.ToArray();
var groupSumDic = new Dictionary<int, InnerPosition>();
foreach (var pos in posList)
{
if (pos.IsGroup == 2 && pos.ParentTradeId > 0)
{
if (!groupSumDic.TryGetValue(pos.ParentTradeId, out var p))
{
groupSumDic[pos.ParentTradeId] = p = new InnerPosition();
}
p.PositionPv += pos.PositionPv;
p.PositionPnl += pos.PositionPnl;
p.DailyPnl += pos.DailyPnl;
}
}
foreach (var pos in posList)
{
var td = TradeHelper2.Deserialize(pos.TradeJson);
if (td == null)
{
td = DbContext.trade.FirstOrDefault(n => n.id == pos.TradeId);
}
if (td == null)
{
continue;
}
if (td.TradeType == "结构化交易")
{
if (td.IsGroup == 1)
{
td.TradeType = "组合交易";
if (groupSumDic.TryGetValue(td.id, out var p))
{
pos.PositionPv = p.PositionPv;
pos.PositionPnl = p.PositionPnl;
}
pos.TradeAmount = td.Notional;
}
else
{
continue;
}
}
else if (td.IsGroup == 2)
{
continue;
}
extendService.SetTradeExtend(new[] { td }, false);
var un = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
if (un != null)
{
pos.TradeAmount /= un.CountRatio;
pos.CountRatio = un.CountRatio;
pos.Risk.DeltaInLots = un.ContractSize != 0 ? pos.Risk.Delta / un.ContractSize : pos.Risk.Delta;
}
if (td.TradeType == "收益互换")
{
var f = GetEodPayOffSwapPostionFields(td, td.StockEqvNotional, pos);
result.SwapPositions.Add(f);
f.SettlePrice = eodPriceProvider.GetPrice(f.GetUnderlyingCode.TrimToNull() ?? f.PayUnderlyingCode
, settlementType: PS.Config.Company == Configuration.CompanyEnum.屿 ? SettlementTypeEnum.SettlePrice : SettlementTypeEnum.ClosePrice);
}
else if (td.TradeType == "远期")
{
var f = GetEodForwardPostionFields(td, pos);
result.ForwardPositions.Add(f);
f.SettlePrice = eodPriceProvider.GetPrice(f.UnderlyingCode
, settlementType: PS.Config.Company == Configuration.CompanyEnum.屿 ? SettlementTypeEnum.SettlePrice : SettlementTypeEnum.ClosePrice);
}
else
{
var f = GetEodOptionPostionFields(td, pos);
result.OptionPositions.Add(f);
f.SettlePrice = eodPriceProvider.GetPrice(f.UnderlyingCode
, settlementType: PS.Config.Company == Configuration.CompanyEnum.屿 ? SettlementTypeEnum.SettlePrice : td.SettlementType);
}
}
return result;
}
#region--------
private EodOptionPositionField GetEodOptionPostionFields(trade td, InnerPosition pos)
{
var isMoneyness = td.IsMoneynessOption == "是";
var isUsePremiumRate = td.IsUsePremiumRate == true;
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
var volFormat = PS.Config.ErpElement.VolMoreAccurate ? "P4" : "P2";
var f = new EodOptionPositionField
{
TradeType = td.TradeType,
StructureType = td.TradeMultipleType,
TradeNumber = td.TradeNumber,
AssetBookName = td.AssetBookName,
TraderName = td.TraderName,
ClientName = td.ClientName,
ExerciseMode = td.ExerciseModeCn,
CallPut = pos.CallPut ?? td.CallPut,
TradeDate = td.TradeDate.OtcFormatDate(),
ExerciseDate = td.ExerciseDate.OtcFormatDate(),
SettlementDate = td.SettlementDate.OtcFormatDate(),
TradeSide = td.BuySell,
UnderlyingCode = td.UnderlyingCode,
UnderlyingName = underlying?.UnderlyingName,
InitSpotPrice = td.SpotPrice ?? 0,
Strike = td.Strike.OtcFormatUmPrice(isMoneyness),
IsMoneynessOption = isMoneyness ? "是" : "否",
Premium = isUsePremiumRate ? td.PremiumRate.OtcFormat(OtcFormatFlag.premiumRateP) : td.TradeSinglePrice.OtcFormat(OtcFormatFlag.tradeSinglePrice),
IsUsePremiumRate = isUsePremiumRate ? "是" : "否",
InitialMargin = td.InitialMargin ?? 0,
TradeAmount = (td.OriginalNotional ?? 0) / pos.CountRatio,
TradePrice = td.TradePrice ?? 0,
StockEqvNotional = td.OriginalStockEqvNotional ?? 0,
StockEqvNotionalReal = td.StockEqvNotionalReal,
IsAnnualized = td.IsAnnualized ? "是" : "否",
AnnualizeFactor = td.AnnualizeFactor?.ToString("F8"),
PrincipalRate = td.PrincipalRate.OtcFormatPercent(),
ParticipationRate = td.ParticipationRate.OtcFormatPercent(),
NoRiskRate = td.NoRiskRate.OtcFormatPercent(),
DividendRate = td.DividendRate.OtcFormatPercent(),
TradeOpenVolatility = td.TradeOpenVolatility?.ToString(volFormat),
TradeCloseVolatility = td.TradeCloseVolatility?.ToString(volFormat),
NumOfSmoothingDays = td.NumOfSmoothingDays ?? 0,
Comments = td.Comments,
PositionPv = pos.PositionPv,
PositionPnl = pos.PositionPnl,
PositionTradeAmount = pos.TradeAmount,
DailyPnl = pos.DailyPnl
};
if (pos.Risk != null)
{
var risk = pos.Risk;
f.Delta = risk.Delta;
f.DeltaInLots = risk.DeltaInLots;
f.DeltaCash = risk.DeltaCash;
f.Gamma = risk.Gamma;
f.GammaCash = risk.GammaCash;
f.Vega = risk.Vega;
f.VegaCash = risk.VegaCash;
f.Theta = risk.Theta;
f.Rho = risk.Rho;
f.PositionVol = risk.Vol.ToString(volFormat);
}
if (_context.TryGetClientInfo(td.ClientId, out var clientInfo))
{
f.ClientName = clientInfo.Name;
f.ClientNumber = clientInfo.Number;
}
switch (f.TradeType)
{
case "亚式期权":
SetAsianOption(td.trade_asian_option, f);
break;
case "障碍期权":
SetBarrierOption(td.trade_barrier_option, f, isMoneyness: isMoneyness, isUsePremiumRate: isUsePremiumRate);
break;
case "双鲨期权":
SetDbSharkOption(td.trade_double_sharkfin_option, f, isMoneyness: isMoneyness, isUsePremiumRate: isUsePremiumRate);
break;
case "二元期权":
SetBianryOption(td.trade_binary_option, f, isMoneyness: isMoneyness, isUsePremiumRate: isUsePremiumRate);
break;
case "区间累积期权":
SetRangeAccuralOption(td.trade_rangeaccrual, f, isMoneyness);
break;
case "气囊结构":
SetAirbagOption(td.trade_airbag, f, isMoneyness);
break;
case "收益增强结构":
if (td.trade_underlying_enhance != null)
{
f.CallPut = string.Empty;
f.AnnualizedEnhanceRate = td.trade_underlying_enhance.AnnualizedEnhanceRate.OtcFormatPercent(4);
}
break;
case "凤凰期权":
SetAutoCallOption(td.trade_autocall, f, isMoneyness);
break;
case "雪球期权":
SetSnowballOption(td.trade_snowball, f, isMoneyness);
break;
case "累计期权":
SetAccumulatorOption(td.trade_accumulator_option, f);
break;
case "自定义交易":
{
f.StructureTypeSpec = td.StructureType;
f.StructureIntroduction = td.StructureIntroduction;
f.ExtendInfo = td.ExtendInfo;
f.ObservationDates = td.trade_custom?.ObservationDates;
}
break;
case "组合交易":
{
f.ExtendInfo = td.ExtendInfo;
}
break;
}
if (td.TradeType == "凤凰期权" || td.TradeType == "雪球期权")
{
f.ExerciseMode = string.Empty;
td.MetaDic.TryGetValue(nameof(OtcOptionTradeFull.AnnualizeFactor2), out var metaValue);
f.AnnualizeFactor = metaValue;
}
else
{
td.MetaDic.TryGetValue(nameof(OtcOptionTradeFull.AnnualizeFactor), out var metaValue);
f.AnnualizeFactor = metaValue;
}
return f;
}
//累计期权
private static void SetAccumulatorOption(trade_accumulator_option option, EodOptionPositionField f)
{
if (option != null)
{
f.AccumulatorKOBarrier = option.KOBarrier.OtcFormatFlex(2, 2);
f.AccumulatorPayoffType = option.PayoffType;
if (option.PayoffType == "固定")
{
f.AccumulatorPayoffType = "固定(票息)";
f.AccumulatorCoupon = option.CouponPercent ? option.Coupon.OtcFormatPercent() : option.Coupon.OtcFormatFlex(2);
f.AccumulatorCouponDayCount = option.CouponDayCount;
f.AccumulatorIsAnnualizedCoupon = option.IsFixedCoupon ? "否" : "是";
}
f.AccumulatorMultiplier = ConsGlobal.CallPut.IsCall(f.CallPut) ? option.PutMultiplier : option.CallMultiplier;
f.AccumulatorEarlyTerminate = option.EarlyTerminate ? "是" : "否";
switch (option.SettlementMode)
{
case "现金期末":
f.AccumulatorSettlementMode = "现金结算(期末)";
break;
case "实物交割":
f.AccumulatorSettlementMode = "实物交割";
break;
default:
f.AccumulatorSettlementMode = "现金结算(当日)";
break;
}
f.AccumulatorAccumuType = option.AccumuType;
f.ObservationDates = option.KOObservationDates;
f.SettlementDate = option.KOObservationSettleDates;
}
}
//雪球期权
private static void SetSnowballOption(trade_snowball option, EodOptionPositionField f, bool isMoneyness)
{
if (option != null)
{
f.SnowballKOBarrier = option.KOBarrier.OtcFormatUmPrice(isMoneyness);
switch (option.KOPayoffType)
{
case KOPayoffTypeEnum.Rebate:
f.SnowballKOPayoffType = "票息补偿";
f.SnowballIsAnnualizedCoupon = option.IsFixedCoupon ? "否" : "是";
f.SnowballKORebate = option.KORebate.OtcFormatPercent();
f.SnowballAnnualizedPremiumRate = option.AnnualizedPremiumRate.OtcFormatPercent();
f.SnowballKOObservationSettleDates = option.KOObservationSettleDates;
break;
case KOPayoffTypeEnum.ToOption:
f.SnowballKOPayoffType = KOPayoffTypeEnumHelper.GetDesc(option.KOPayoffType, f.CallPut);
f.SnowballKOStrike1 = option.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness);
break;
case KOPayoffTypeEnum.ToSpreadOption:
f.SnowballKOPayoffType = KOPayoffTypeEnumHelper.GetDesc(option.KOPayoffType, f.CallPut);
f.SnowballKOStrike2 = option.SpreadStrikeAtKO.OtcFormatUmPrice(isMoneyness);
f.SnowballKOStrike1 = option.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness);
break;
default:
f.SnowballKOPayoffType = option.KOPayoffType.ToString();
break;
}
f.SnowballKORebateType = RebateTypeEnumHelper.GetDesc(option.KORebateType);
f.SnowballKIBarrier = option.KIBarrier.OtcFormatUmPrice(isMoneyness);
switch (option.KIPayoffType)
{
case KIPayoffTypeEnum.None:
f.SnowballKIPayoffType = "无";
break;
case KIPayoffTypeEnum.ToPutOption:
f.SnowballKIPayoffType = "敲入转看跌";
f.SnowballKIStrike1 = option.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
case KIPayoffTypeEnum.ToPutSpreadOption:
f.SnowballKIPayoffType = "敲入转熊市价差";
f.SnowballKIStrike2 = option.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness);
f.SnowballKIStrike1 = option.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
case KIPayoffTypeEnum.ToCallOption:
f.SnowballKIPayoffType = "敲入转看涨";
f.SnowballKIStrike1 = option.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
case KIPayoffTypeEnum.ToCallSpreadOption:
f.SnowballKIPayoffType = "敲入转牛市价差";
f.SnowballKIStrike2 = option.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness);
f.SnowballKIStrike1 = option.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
default:
f.SnowballKIPayoffType = option.KIPayoffType.ToString();
break;
}
f.SnowballNoKICoupon = option.Coupon.OtcFormatPercent();
var KOObservationDates = option.KOObservationDates ?? string.Empty;
var index = KOObservationDates.IndexOf(';');
f.KOObservationDates = index > 0 ? option.KOObservationDates.Substring(0, index) : KOObservationDates;
f.KIObservationDates = option.ObservationDates;
f.IsAnnualized = option.IsAnnualized2 ? "是" : "否";
f.SnowballKnockInOutStatus = option.KnockInOutStatusCn;
f.SnowballKnockInOutDate = option.KnockInOutDate.OtcFormatDate();
}
}
//凤凰期权
private static void SetAutoCallOption(trade_autocall option, EodOptionPositionField f, bool isMoneyness)
{
if (option != null)
{
f.AutocallIsAnnualizedCoupon = option.IsFixedCoupon ? "否" : "是";
f.AutocallCoupon = option.Coupon.OtcFormatPercent();
f.AutocallCouponBarrier = option.CouponBarrier.OtcFormatUmPrice(isMoneyness);
f.AutocallCouponPayType = option.CouponPayTypeDesc();
f.AutocallKOBarrier = option.KOBarrier.OtcFormatUmPrice(isMoneyness);
f.AutocallKIBarrier = option.KIBarrier.OtcFormatUmPrice(isMoneyness);
f.AutocallIncludeCouponAfterKI = option.IncludeCouponAfterKI ? "是" : "否";
f.AutocallKIPayoffType = option.KIPayoffTypeDesc();
f.AutocallKIStrike1 = option.SpreadStrike1.OtcFormatUmPrice(isMoneyness);
if (option.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption)
{
f.AutocallKIStrike2 = option.SpreadStrike.OtcFormatUmPrice(isMoneyness);
}
var KOObservationDates = option.KOObservationDates ?? string.Empty;
var index = KOObservationDates.IndexOf(';');
f.KOObservationDates = index > 0 ? option.KOObservationDates.Substring(0, index) : KOObservationDates;
f.KIObservationDates = option.ObservationDates;
f.IsAnnualized = option.IsAnnualized2 ? "是" : "否";
f.AutocallKnockInOutStatus = option.KnockInOutStatusCn;
f.AutocallKnockInOutDate = option.KnockInOutDate.OtcFormatDate();
}
}
//气囊结构
private static void SetAirbagOption(trade_airbag option, EodOptionPositionField f, bool isMoneyness)
{
if (option != null)
{
f.AirbagBarrier = option.Barrier.OtcFormatUmPrice(isMoneyness);
f.AirbagIsDiscrete = option.IsDiscreteMonitored ? "是" : "否";
f.AirbagKIParticipationRate = option.KIParticipationRate.OtcFormatPercent();
f.AirbagHasPayoffLimit = option.HasPayoffLimit ? "是" : "否";
f.AirbagHighStrike = option.HighStrike.OtcFormatUmPrice(isMoneyness);
f.CallPut = string.Empty;
}
}
//区间累积
private static void SetRangeAccuralOption(trade_rangeaccrual option, EodOptionPositionField f, bool isMoneyness)
{
if (option != null)
{
f.CallPut = string.Empty;
f.RangeAccrualLowerRange = option.LowerRange.OtcFormatUmPrice(isMoneyness);
f.RangeAccrualUpperRange = option.UpperRange.OtcFormatUmPrice(isMoneyness);
f.RangeAccrualBonusRate = option.BonusRate.OtcFormatPercent(4);
f.ObservationDates = option.ObservationDates;
}
}
//二元期权
private static void SetBianryOption(trade_binary_option option, EodOptionPositionField f, bool isMoneyness, bool isUsePremiumRate)
{
if (option != null)
{
f.BinaryPayoffType = option.PayoffType;
f.BinaryUpperBarrier = option.UpperBarrier.OtcFormatUmPrice(isMoneyness);
f.BinaryCashOrNothingAmount = OtcFormatHelper.FormatPremium(isUsePremiumRate, option.CashOrNothingAmountRate, option.CashOrNothingAmount);
f.BinaryCashOrNothingAmountHigh = OtcFormatHelper.FormatPremium(isUsePremiumRate, option.CashOrNothingAmountHighRate, option.CashOrNothingAmountHigh);
f.BinaryMonitorType = option.MonitorType;
f.BinaryRebateType = TradeHelper.GetRebateTypeCn(option.RebateType);
}
}
//双鲨期权
private static void SetDbSharkOption(trade_double_sharkfin_option option, EodOptionPositionField f, bool isMoneyness, bool isUsePremiumRate)
{
if (option != null)
{
f.DbSharkBarrierLow = option.BarrierLow.OtcFormatUmPrice(isMoneyness);
f.DbSharkBarrierHigh = option.BarrierHigh.OtcFormatUmPrice(isMoneyness);
f.DbSharkStrikeHigh = option.StrikeHigh.OtcFormatUmPrice(isMoneyness);
f.DbSharkCallParticipationRate = option.CallParticipationRate.OtcFormatPercent();
f.DbSharkPutParticipationRate = option.PutParticipationRate.OtcFormatPercent();
f.DbSharkRebate = OtcFormatHelper.FormatPremium(isUsePremiumRate, option.RebateRate, option.Rebate);
f.DbSharkRebateHigh = OtcFormatHelper.FormatPremium(isUsePremiumRate, option.RebateHighRate, option.RebateHigh);
f.DbSharkRebateType = TradeHelper.GetRebateTypeCn(option.RebateType);
f.DbSharkDiscrete = option.Discrete;
f.ObservationDates = option.ObservationDates;
f.DbsharkKnockInOutStatus = option.KnockInOutStatusCn;
f.DbsharkKnockInOutDate = option.KnockInOutDate.OtcFormatDate();
}
}
//障碍期权
private static void SetBarrierOption(trade_barrier_option option, EodOptionPositionField f, bool isMoneyness, bool isUsePremiumRate)
{
if (option != null)
{
f.BarrierType = option.BarrierType;
f.BarrierPrice = option.BarrierPrice.OtcFormatUmPrice(isMoneyness);
f.BarrierPriceHigh = option.UpperBarrierPrice.OtcFormatUmPrice(isMoneyness);
f.BarrierShift = option.BarrierShift ?? 0;
f.BarrierRebate = OtcFormatHelper.FormatPremium(isUsePremiumRate, option.RebateRate, option.Rebate);
f.BarrierRebateType = option.RebateTypeCn;
f.BarrierDiscrete = option.Discrete;
f.ObservationDates = option.ObservationDates;
f.BarrierKnockInOutDate = option.KnockInOutDate.OtcFormatDate();
f.BarrierKnockInOutStatus = option.KnockInOutStatusCn;
}
}
//亚式期权
private static void SetAsianOption(trade_asian_option option, EodOptionPositionField f)
{
if (option != null)
{
f.AsianAveragingPeriodStartDate = option.AveragingPeriodStartDate.OtcFormatDate();
f.AsianPayoffType = option.PayoffTypeCn;
f.AsianStrikeType = option.StrikeTypeCn;
f.AsianStrikeGearingFactor = option.StrikeGearingFactor.OtcFormatPercent();
}
}
#endregion
#region--------
private EodPayOffSwapPositionField GetEodPayOffSwapPostionFields(trade td, double positionStockEqvNotional, InnerPosition pos)
{
var swap = td.trade_swap ?? new trade_swap();
var f = new EodPayOffSwapPositionField
{
StructureType = ConsGlobal.TradeType.PayoffSwap,
TradeNumber = td.TradeNumber,
AssetBookName = td.AssetBookName,
TraderName = td.TraderName,
ClientName = td.ClientName,
TradeDate = td.TradeDate.OtcFormatDate(),
ExerciseDate = td.ExerciseDate.OtcFormatDate(),
Comments = td.Comments,
StockEqvNotional = td.OriginalStockEqvNotional ?? 0,
GetFixedProfit = swap.GetFixedProfit,
GetLongShort = swap.GetLongShort,
GetMarginRate = swap.GetMarginRate.OtcFormatFlex(minDecimals: 0, percent: true),
GetTradePrice = swap.GetTradePrice,
GetUnderlyingCode = swap.GetUnderlyingCode,
GetSpotPrice = swap.GetSpotPrice,
IsGetFloatingProfit = swap.IsGetFloatingProfit ? "是" : "否",
IsPayFloatingProfit = swap.IsPayFloatingProfit ? "是" : "否",
PayFixedProfit = swap.PayFixedProfit,
PayLongShort = swap.PayLongShort,
PayMarginRate = swap.PayMarginRate.OtcFormatPercent(),
PaySpotPrice = swap.PaySpotPrice,
PayTradePrice = swap.PayTradePrice,
PayUnderlyingCode = swap.PayUnderlyingCode,
PositionPnl = pos.PositionPnl,
PositionPv = pos.PositionPv,
PositionStockEqvNotional = positionStockEqvNotional,
DailyPnl = pos.DailyPnl
};
if (_context.TryGetClientInfo(td.ClientId, out var clientInfo))
{
f.ClientName = clientInfo.Name;
f.ClientNumber = clientInfo.Number;
}
return f;
}
#endregion
#region--------
private EodForwardPositionField GetEodForwardPostionFields(trade td, InnerPosition pos)
{
var forward = td.trade_forward ?? new trade_forward();
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
var f = new EodForwardPositionField
{
StructureType = td.StructureType.TrimToNull() ?? ConsGlobal.TradeType.Forward,
TradeNumber = td.TradeNumber,
AssetBookName = td.AssetBookName,
TraderName = td.TraderName,
ClientName = td.ClientName,
TradeDate = td.TradeDate.OtcFormatDate(),
ExerciseDate = td.ExerciseDate.OtcFormatDate(),
Comments = td.Comments,
InitSpotPrice = td.SpotPrice ?? 0,
AnnualMarginRate = forward.AnnualMarginRate.OtcFormatPercent(),
AnnualStoragePrice = forward.AnnualStoragePrice,
BasisGap = td.BasisGap,
BasisUnderlyingCode = td.BasisUnderlyingCode,
CallPut = ConsGlobal.CallPut.IsCall(td.CallPut) ? "多头" : "空头",
NoRiskRate = td.NoRiskRate.OtcFormatPercent(),
ObservationDates = forward.ObservationDates,
Strike = td.Strike ?? 0,
OpenFee = forward.OpenCommission,
TotalFee = td.TradePrice ?? 0,
TradeAmount = (td.OriginalNotional ?? 0) / pos.CountRatio,
TradeSide = td.BuySell,
UnderlyingCode = td.UnderlyingCode,
UnderlyingName = underlying?.UnderlyingName,
PositionPv = pos.PositionPv,
PositionPnl = pos.PositionPnl,
PositionTradeAmount = pos.TradeAmount,
DailyPnl = pos.DailyPnl,
CountRatio = pos.CountRatio
};
if (_context.TryGetClientInfo(td.ClientId, out var clientInfo))
{
f.ClientName = clientInfo.Name;
f.ClientNumber = clientInfo.Number;
}
return f;
}
#endregion
/// <summary>
/// 查询场内期权持仓列表
/// </summary>
public IEnumerable<EodExOptionPositionExportFields> SearchExOptionTradeListForExport(DateTime valueDate)
{
var IsPVRounded = PS.Config.IsPVRounded;
var umSource = DataCacheProvider.GetUnderlyingDataSource();
var exOptionSource = DataCacheProvider.GetExchangeListOptionDataSource();
var volFormat = PS.Config.ErpElement.VolMoreAccurate ? "P4" : "P2";
valueDate = valueDate.Date;
var query = from etp in DbContext.eod_trade_position
join etr in DbContext.eod_trade_risk on etp.TradeId equals etr.TradeId
where etp.ValueDate == valueDate && etr.ValueDate == valueDate
&& etp.TradeType == "场内期权"
select new
{
etp.UnderlyingCode,
etp.ExchangeOptionCode,
etp.Amount,
etp.PositionType,
PositionPv = IsPVRounded ? etp.RoundedPv : etp.Pv,
PositionPnl = IsPVRounded ? etp.RoundedPositionPnL : etp.PositionPnL,
etr.Vol
};
var list = new List<EodExOptionPositionExportFields>();
foreach (var item in query)
{
var exoption = exOptionSource.GetData(item.ExchangeOptionCode);
var f = new EodExOptionPositionExportFields
{
OptionCode = item.ExchangeOptionCode,
ExerciseMode = exoption?.ExerciseMode,
Strike = (exoption?.Strike)?.ToString("F4"),
UnderlyingCode = item.UnderlyingCode,
PositionType = item.PositionType,
PositionPnl = Convert.ToDouble(item.PositionPnl).OtcFormatMoney(),
PositionPv = Convert.ToDouble(item.PositionPv).OtcFormatMoney(),
PositionTradeAmount = item.Amount.OtcFormatNotional(),
PositionVol = item.Vol.ToString(volFormat)
};
list.Add(f);
}
return list;
}
public ClientSettleBalancesSumInfo GetClientSettleBalancesSumInfo(IEnumerable<ClientSettleBalance> clientSettleBalances)
{
ClientSettleBalancesSumInfo settleBalancesSumInfo = new ClientSettleBalancesSumInfo();
if (clientSettleBalances.Any())
{
settleBalancesSumInfo.WinLossSum = clientSettleBalances.Sum(a => a.WinLoss) * -1;
settleBalancesSumInfo.TdWinLossSum = clientSettleBalances.Sum(a => a.TdWinLoss) * -1;
settleBalancesSumInfo.PositionPnlSum = clientSettleBalances.Sum(a => a.PositionPnl) * -1;
}
return settleBalancesSumInfo;
}
class InnerPosition
{
public int TradeId { get; set; }
public int ParentTradeId { get; set; }
public string TradeJson { get; set; }
public string CallPut { get; set; }
public double TradeAmount { get; set; }
public double PositionPv { get; set; }
public double PositionPnl { get; set; }
public InnerPositionRisk Risk { get; set; }
public double CountRatio { get; set; } = 1;
/// <summary>
/// 当日盈亏
/// </summary>
public double DailyPnl { get; set; }
public int IsGroup { get; set; }
}
class InnerPositionRisk
{
public double Delta { get; set; }
public double DeltaInLots { get; set; }
public double Gamma { get; set; }
public double Theta { get; set; }
public double Rho { get; set; }
public double Vega { get; set; }
public double DeltaCash { get; set; }
public double GammaCash { get; set; }
public double VegaCash { get; set; }
public double Vol { get; set; }
}
}
}
@@ -0,0 +1,915 @@
namespace YLErp.Modules.EodModule.QueryModule
{
/// <summary>
/// 日终清算--请求参数
/// </summary>
public class EodSettleInfoRequest
{
/// <summary>
/// 清算日期
/// </summary>
public DateTime ValueDate { get; set; }
/// <summary>
/// 返回结果是否采用精简模式
/// </summary>
public bool CompactResult { get; set; }
}
/// <summary>
/// 日终清算--持仓列表结果
/// </summary>
public class EodTradePositionResult
{
public List<EodOptionPositionField> OptionPositions { get; set; }
public List<EodForwardPositionField> ForwardPositions { get; set; }
public List<EodPayOffSwapPositionField> SwapPositions { get; set; }
}
/// <summary>
/// 持仓记录
/// </summary>
public abstract class EodPositionField
{
/// <summary>
/// 交易编号
/// </summary>
public string TradeNumber { get; set; }
/// <summary>
/// 簿记账户
/// </summary>
public string AssetBookName { get; set; }
/// <summary>
/// 交易员
/// </summary>
public string TraderName { get; set; }
/// <summary>
/// 交易对手方
/// </summary>
public string ClientName { get; set; }
/// <summary>
/// 交易对手方编号
/// </summary>
public string ClientNumber { get; set; }
/// <summary>
/// 成交日期
/// </summary>
public string TradeDate { get; set; }
/// <summary>
/// 到期日期
/// </summary>
public string ExerciseDate { get; set; }
/// <summary>
/// 交易备注
/// </summary>
public string Comments { get; set; }
/// <summary>
/// 日终结算价格
/// </summary>
public double SettlePrice { get; set; }
}
/// <summary>
/// (日终清算)场外期权持仓数据字段
/// </summary>
public class EodOptionPositionField : EodPositionField
{
#region--------
/// <summary>
/// 交易类型
/// </summary>
public string TradeType { get; set; }
/// <summary>
/// 结构类型
/// </summary>
public string StructureType { get; set; }
/// <summary>
/// 行权方式
/// </summary>
public string ExerciseMode { get; set; }
/// <summary>
/// 看涨看跌
/// </summary>
public string CallPut { get; set; }
/// <summary>
/// 结算日期
/// </summary>
public string SettlementDate { get; set; }
/// <summary>
///
/// </summary>
public string TradeSide { get; set; }
/// <summary>
///
/// </summary>
public string UnderlyingCode { get; set; }
/// <summary>
///
/// </summary>
public string UnderlyingName { get; set; }
/// <summary>
/// 期初标的价格
/// </summary>
public double InitSpotPrice { get; set; }
public string Strike { get; set; }
public string IsMoneynessOption { get; set; }
public string Premium { get; set; }
public string IsUsePremiumRate { get; set; }
/// <summary>
/// 初始预付金
/// </summary>
public double InitialMargin { get; set; }
/// <summary>
/// 有效成交数量
/// </summary>
public double TradeAmount { get; set; }
/// <summary>
/// 成交金额
/// </summary>
public double TradePrice { get; set; }
/// <summary>
/// 名义本金(成交)
/// </summary>
public double StockEqvNotional { get; set; }
/// <summary>
/// 实际名义本金(成交)
/// </summary>
public double StockEqvNotionalReal { get; set; }
public string IsAnnualized { get; set; }
public string AnnualizeFactor { get; set; }
public string PrincipalRate { get; set; }
public string ParticipationRate { get; set; }
public string NoRiskRate { get; set; }
public string DividendRate { get; set; }
public string TradeOpenVolatility { get; set; }
public string TradeCloseVolatility { get; set; }
/// <summary>
/// 平滑过渡天数
/// </summary>
public int NumOfSmoothingDays { get; set; }
#endregion
#region--------
/// <summary>
/// 均价起算日 格式:yyyy-MM-dd
/// </summary>
public string AsianAveragingPeriodStartDate { get; set; }
/// <summary>
/// 均价计算方式(算术平均|几何平均|算术平均(离散)|增强算术平均)
/// </summary>
public string AsianPayoffType { get; set; }
/// <summary>
/// 行权价类型(固定行权价|浮动行权价|分段式)
/// </summary>
public string AsianStrikeType { get; set; }
/// <summary>
/// 杠杆率(百分数)
/// </summary>
public string AsianStrikeGearingFactor { get; set; }
#endregion
#region--------
/// <summary>
/// 障碍类型(上升敲入|上升敲出|下降敲入|下降敲出|双障碍敲入|双障碍敲出)
/// </summary>
public string BarrierType { get; set; }
/// <summary>
/// 障碍价格 IsMoneynessOption等于‘是’时为百分数,否则为绝对数值
/// </summary>
public string BarrierPrice { get; set; }
/// <summary>
/// 高障碍价格 IsMoneynessOption等于‘是’时为百分数,否则为绝对数值
/// </summary>
public string BarrierPriceHigh { get; set; }
/// <summary>
/// 障碍偏移
/// </summary>
public double? BarrierShift { get; set; }
/// <summary>
/// 补偿金额 IsUsePremiumRate等于‘是’时为百分数,否则为绝对数值
/// </summary>
public string BarrierRebate { get; set; }
/// <summary>
/// 补偿支付方式(立即|递延)
/// </summary>
public string BarrierRebateType { get; set; }
/// <summary>
/// 观察方式(离散|连续)
/// </summary>
public string BarrierDiscrete { get; set; }
/// <summary>
/// 敲入敲出状态(观察中|已敲入|已敲出)
/// </summary>
public string BarrierKnockInOutStatus { get; set; }
/// <summary>
/// 敲入敲出日期(格式:yyyy-MM-dd)
/// </summary>
public string BarrierKnockInOutDate { get; set; }
#endregion
#region--------
/// <summary>
/// 低障碍价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string DbSharkBarrierLow { get; set; }
/// <summary>
/// 高障碍价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string DbSharkBarrierHigh { get; set; }
/// <summary>
/// 高行权价(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string DbSharkStrikeHigh { get; set; }
/// <summary>
/// 高参与率(百分数)
/// </summary>
public string DbSharkCallParticipationRate { get; set; }
/// <summary>
/// 低参与率(百分数)
/// </summary>
public string DbSharkPutParticipationRate { get; set; }
/// <summary>
/// 补偿金额(IsUsePremiumRate等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string DbSharkRebate { get; set; }
/// <summary>
/// 高障碍补偿金额(IsUsePremiumRate等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string DbSharkRebateHigh { get; set; }
/// <summary>
/// 补偿支付方式(立即|递延)
/// </summary>
public string DbSharkRebateType { get; set; }
/// <summary>
/// 观察方式(离散|连续)
/// </summary>
public string DbSharkDiscrete { get; set; }
/// <summary>
/// 敲入敲出状态 观察中|已敲入|已敲出
/// </summary>
public string DbsharkKnockInOutStatus { get; set; }
/// <summary>
/// 敲入敲出日期 格式:yyyy-MM-dd
/// </summary>
public string DbsharkKnockInOutDate { get; set; }
#endregion
#region--------
/// <summary>
/// 二元类型 "欧式期权: CashOrNothing|AssetOrNothing
/// 美式期权: UpOneTouch|DownOneTouch|UpNoTouch|DownNoTouch|DoubleOneTouch|DoubleNoTouch"
/// </summary>
public string BinaryPayoffType { get; set; }
/// <summary>
/// 高障碍价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string BinaryUpperBarrier { get; set; }
/// <summary>
/// 补偿金额(IsUsePremiumRate等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string BinaryCashOrNothingAmount { get; set; }
/// <summary>
/// 高障碍补偿金额(IsUsePremiumRate等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string BinaryCashOrNothingAmountHigh { get; set; }
/// <summary>
/// 观察方式(离散|连续)
/// </summary>
public string BinaryMonitorType { get; set; }
/// <summary>
/// 补偿支付方式(立即|递延)
/// </summary>
public string BinaryRebateType { get; set; }
#endregion
#region--------
/// <summary>
/// 区间下限(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string RangeAccrualLowerRange { get; set; }
/// <summary>
/// 区间上限(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string RangeAccrualUpperRange { get; set; }
/// <summary>
/// 区间收益(百分数)
/// </summary>
public string RangeAccrualBonusRate { get; set; }
#endregion
#region--------
/// <summary>
/// 障碍价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string AirbagBarrier { get; set; }
/// <summary>
/// 是否离散观察(是|否)
/// </summary>
public string AirbagIsDiscrete { get; set; }
/// <summary>
/// 敲入参与率(百分数)
/// </summary>
public string AirbagKIParticipationRate { get; set; }
/// <summary>
/// 收益封顶(是|否)
/// </summary>
public string AirbagHasPayoffLimit { get; set; }
/// <summary>
/// 收益封顶价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string AirbagHighStrike { get; set; }
//收益增强结构
/// <summary>
/// 年化增强收益(百分数)
/// </summary>
public string AnnualizedEnhanceRate { get; set; }
#endregion
#region--------
/// <summary>
/// 票息年化(是|否)
/// </summary>
public string AutocallIsAnnualizedCoupon { get; set; }
/// <summary>
/// 票息率(百分数)
/// </summary>
public string AutocallCoupon { get; set; }
/// <summary>
/// 票息障碍价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string AutocallCouponBarrier { get; set; }
/// <summary>
/// 票息结算方式(产生时支付|敲出时支付|期末支付)
/// </summary>
public string AutocallCouponPayType { get; set; }
/// <summary>
/// 敲出障碍价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string AutocallKOBarrier { get; set; }
/// <summary>
/// 敲入障碍价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string AutocallKIBarrier { get; set; }
/// <summary>
/// 敲入到期是否支付票息(是|否)
/// </summary>
public string AutocallIncludeCouponAfterKI { get; set; }
/// <summary>
/// 敲入到期支付类别(无|敲入转期权|敲入转价差期权)
/// </summary>
public string AutocallKIPayoffType { get; set; }
/// <summary>
/// 敲入行权价1(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string AutocallKIStrike1 { get; set; }
/// <summary>
/// 敲入行权价2(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string AutocallKIStrike2 { get; set; }
/// <summary>
/// 敲入敲出状态 观察中|已敲入|已敲出
/// </summary>
public string AutocallKnockInOutStatus { get; set; }
/// <summary>
/// 敲入敲出日期 格式:yyyy-MM-dd
/// </summary>
public string AutocallKnockInOutDate { get; set; }
#endregion
#region--------
/// <summary>
/// 敲出障碍价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string SnowballKOBarrier { get; set; }
/// <summary>
/// 敲出赔付类别(票息补偿|敲出转期权|敲出转价差期权)
/// </summary>
public string SnowballKOPayoffType { get; set; }
/// <summary>
/// 票息年化(是|否, SnowballKOPayoffType等于‘票息补偿’时有值)
/// </summary>
public string SnowballIsAnnualizedCoupon { get; set; }
/// <summary>
/// 票息率(百分数, SnowballKOPayoffType等于‘票息补偿’时有值)
/// </summary>
public string SnowballKORebate { get; set; }
/// <summary>
/// 年化期权费率(百分数, SnowballKOPayoffType等于‘票息补偿’时有值)
/// </summary>
public string SnowballAnnualizedPremiumRate { get; set; }
/// <summary>
/// 票息支付日期(以逗号分隔的日期序列)
/// </summary>
public string SnowballKOObservationSettleDates { get; set; }
/// <summary>
/// 敲出行权价1(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值, SnowballKOPayoffType等于‘票息补偿’或‘敲出转价差期权’时有值)
/// </summary>
public string SnowballKOStrike1 { get; set; }
/// <summary>
/// 敲出行权价2(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值, SnowballKOPayoffType等于‘敲出转价差期权’时有值)
/// </summary>
public string SnowballKOStrike2 { get; set; }
/// <summary>
/// 敲出支付方式(立即|期末)
/// </summary>
public string SnowballKORebateType { get; set; }
/// <summary>
/// 敲入障碍价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string SnowballKIBarrier { get; set; }
/// <summary>
/// 敲入到期支付类别(无|敲入转期权|敲入转价差期权)
/// </summary>
public string SnowballKIPayoffType { get; set; }
/// <summary>
/// 敲入行权价1(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值, SnowballKIPayoffType等于‘票息补偿’或‘敲出转价差期权’时有值)
/// </summary>
public string SnowballKIStrike1 { get; set; }
/// <summary>
/// 敲入行权价2(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值, SnowballKIPayoffType等于‘敲出转价差期权’时有值)
/// </summary>
public string SnowballKIStrike2 { get; set; }
/// <summary>
/// 非敲入到期支付票息(百分数)
/// </summary>
public string SnowballNoKICoupon { get; set; }
/// <summary>
/// 敲入敲出状态 观察中|已敲入|已敲出
/// </summary>
public string SnowballKnockInOutStatus { get; set; }
/// <summary>
/// 敲入敲出日期 格式:yyyy-MM-dd
/// </summary>
public string SnowballKnockInOutDate { get; set; }
#endregion
#region--------
/// <summary>
/// 自定义结构类型
/// </summary>
public string StructureTypeSpec { get; set; }
/// <summary>
/// 自定义结构说明
/// </summary>
public string StructureIntroduction { get; set; }
/// <summary>
/// 交易扩展信息
/// </summary>
public string ExtendInfo { get; set; }
#endregion
#region--------
/// <summary>
/// 敲出障碍价格(IsMoneynessOption等于‘是’时为百分数,否则为绝对数值)
/// </summary>
public string AccumulatorKOBarrier { get; set; }
/// <summary>
/// 上端收益类型 浮动|固定
/// </summary>
public string AccumulatorPayoffType { get; set; }
/// <summary>
/// 票息 带'%'后缀的为百分比格式的票息率方式,否则为单份票息金额方式,'上端收益类型'为‘票息’时适用
/// </summary>
public string AccumulatorCoupon { get; set; }
/// <summary>
/// 票息年化 是|否,为'否'时票息年化,'上端收益类型'为‘票息’时适用
/// </summary>
public string AccumulatorIsAnnualizedCoupon { get; set; }
/// <summary>
/// 票息日历规则,为空时则默认为Act365
/// </summary>
public string AccumulatorCouponDayCount { get; set; }
/// <summary>
/// 杠杆倍数
/// </summary>
public double? AccumulatorMultiplier { get; set; }
/// <summary>
/// 敲出是否终止 是|否
/// </summary>
public string AccumulatorEarlyTerminate { get; set; }
/// <summary>
/// 结算方式 现金结算(当日)|现金结算(期末)|实物交割
/// </summary>
public string AccumulatorSettlementMode { get; set; }
/// <summary>
/// 累计类型 子弹|空值
/// </summary>
public string AccumulatorAccumuType { get; set; }
#endregion
#region--------
/// <summary>
/// 观察频率 以逗号分隔的日期序列,适用于:障碍期权,
/// </summary>
public string ObservationDates { get; set; }
/// <summary>
/// 敲出观察频率 以逗号分隔的日期序列,适用于:障碍期权,
/// </summary>
public string KOObservationDates { get; set; }
/// <summary>
/// 敲入观察频率 以逗号分隔的日期序列,适用于:障碍期权,
/// </summary>
public string KIObservationDates { get; set; }
#endregion
#region--------
/// <summary>
/// 持仓数量
/// </summary>
public double PositionTradeAmount { get; set; }
/// <summary>
/// 持仓市值
/// </summary>
public double PositionPv { get; set; }
/// <summary>
/// 持仓盈亏
/// </summary>
public double PositionPnl { get; set; }
/// <summary>
/// 持仓波动率(百分数)
/// </summary>
public string PositionVol { get; set; }
/// <summary>
/// 当日盈亏
/// </summary>
public double DailyPnl { get; set; }
#endregion
#region--------
/// <summary>
/// 持仓Delta
/// </summary>
public double Delta { get; set; }
public double DeltaInLots { get; set; }
/// <summary>
/// 持仓Gamma
/// </summary>
public double Gamma { get; set; }
/// <summary>
/// 持仓Vega
/// </summary>
public double Vega { get; set; }
/// <summary>
/// 持仓Theta
/// </summary>
public double Theta { get; set; }
/// <summary>
/// 持仓Rho
/// </summary>
public double Rho { get; set; }
/// <summary>
///
/// </summary>
public double DeltaCash { get; set; }
/// <summary>
///
/// </summary>
public double GammaCash { get; set; }
/// <summary>
///
/// </summary>
public double VegaCash { get; set; }
#endregion
}
/// <summary>
/// (日终清算)场内期权持仓数据字段
/// </summary>
public class EodExOptionPositionFields
{
public string OptionCode { get; set; }
public string UnderlyingCode { get; set; }
public string ExerciseMode { get; set; }
public string Strike { get; set; }
public string PositionType { get; set; }
public string PositionTradeAmount { get; set; }
public string PositionPv { get; set; }
public string PositionPnl { get; set; }
public string PositionVol { get; set; }
}
/// <summary>
/// (日终清算)收益互换持仓数据字段
/// </summary>
public class EodPayOffSwapPositionField : EodPositionField
{
/// <summary>
/// 结构类型
/// </summary>
public string StructureType { get; set; }
/// <summary>
/// 名义本金
/// </summary>
public double StockEqvNotional { get; set; }
/// <summary>
/// [收取]浮动收益(是|否)
/// </summary>
public string IsGetFloatingProfit { get; set; }
/// <summary>
/// [收取]标的代码
/// </summary>
public string GetUnderlyingCode { get; set; }
/// <summary>
/// [收取]多头空头(多头|空头)
/// </summary>
public string GetLongShort { get; set; }
/// <summary>
/// [收取]标的期初价格
/// </summary>
public double? GetSpotPrice { get; set; }
/// <summary>
/// [收取]交易费用
/// </summary>
public double? GetTradePrice { get; set; }
/// <summary>
/// [收取]初始预付金率(百分数)
/// </summary>
public string GetMarginRate { get; set; }
/// <summary>
/// [收取]固定收益
/// </summary>
public double? GetFixedProfit { get; set; }
/// <summary>
/// [支付]浮动收益(是|否)
/// </summary>
public string IsPayFloatingProfit { get; set; }
/// <summary>
/// [支付]标的代码
/// </summary>
public string PayUnderlyingCode { get; set; }
/// <summary>
/// [支付]多头空头(多头|空头)
/// </summary>
public string PayLongShort { get; set; }
/// <summary>
/// [支付]标的期初价格
/// </summary>
public double? PaySpotPrice { get; set; }
/// <summary>
/// [支付]交易费用
/// </summary>
public double? PayTradePrice { get; set; }
/// <summary>
/// [支付]固定收益
/// </summary>
public double? PayFixedProfit { get; set; }
/// <summary>
/// [支付]初始预付金率(百分数)
/// </summary>
public string PayMarginRate { get; set; }
//持仓信息
/// <summary>
/// 持仓名义本金
/// </summary>
public double PositionStockEqvNotional { get; set; }
/// <summary>
/// 持仓市值
/// </summary>
public double PositionPv { get; set; }
/// <summary>
/// 持仓盈亏
/// </summary>
public double PositionPnl { get; set; }
/// <summary>
/// 当日盈亏
/// </summary>
public double DailyPnl { get; set; }
}
/// <summary>
/// (日终清算)远期持仓数据字段
/// </summary>
public class EodForwardPositionField : EodPositionField
{
/// <summary>
/// 结构类型
/// </summary>
public string StructureType { get; set; }
/// <summary>
/// 标的代码
/// </summary>
public string UnderlyingCode { get; set; }
/// <summary>
/// 标的名称
/// </summary>
public string UnderlyingName { get; set; }
/// <summary>
/// 挂钩标的
/// </summary>
public string BasisUnderlyingCode { get; set; }
/// <summary>
/// 基差
/// </summary>
public double? BasisGap { get; set; }
/// <summary>
/// 交易方向(买入|卖出)
/// </summary>
public string TradeSide { get; set; }
/// <summary>
/// 多头空头(多头|空头)
/// </summary>
public string CallPut { get; set; }
/// <summary>
/// 成交数量
/// </summary>
public double TradeAmount { get; set; }
/// <summary>
/// 交割价格
/// </summary>
public double Strike { get; set; }
/// <summary>
/// 期初标的价格
/// </summary>
public double InitSpotPrice { get; set; }
/// <summary>
/// 开仓费用(每手单价)
/// </summary>
public double OpenFee { get; set; }
/// <summary>
/// 开仓总费用
/// </summary>
public double TotalFee { get; set; }
/// <summary>
/// 年化预付金成本率(百分数)
/// </summary>
public string AnnualMarginRate { get; set; }
/// <summary>
/// 年化仓储成本(单价)
/// </summary>
public double AnnualStoragePrice { get; set; }
/// <summary>
/// 无风险利率(百分数)
/// </summary>
public string NoRiskRate { get; set; }
/// <summary>
/// 均价结算设置
/// </summary>
public string ObservationDates { get; set; }
/// <summary>
/// 持仓数量
/// </summary>
public double PositionTradeAmount { get; set; }
/// <summary>
/// 持仓市值
/// </summary>
public double PositionPv { get; set; }
/// <summary>
/// 持仓盈亏
/// </summary>
public double PositionPnl { get; set; }
/// <summary>
/// 当日盈亏
/// </summary>
public double DailyPnl { get; set; }
public double CountRatio { get; set; }
}
public class ClientSettleBalancesSumInfo
{
public double WinLossSum { get; set; }
public double TdWinLossSum { get; set; }
public double PositionPnlSum { get; set; }
}
}
@@ -0,0 +1,854 @@
using BaseOUDAL;
using CsvHelper;
using CsvHelper.Configuration;
using ICSharpCode.SharpZipLib.Zip;
using System.Data;
using YLErp.Commons;
using YLErp.DBModels.Helpers;
using YLErp.Modules.ClientModule;
using YLErp.Modules.TradeModule;
using YLErp.Office.ExcelModule;
using YLErp.QdpModule;
namespace YLErp.Modules.EodModule.QueryModule
{
/// <summary>
/// 日终持仓导出服务
/// 暂时用于兴证数据接口导出
/// </summary>
public class EodTradePositionExportService : YLBaseService
{
public EodTradePositionExportService(OptUserInfo optUser) : base(optUser)
{
}
/// <summary>
/// 查询场外期权持仓列表
/// </summary>
public void SearchOptionTradeListForExport(DateTime valueDate
, out List<EodOptionPositionExportFields> listOption
, out List<EodPayOffSwapPositionExportFields> listSwap)
{
listSwap = null;
listOption = null;
var IsPVRounded = PS.Config.IsPVRounded;
valueDate = valueDate.Date;
var query = from et in DbContext.eod_trade
join etp in DbContext.eod_trade_position on et.TradeId equals etp.TradeId
join etr in DbContext.eod_trade_risk on et.TradeId equals etr.TradeId
where et.ValueDate == valueDate && etp.ValueDate == valueDate && etr.ValueDate == valueDate
&& et.TradeId > 0 && etp.TradeId > 0 && etr.TradeId > 0
&& et.TradeType != "结构化交易" && et.ClientId > 0
select new
{
et.TradeId,
et.TradeJson,
etp.Amount,
etp.Pv,
PositionPv = IsPVRounded ? etp.RoundedPv : etp.Pv,
PositionPnl = IsPVRounded ? etp.RoundedPositionPnL : etp.PositionPnL,
etr.Vol
};
//因为query还在读取中,所以不要用同一个dbcontext
var extendService = new TradeExtendService(OptUser);
foreach (var item in query)
{
var td = TradeHelper2.Deserialize(item.TradeJson);
if (td == null)
{
td = DbContext.trade.Find(item.TradeId);
}
if (td == null)
{
continue;
}
extendService.SetTradeExtend(new[] { td }, true);
if (td.TradeType == "收益互换")
{
var f = GetEodPayOffSwapPostionFields(td, item.Amount, item.PositionPnl, item.PositionPv);
if (listSwap == null)
{
listSwap = new List<EodPayOffSwapPositionExportFields>();
}
listSwap.Add(f);
}
else if (td.TradeType == "远期")
{
}
else
{
var f = GetEodOptionPostionFields(td, item.Amount, item.PositionPnl, item.PositionPv, item.Vol);
if (listOption == null)
{
listOption = new List<EodOptionPositionExportFields>();
}
listOption.Add(f);
}
}
}
//场外期权
private EodOptionPositionExportFields GetEodOptionPostionFields(trade td, double PositionTradeAmount, double PositionPnl, double PositionPv, double PositionVol)
{
var isMoneyness = td.IsMoneynessOption == "是";
var isPremiumRate = td.IsUsePremiumRate == true;
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
var volFormat = PS.Config.ErpElement.VolMoreAccurate ? "P2" : "P4";
var f = new EodOptionPositionExportFields
{
TradeNumber = td.TradeNumber,
AssetBookName = td.AssetBookName,
TraderName = td.TraderName,
ClientName = td.ClientName,
StructureType = td.TradeType,
ExerciseMode = td.ExerciseModeCn,
CallPut = td.CallPut,
TradeDate = td.TradeDate.OtcFormatDate(),
ExerciseDate = td.ExerciseDate.OtcFormatDate(),
SettlementDate = td.SettlementDate.OtcFormatDate(),
TradeSide = td.BuySell,
UnderlyingCode = td.UnderlyingCode,
UnderlyingName = underlying?.UnderlyingName,
InitSpotPrice = td.SpotPrice.OtcFormatUmPrice(),
Strike = td.Strike.OtcFormatUmPrice(isMoneyness),
IsMoneynessOption = isMoneyness ? "是" : "否",
Premium = isPremiumRate ? td.PremiumRate.OtcFormat(OtcFormatFlag.premiumRateP) : td.TradeSinglePrice.OtcFormat(OtcFormatFlag.tradeSinglePrice),
IsUsePremiumRate = isPremiumRate ? "是" : "否",
InitialMargin = td.InitialMargin.OtcFormatMoney(),
TradeAmount = td.OriginalNotional.OtcFormatNotional(),
TradePrice = td.TradePrice.OtcFormatMoney(),
StockEqvNotional = td.OriginalStockEqvNotional.OtcFormat(OtcFormatFlag.StockEqvNotional),
StockEqvNotionalReal = td.StockEqvNotionalReal.OtcFormat(OtcFormatFlag.StockEqvNotional),
IsAnnualized = td.IsAnnualized ? "是" : "否",
AnnualizeFactor = td.AnnualizeFactor?.ToString("F8"),
PrincipalRate = td.PrincipalRate.OtcFormatPercent(),
ParticipationRate = td.ParticipationRate.OtcFormatPercent(),
NoRiskRate = td.NoRiskRate.OtcFormatPercent(),
DividendRate = td.DividendRate.OtcFormatPercent(),
TradeOpenVolatility = td.TradeOpenVolatility?.ToString(volFormat),
TradeCloseVolatility = td.TradeCloseVolatility?.ToString(volFormat),
NumOfSmoothingDays = td.NumOfSmoothingDays?.ToString(),
Comments = td.Comments,
PositionPnl = Convert.ToDouble(PositionPnl).OtcFormatMoney(),
PositionPv = Convert.ToDouble(PositionPv).OtcFormatMoney(),
PositionTradeAmount = PositionTradeAmount.OtcFormatNotional(),
PositionVol = PositionVol.ToString(volFormat)
};
f.ClientNumber = ClientDataQueryService.GetClient(td.ClientId)?.Number;
switch (f.StructureType)
{
case "亚式期权":
if (td.trade_asian_option != null)
{
var ext = td.trade_asian_option;
f.AsianAveragingPeriodStartDate = ext.AveragingPeriodStartDate.OtcFormatDate();
f.AsianPayoffType = ext.PayoffTypeCn;
f.AsianStrikeType = ext.StrikeTypeCn;
f.AsianStrikeGearingFactor = ext.StrikeGearingFactor.OtcFormatPercent();
}
break;
case "障碍期权":
if (td.trade_barrier_option != null)
{
var ext = td.trade_barrier_option;
f.BarrierType = ext.BarrierType;
f.BarrierPrice = ext.BarrierPrice.OtcFormatUmPrice(isMoneyness);
f.BarrierPriceHigh = ext.UpperBarrierPrice.OtcFormatUmPrice(isMoneyness);
f.BarrierShift = ext.BarrierShift.OtcFormatUmPrice();
f.BarrierRebate = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateRate, ext.Rebate);
f.BarrierRebateType = ext.RebateTypeCn;
f.BarrierDiscrete = ext.Discrete;
f.BarrierKnockInOutStatus = ext.KnockInOutStatus;
f.BarrierKnockInOutDate = ext.KnockInOutDate.OtcFormatDate();
}
break;
case "双鲨期权":
if (td.trade_double_sharkfin_option != null)
{
var ext = td.trade_double_sharkfin_option;
f.DbsharkBarrierLow = ext.BarrierLow.OtcFormatUmPrice(isMoneyness);
f.DbsharkBarrierHigh = ext.BarrierHigh.OtcFormatUmPrice(isMoneyness);
f.DbsharkStrikeHigh = ext.StrikeHigh.OtcFormatUmPrice(isMoneyness);
f.DbsharkCallParticipationRate = ext.CallParticipationRate.OtcFormatPercent();
f.DbsharkPutParticipationRate = ext.PutParticipationRate.OtcFormatPercent();
f.DbsharkRebate = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateRate, ext.Rebate);
f.DbsharkRebateHigh = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateHighRate, ext.RebateHigh);
f.DbsharkRebateType = TradeHelper.GetRebateTypeCn(ext.RebateType);
f.DbsharkDiscrete = ext.Discrete;
}
break;
case "二元期权":
if (td.trade_binary_option != null)
{
var ext = td.trade_binary_option;
f.BinaryPayoffType = ext.PayoffType;
f.BinaryUpperBarrier = ext.UpperBarrier.OtcFormatUmPrice(isMoneyness);
f.BinaryCashOrNothingAmount = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.CashOrNothingAmountRate, ext.CashOrNothingAmount);
f.BinaryCashOrNothingAmountHigh = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.CashOrNothingAmountHighRate, ext.CashOrNothingAmountHigh);
f.BinaryMonitorType = ext.MonitorType;
f.BinaryRebateType = TradeHelper.GetRebateTypeCn(ext.RebateType);
}
break;
case "区间累积期权":
if (td.trade_rangeaccrual != null)
{
var ext = td.trade_rangeaccrual;
f.RangeAccrualLowerRange = ext.LowerRange.OtcFormatUmPrice(isMoneyness);
f.RangeAccrualUpperRange = ext.UpperRange.OtcFormatUmPrice(isMoneyness);
f.RangeAccrualBonusRate = ext.BonusRate.OtcFormatPercent(4);
f.CallPut = string.Empty;
}
break;
case "气囊结构":
if (td.trade_airbag != null)
{
var ext = td.trade_airbag;
f.AirbagBarrier = ext.Barrier.OtcFormatUmPrice(isMoneyness);
f.AirbagIsDiscrete = ext.IsDiscreteMonitored ? "是" : "否";
f.AirbagKIParticipationRate = ext.KIParticipationRate.OtcFormatPercent();
f.AirbagHasPayoffLimit = ext.HasPayoffLimit ? "是" : "否";
f.AirbagHighStrike = ext.HighStrike.OtcFormatUmPrice(isMoneyness);
f.CallPut = string.Empty;
}
break;
case "收益增强结构":
if (td.trade_underlying_enhance != null)
{
f.CallPut = string.Empty;
f.AnnualizedEnhanceRate = td.trade_underlying_enhance.AnnualizedEnhanceRate.OtcFormatPercent(4);
}
break;
case "凤凰期权":
if (td.trade_autocall != null)
{
var ext = td.trade_autocall;
f.AutocallIsFixedCoupon = ext.IsFixedCoupon ? "否" : "是";
f.AutocallCoupon = ext.Coupon.OtcFormatPercent();
f.AutocallCouponBarrier = ext.CouponBarrier.OtcFormatUmPrice(isMoneyness);
f.AutocallCouponPayType = ext.CouponPayTypeDesc();
f.AutocallKOBarrier = ext.KOBarrier.OtcFormatUmPrice(isMoneyness);
f.AutocallKIBarrier = ext.KIBarrier.OtcFormatUmPrice(isMoneyness);
f.AutocallIncludeCouponAfterKI = ext.IncludeCouponAfterKI ? "是" : "否";
f.AutocallKIPayoffType = ext.KIPayoffTypeDesc();
f.AutocallKIStrike1 = ext.SpreadStrike1.OtcFormatUmPrice(isMoneyness);
if (ext.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption)
{
f.AutocallKIStrike2 = ext.SpreadStrike.OtcFormatUmPrice(isMoneyness);
}
var KOObservationDates = ext.KOObservationDates ?? string.Empty;
var index = KOObservationDates.IndexOf(';');
f.KOObservationDates = index > 0 ? ext.KOObservationDates.Substring(0, index) : KOObservationDates;
f.KIObservationDates = ext.ObservationDates;
f.IsAnnualized = ext.IsAnnualized2 ? "是" : "否";
}
break;
case "雪球期权":
if (td.trade_snowball != null)
{
var ext = td.trade_snowball;
f.SnowballKOBarrier = ext.KOBarrier.OtcFormatUmPrice(isMoneyness);
switch (ext.KOPayoffType)
{
case KOPayoffTypeEnum.Rebate:
f.SnowballKOPayoffType = "票息补偿";
f.SnowballIsFixedCoupon = ext.IsFixedCoupon ? "否" : "是";
f.SnowballKORebate = ext.KORebate.OtcFormatPercent();
f.SnowballAnnualizedPremiumRate = ext.AnnualizedPremiumRate.OtcFormatPercent();
f.SnowballKOObservationSettleDates = ext.KOObservationSettleDates;
break;
case KOPayoffTypeEnum.ToOption:
f.SnowballKOPayoffType = KOPayoffTypeEnumHelper.GetDesc(ext.KOPayoffType, td.CallPut);
f.SnowballKOStrike1 = ext.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness);
break;
case KOPayoffTypeEnum.ToSpreadOption:
f.SnowballKOPayoffType = KOPayoffTypeEnumHelper.GetDesc(ext.KOPayoffType, td.CallPut);
f.SnowballKOStrike2 = ext.SpreadStrikeAtKO.OtcFormatUmPrice(isMoneyness);
f.SnowballKOStrike1 = ext.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness);
break;
default:
f.SnowballKOPayoffType = ext.KOPayoffType.ToString();
break;
}
f.SnowballKORebateType = RebateTypeEnumHelper.GetDesc(ext.KORebateType);
f.SnowballKIBarrier = ext.KIBarrier.OtcFormatUmPrice(isMoneyness);
switch (ext.KIPayoffType)
{
case KIPayoffTypeEnum.None:
f.SnowballKIPayoffType = "无";
break;
case KIPayoffTypeEnum.ToPutOption:
f.SnowballKIPayoffType = "敲入转看跌";
f.SnowballKIStrike1 = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
case KIPayoffTypeEnum.ToPutSpreadOption:
f.SnowballKIPayoffType = "敲入转熊市价差";
f.SnowballKIStrike2 = ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness);
f.SnowballKIStrike1 = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
case KIPayoffTypeEnum.ToCallOption:
f.SnowballKIPayoffType = "敲入转看涨";
f.SnowballKIStrike1 = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
case KIPayoffTypeEnum.ToCallSpreadOption:
f.SnowballKIPayoffType = "敲入转牛市价差";
f.SnowballKIStrike2 = ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness);
f.SnowballKIStrike1 = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
default:
f.SnowballKIPayoffType = ext.KIPayoffType.ToString();
break;
}
f.SnowballNoKICoupon = ext.Coupon.OtcFormatPercent();
var KOObservationDates = ext.KOObservationDates ?? string.Empty;
var index = KOObservationDates.IndexOf(';');
f.KOObservationDates = index > 0 ? ext.KOObservationDates.Substring(0, index) : KOObservationDates;
f.KIObservationDates = ext.ObservationDates;
f.IsAnnualized = ext.IsAnnualized2 ? "是" : "否";
}
break;
}
if (td.TradeType == "凤凰期权" || td.TradeType == "雪球期权")
{
f.CallPut = f.ExerciseMode = string.Empty;
td.MetaDic.TryGetValue(nameof(OtcOptionTradeFull.AnnualizeFactor2), out var metaValue);
f.AnnualizeFactor = metaValue;
}
else
{
td.MetaDic.TryGetValue(nameof(OtcOptionTradeFull.AnnualizeFactor), out var metaValue);
f.AnnualizeFactor = metaValue;
}
return f;
}
//收益互换
private EodPayOffSwapPositionExportFields GetEodPayOffSwapPostionFields(trade td, double PositionTradeAmount, double PositionPnl, double PositionPv)
{
var swap = td.trade_swap ?? new trade_swap();
var f = new EodPayOffSwapPositionExportFields
{
TradeNumber = td.TradeNumber,
AssetBookName = td.AssetBookName,
TraderName = td.TraderName,
ClientName = td.ClientName,
TradeDate = td.TradeDate.OtcFormatDate(),
ExerciseDate = td.ExerciseDate.OtcFormatDate(),
StockEqvNotional = td.OriginalStockEqvNotional.OtcFormat(OtcFormatFlag.StockEqvNotional),
Comments = td.Comments,
GetFixedProfit = swap.GetFixedProfit.OtcFormatMoney(),
GetLongShort = swap.GetLongShort,
GetMarginRate = swap.GetMarginRate.OtcFormatFlex(minDecimals: 0, percent: true),
GetTradePrice = swap.GetTradePrice.OtcFormatMoney(),
GetUnderlyingCode = swap.GetUnderlyingCode,
GetSpotPrice = swap.GetSpotPrice.OtcFormatUmPrice(),
IsGetFloatingProfit = swap.IsGetFloatingProfit ? "是" : "否",
IsPayFloatingProfit = swap.IsPayFloatingProfit ? "是" : "否",
PayFixedProfit = swap.PayFixedProfit.OtcFormatMoney(),
PayLongShort = swap.PayLongShort,
PayMarginRate = swap.PayMarginRate.OtcFormatMoney(),
PaySpotPrice = swap.PaySpotPrice.OtcFormatUmPrice(),
PayTradePrice = swap.PayTradePrice.OtcFormatMoney(),
PayUnderlyingCode = swap.PayUnderlyingCode,
PositionPnl = Convert.ToDouble(PositionPnl).OtcFormatMoney(),
PositionPv = Convert.ToDouble(PositionPv).OtcFormatMoney(),
PositionStockEqvNotional = PositionTradeAmount.OtcFormat(OtcFormatFlag.StockEqvNotional)
};
f.ClientNumber = ClientDataQueryService.GetClient(td.ClientId)?.Number;
return f;
}
/// <summary>
/// 查询场内期权持仓列表
/// </summary>
public IEnumerable<EodExOptionPositionExportFields> SearchExOptionTradeListForExport(DateTime valueDate)
{
var IsPVRounded = PS.Config.IsPVRounded;
var umSource = DataCacheProvider.GetUnderlyingDataSource();
var exOptionSource = DataCacheProvider.GetExchangeListOptionDataSource();
var volFormat = PS.Config.ErpElement.VolMoreAccurate ? "P2" : "P4";
valueDate = valueDate.Date;
var query = from etp in DbContext.eod_trade_position
join etr in DbContext.eod_trade_risk on etp.TradeId equals etr.TradeId
where etp.ValueDate == valueDate && etr.ValueDate == valueDate
&& etp.TradeType == "场内期权"
select new
{
etp.UnderlyingCode,
etp.ExchangeOptionCode,
etp.Amount,
etp.PositionType,
PositionPv = IsPVRounded ? etp.RoundedPv : etp.Pv,
PositionPnl = IsPVRounded ? etp.RoundedPositionPnL : etp.PositionPnL,
etr.Vol
};
var list = new List<EodExOptionPositionExportFields>();
foreach (var item in query)
{
var exoption = exOptionSource.GetData(item.ExchangeOptionCode);
var f = new EodExOptionPositionExportFields
{
OptionCode = item.ExchangeOptionCode,
ExerciseMode = exoption?.ExerciseMode,
Strike = (exoption?.Strike)?.ToString("F4"),
UnderlyingCode = item.UnderlyingCode,
PositionType = item.PositionType,
PositionPnl = Convert.ToDouble(item.PositionPnl).OtcFormatMoney(),
PositionPv = Convert.ToDouble(item.PositionPv).OtcFormatMoney(),
PositionTradeAmount = item.Amount.OtcFormatNotional(),
PositionVol = item.Vol.ToString(volFormat)
};
list.Add(f);
}
return list;
}
/// <summary>
/// 导出兴证数据中心需要的文件
/// </summary>
public byte[] ExportXingZhengZipFile(DateTime valueDate, out string zipFileName, IEnumerable<int> clienIds = null)
{
valueDate = valueDate.Date;
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}'未收盘!");
}
SearchOptionTradeListForExport(valueDate, out var listOption, out var listSwap);
var listExOption = SearchExOptionTradeListForExport(valueDate);
var dateStr = valueDate.ToString("yyyyMMdd");
zipFileName = $"ylotc_position_{dateStr}.zip";
var clients = DbContextFactory.GetClientDbContext(UserInfo).client
.Where(d => d.ProcessStatus == "已开户" || d.ProcessStatus == "已休眠" || d.ProcessStatus == "已销户")
.Select(n => new InnerClientInfo { id = n.id, ClientNumber = n.Number, ClientName = n.Name, LicenseCode = n.LicenseCode, ClientType = n.ClientType }).ToArray();
#region tw
if (clienIds != null)
{
clients = clients.Where(l => clienIds.Contains(l.id)).ToArray();
}
#endregion
using (var yldb = DbContextFactory.GetYLDbContext())
{
var sumQuery = from t in yldb.trade
where t.ValidState != ConsGlobal.InValid && t.IsGroup != 2
&& (t.TradeType != "结构化交易" || t.IsGroup == 1)
group t by t.ClientId into g
select new
{
clientId = g.Key,
sum = g.Sum(n => n.OriginalStockEqvNotional ?? 0)
};
var sumDic = sumQuery.ToDictionary(n => n.clientId, m => m.sum);
foreach (var c in clients)
{
if (sumDic.TryGetValue(c.id, out var sum))
{
c.StockEqvNotional = sum.ToString("F4");
}
}
}
using (var ms = new MemoryStream())
using (var outStream = new ZipOutputStream(ms))
using (var writer = new StreamWriter(outStream))
{
var csvConfig = new CsvConfiguration(System.Globalization.CultureInfo.InvariantCulture)
{
LeaveOpen = true,
Delimiter = "$#$"
};
outStream.PutNextEntry(new ZipEntry($"ylotc_position_option_{dateStr}.csv"));
using (var csv = new CsvWriter(writer, csvConfig))
{
csv.WriteRecords(listOption ?? Enumerable.Empty<EodOptionPositionExportFields>());
}
writer.Flush();
outStream.PutNextEntry(new ZipEntry($"ylotc_position_exoption_{dateStr}.csv"));
using (var csv = new CsvWriter(writer, csvConfig))
{
csv.WriteRecords(listExOption ?? Enumerable.Empty<EodExOptionPositionExportFields>());
}
writer.Flush();
outStream.PutNextEntry(new ZipEntry($"ylotc_position_payoffswap_{dateStr}.csv"));
using (var csv = new CsvWriter(writer, csvConfig))
{
csv.WriteRecords(listSwap ?? Enumerable.Empty<EodPayOffSwapPositionExportFields>());
}
writer.Flush();
outStream.PutNextEntry(new ZipEntry($"ylotc_client_{dateStr}.csv"));
using (var csv = new CsvWriter(writer, csvConfig))
{
csv.WriteRecords(clients);
}
writer.Flush();
writer.Close();
return ms.ToArray();
}
}
public byte[] GetClient()
{
var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/国投客户数据采集.xlsx");
using (var baseDb = new ClientDBContext())
{
//处理客户不属于 内部客户 n.IsInsided!=1
var ClientList = baseDb.client.Where(n => n.ProcessStatus == "已开户"&&n.IsInsided!=1).Select(x =>
new ClientInfo
{
ClientType = x.ClientType == "自然人" ? "个人" : x.ClientType,
ClientName = x.Name,
ClientTypeMemo = x.ClientType == "机构" ? "机构全称" : x.ClientType == "自然人" ? "" : "产品全称",
AdminFullName = x.ClientType == "产品" ? x.AdminFullName : "",
LicenseType = x.ClientType == "机构" ? "统一社会信用代码" : x.ClientType == "自然人" ? "居民身份证" : "产品编号",
AdminFullNameMome = x.ClientType == "产品" ? "产品管理人全称" : "",
IdentificationNumber = x.ClientType == "机构" ? x.LicenseCode : x.ClientType == "自然人" ? x.IdentificationNumber : x.ProductNumber,
AdminFullNameLicenseType = x.ClientType == "机构" ? "" : x.ClientType == "自然人" ? "" : "统一社会信用代码",
AdminRegisteredNum = x.ClientType == "产品" ? x.LicenseCode : "",
MainProtocolCode = x.MainProtocolCode
});
var buffer = ExcelGenerator.UseTemplateGenerator(templateFile).AddVariable(new { list = ClientList }).GenerateBytes();
return buffer;
}
}
public byte[] GetEodPosition(Model.EodPositionRisksReq req)
{
var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/国投数据采集.xlsx");
using (var baseDb = new ClientDBContext())
{
req.ValueDate = req.ValueDate;
req.EodSettlePriceMode = "收盘价";
req.IsOnlyExport = false;
req.IsParentTrade = false;
req.needSettleData = false;
req.VolType = "持仓";
//处理客户不属于 内部客户
req.ClientIds = baseDb.client.Where(n => n.IsInsided != 1).Select(l => l.id).ToList();
var result = new EodPositionRisksQueryService(UserInfo).SearchList(req);
var responEodPositions = new List<ResponEodPosition>();
foreach (var item in result.rows)
{
var responEodPosition = new ResponEodPosition();
var td = DbContext.trade.FirstOrDefault(l => l.id == item.id);
responEodPosition.bookName = item.AssetBookName;
responEodPosition.tradeId = item.TradeNumber;
responEodPosition.positionId = item.trade?.AssetId;
responEodPosition.underlyerInstrumentId = item.UnderlyingCode;
responEodPosition.underlyerMultiplier = GetunderlyerMultiplier(item.UnderlyingCode);
responEodPosition.productType = item.TradeType;
responEodPosition.initialNumber = item.TradeOriginalAmount;
responEodPosition.unwindNumber = td?.UnWindNotional;
responEodPosition.number = item.Notional;
responEodPosition.premium = item.TradePrice;
responEodPosition.marketValue = item.RoundedPV;
responEodPosition.pnl = item.dailyPnl;
responEodPosition.delta = item.Delta;
responEodPosition.deltaCash = item.DeltaCash;
responEodPosition.gamma = item.Gamma;
responEodPosition.gammaCash = item.GammaCash;
responEodPosition.vega = item.Vega;
responEodPosition.theta = item.Theta;
responEodPosition.rho = item.Rho;
responEodPosition.effectiveDate = td?.TradeDate;
responEodPosition.expirationDate = td?.ExerciseDate;
responEodPosition.message = "";
responEodPosition.pricingEnvironment = "";
responEodPosition.r = item.RiskFreeRate;
responEodPosition.q = item.DividendRate;
responEodPosition.vol = item.CurrentVolatility;
responEodPosition.listedOption = 0;//!
responEodPosition.price = item.UnderlyingPrice;
responEodPosition.notional = td?.StockEqvNotionalReal;
responEodPosition.initialNotional = item.StockEqvNotional;
responEodPosition.initialMargin = item.Margin;
responEodPosition.maintenanceMargin = td?.InitialMargin;
responEodPosition.initialVol = item.CurrentVolatility;
responEodPosition.masterAgreementId = GetmasterAgreement(item.ClientNumber);
responEodPosition.direction = td?.BuySell;
if (td != null)
{
responEodPosition.initialQ = GetinitialQ(item.id, req.ValueDate);
responEodPosition.initialR = GetinitialR(item.id, req.ValueDate);
responEodPosition.term = QdpModule.QdpCalendarHelper.AllBizDays(Convert.ToDateTime(td.TradeDate), Convert.ToDateTime(td.ExerciseDate)).Count;
var strike = DbContext.trade_double_sharkfin_option.FirstOrDefault(l => l.TradeId == item.id);
responEodPosition.highStrike = strike?.StrikeHigh;
responEodPosition.lowStrike = strike?.StrikeLow;
}
responEodPosition.settlementDate = td?.SettlementDate;//!
responEodPosition.tradeStatus = item.TradeStatus;
responEodPosition.lcmEventType = item.TradeStatus;
responEodPosition.initialSpot = td?.SpotPrice;
responEodPosition.highBarrier = item.RebateHigh;
responEodPosition.lowBarrier = item.Rebate;
responEodPosition.participationRates = item.ParticipationRate;
responEodPosition.rebate = item.Rebate;
responEodPosition.annualized = td?.IsAnnualized;
responEodPosition.specifiedPrice = td?.SettlementType == SettlementTypeEnum.ClosePrice ? "收盘价" : "结算价";
responEodPosition.frontPremium = item.TradeAmount;
responEodPosition.minimumPremium = td?.PrincipalRateWrite;
responEodPosition.daysInYear = item.InitialSpotPrice;//?
responEodPosition.initialPricingValue = item.TradeSinglePrice;
responEodPosition.initialUnderlyerPrice = td?.UnderlyingPrice;
responEodPosition.portfolioNames = item.TradeType;
responEodPosition.trader = td?.TraderName;
responEodPosition.tradeConfirmId = item.ContractCode;
responEodPosition.underlyerPrice = item.UnderlyingPrice;
responEodPosition.callput = item.trade?.CallPut;
responEodPositions.Add(responEodPosition);
}
var buffer = ExcelGenerator.UseTemplateGenerator(templateFile).AddVariable(new { list2 = responEodPositions }).GenerateBytes();
return buffer;
}
}
/// <summary>
/// 获取开仓无风险利率
/// </summary>
public double? GetinitialQ(int tdId, DateTime dateTime)
{
return DbContext.TradeHisData.Where(l => l.TradeId == tdId && l.ValueDate == dateTime && l.ValueType == "NoRiskRate").FirstOrDefault()?.Value;
}
/// <summary>
/// 获取开仓分红率
/// </summary>
public double? GetinitialR(int tdId, DateTime dateTime)
{
return DbContext.TradeHisData.Where(l => l.TradeId == tdId && l.ValueDate == dateTime && l.ValueType == "DividendRate").FirstOrDefault()?.Value;
}
/// <summary>
/// 获取 合约乘数
/// </summary>
/// <param name="UnderlyingCode"></param>
/// <returns></returns>
public double? GetunderlyerMultiplier(string UnderlyingCode)
{
var underlyerMultiplier = DataCacheProvider.GetUnderlyingDataSource().GetData(UnderlyingCode).ContractSize;
return underlyerMultiplier;
}
/// <summary>
/// 获取sac主协议编号
/// </summary>
/// <param name="ClientNumber"></param>
/// <returns></returns>
public string GetmasterAgreement(string ClientNumber)
{
var clientdb = new ClientDBContext();
if (string.IsNullOrEmpty(ClientNumber))
{
return "";
}
return clientdb.client.First(l => l.Number == ClientNumber).MainProtocolCode;
}
// {{item.positionId}} {{item.underlyerInstrumentId}} {{item.underlyerInstrumentIds}} {{item.underlyerMultiplier}} {{item.underlyerMultipliers}}
// {{item.productType}} {{item.initialNumber}} {{item.initialNumbers}} {{item.unwindNumber}} {{item.unwindNumbers}} {{item.number}} {{item.numbers}}
// {{item.premium}} {{item.unwindAmount}} {{item.marketValue}} {{item.pnl}} {{item.delta}} {{item.deltas}} {{item.deltaCash}} {{item.deltaCashes}}
// {{item.deltaDecay}} {{item.deltaDecays}} {{item.deltaWithDecay}} {{item.deltaWithDecays}} {{item.gamma}} {{item.gammas}} {{item.gammaCash}}
// {{item.gammaCashes}} {{item.vega}} {{item.vegas}} {{item.theta}} {{item.rho}} {{item.tradeDate}} {{item.effectiveDate}} {{item.expirationDate}}
// {{item.message}} {{item.createdAt}} {{item.pricingEnvironment}} {{item.r}} {{item.q}} {{item.qs}} {{item.vol}} {{item.vols}} {{item.listedOption}}
// {{item.price}} {{item.correlation}} {{item.notional}} {{item.initialNotional}} {{item.initialMargin}} {{item.initialQ}} {{item.initialR}} {{item.initialVol}}
// {{item.maintenanceMargin}} {{item.masterAgreementId}} {{item.direction}} {{item.term}} {{item.settlementDate}} {{item.tradeStatus}} {{item.lcmEventType}}
// {{item.initialSpot}} {{item.initialSpots}} {{item.highStrike}} {{item.lowStrike}} {{item.highBarrier}} {{item.lowBarrier}} {{item.participationRates}}
// {{item.rebate}} {{item.annualized}} {{item.specifiedPrice}} {{item.frontPremium}} {{item.minimumPremium}} {{item.daysInYear}} {{item.initialPricingValue}}
// {{item.initialUnderlyerPrice}} {{item.initialPnl}} {{item.initialStdDelta}} {{item.initialDelta}} {{item.initialDeltaCash}} {{item.initialGamma}} {{item.initialGammaCash}} {{item.initialVega}} {{item.initialTheta}} {{item.initialRhoR}} {{item.initialStdGamma}} {{item.tradeCategory}} {{item.portfolioNames}} {{item.trader}} {{item.tradeConfirmId}} {{item.regulationAssetClass}} {{item.regulationAssetSubClass}} {{item.underlyerPrice}}
class ResponEodPosition
{
public string bookName { get; set; }
public string tradeId { get; set; }
public int? positionId { get; set; }
public string underlyerInstrumentId { get; set; }
public string underlyerInstrumentIds { get; set; }
public double? underlyerMultiplier { get; set; }
public string underlyerMultipliers { get; set; }
public string productType { get; set; }
public double? initialNumber { get; set; }
public double? initialNumbers { get; set; }
public double? unwindNumber { get; set; }
public double? unwindNumbers { get; set; }
public double? number { get; set; }
public double? numbers { get; set; }
public double? premium { get; set; }
public double? unwindAmount { get; set; }
public double? marketValue { get; set; }
public double? pnl { get; set; }
public double? delta { get; set; }
public double? deltas { get; set; }
public double? deltaCash { get; set; }
public double? deltaCashes { get; set; }
public double? deltaDecay { get; set; }
public double? deltaDecays { get; set; }
public double? deltaWithDecay { get; set; }
public double? deltaWithDecays { get; set; }
public double? gamma { get; set; }
public double? gammas { get; set; }
public double? gammaCash { get; set; }
public double? gammaCashes { get; set; }
public double? vega { get; set; }
public double? vegas { get; set; }
public double? theta { get; set; }
public double? rho { get; set; }
public string tradeDate { get; set; }
public DateTime? effectiveDate { get; set; }
public DateTime? expirationDate { get; set; }
public string message { get; set; }
public string createdAt { get; set; }
public string pricingEnvironment { get; set; }
public double? r { get; set; }
public double? q { get; set; }
public double? qs { get; set; }
public double? vol { get; set; }
public double? vols { get; set; }
public double? listedOption { get; set; }
public double? price { get; set; }
public double? correlation { get; set; }
public double? notional { get; set; }
public double? initialNotional { get; set; }
public double? initialMargin { get; set; }
public double? initialQ { get; set; }
public double? initialR { get; set; }
public double? initialVol { get; set; }
public double? maintenanceMargin { get; set; }
public string masterAgreementId { get; set; }
public string direction { get; set; }
public int term { get; set; }
public DateTime? settlementDate { get; set; }
public string tradeStatus { get; set; }
public string lcmEventType { get; set; }
public double? initialSpot { get; set; }
public double? initialSpots { get; set; }
public double? highStrike { get; set; }
public double? lowStrike { get; set; }
public double? highBarrier { get; set; }
public double? lowBarrier { get; set; }
public double? participationRates { get; set; }
public double? rebate { get; set; }
public bool? annualized { get; set; }
public string specifiedPrice { get; set; }
public double? frontPremium { get; set; }
public double? minimumPremium { get; set; }
public double? daysInYear { get; set; }
public double? initialPricingValue { get; set; }
public double? initialUnderlyerPrice { get; set; }
public double? initialPnl { get; set; }
public double? initialStdDelta { get; set; }
public double? initialDelta { get; set; }
public double? initialDeltaCash { get; set; }
public double? initialGamma { get; set; }
public double? initialGammaCash { get; set; }
public double? initialVega { get; set; }
public double? initialTheta { get; set; }
public double? initialRhoR { get; set; }
public double? initialStdGamma { get; set; }
public double? tradeCategory { get; set; }
public string portfolioNames { get; set; }
public string trader { get; set; }
public string tradeConfirmId { get; set; }
public string regulationAssetClass { get; set; }
public string regulationAssetSubClass { get; set; }
public double? underlyerPrice { get; set; }
public string callput { get; set; }
}
class ClientInfo
{
/// <summary>
/// 客户类型
/// </summary>
public string ClientType { get; set; }
/// <summary>
/// 客户名称
/// </summary>
public string ClientName { get; set; }
/// <summary>
/// 客户类型备注 机构全称,产品全称,居民身份证
/// </summary>
public string ClientTypeMemo { get; set; }
/// <summary>
/// 证件类型
/// </summary>
public string LicenseType { get; set; }
/// <summary>
/// 证件号
/// </summary>
public string IdentificationNumber { get; set; }
/// <summary>
/// 产品管理人
/// </summary>
public string AdminFullName { get; set; }
/// <summary>
/// 主协议编号
/// </summary>
public string MainProtocolCode { get; set; }
/// <summary>
/// 证件类型备注 产品管理人全称
/// </summary>
public string AdminFullNameMome { get; set; }
/// <summary>
/// 产品管理人证件类型
/// </summary>
public string AdminFullNameLicenseType { get; set; }
/// <summary>
/// 产品管理人证件号
/// </summary>
public string AdminRegisteredNum { get; set; }
}
class InnerClientInfo
{
internal int id { get; set; }
public string ClientNumber { get; set; }
public string ClientName { get; set; }
public string LicenseCode { get; set; }
public string ClientType { get; set; }
public string StockEqvNotional { get; set; }
}
}
}
@@ -0,0 +1,240 @@
namespace YLErp.Modules.EodModule.QueryModule
{
/// <summary>
/// 场外期权持仓数据字段
/// 使用兴证数据中心接口文档创建
/// </summary>
public class EodOptionPositionExportFields
{
public string TradeNumber { get; set; }
public string AssetBookName { get; set; }
public string TraderName { get; set; }
public string ClientName { get; set; }
public string ClientNumber { get; set; }
public string StructureType { get; set; }
public string ExerciseMode { get; set; }
public string CallPut { get; set; }
public string TradeDate { get; set; }
public string ExerciseDate { get; set; }
public string SettlementDate { get; set; }
public string TradeSide { get; set; }
public string UnderlyingCode { get; set; }
public string UnderlyingName { get; set; }
public string InitSpotPrice { get; set; }
public string Strike { get; set; }
public string IsMoneynessOption { get; set; }
public string Premium { get; set; }
public string IsUsePremiumRate { get; set; }
public string InitialMargin { get; set; }
public string TradeAmount { get; set; }
public string TradePrice { get; set; }
public string StockEqvNotional { get; set; }
public string StockEqvNotionalReal { get; set; }
public string IsAnnualized { get; set; }
public string AnnualizeFactor { get; set; }
public string PrincipalRate { get; set; }
public string ParticipationRate { get; set; }
public string NoRiskRate { get; set; }
public string DividendRate { get; set; }
public string TradeOpenVolatility { get; set; }
public string TradeCloseVolatility { get; set; }
public string NumOfSmoothingDays { get; set; }
public string Comments { get; set; }
#region--------
//亚式期权
public string AsianAveragingPeriodStartDate { get; set; }
public string AsianPayoffType { get; set; }
public string AsianStrikeType { get; set; }
public string AsianStrikeGearingFactor { get; set; }
//障碍期权
public string BarrierType { get; set; }
public string BarrierPrice { get; set; }
public string BarrierPriceHigh { get; set; }
public string BarrierShift { get; set; }
public string BarrierRebate { get; set; }
public string BarrierRebateType { get; set; }
public string BarrierDiscrete { get; set; }
public string BarrierKnockInOutStatus { get; set; }
public string BarrierKnockInOutDate { get; set; }
//双鲨期权
public string DbsharkBarrierLow { get; set; }
public string DbsharkBarrierHigh { get; set; }
public string DbsharkStrikeHigh { get; set; }
public string DbsharkCallParticipationRate { get; set; }
public string DbsharkPutParticipationRate { get; set; }
public string DbsharkRebate { get; set; }
public string DbsharkRebateHigh { get; set; }
public string DbsharkRebateType { get; set; }
public string DbsharkDiscrete { get; set; }
//二元期权
public string BinaryPayoffType { get; set; }
public string BinaryUpperBarrier { get; set; }
public string BinaryCashOrNothingAmount { get; set; }
public string BinaryCashOrNothingAmountHigh { get; set; }
public string BinaryMonitorType { get; set; }
public string BinaryRebateType { get; set; }
//区间累积期权
public string RangeAccrualLowerRange { get; set; }
public string RangeAccrualUpperRange { get; set; }
public string RangeAccrualBonusRate { get; set; }
//气囊结构
public string AirbagBarrier { get; set; }
public string AirbagIsDiscrete { get; set; }
public string AirbagKIParticipationRate { get; set; }
public string AirbagHasPayoffLimit { get; set; }
public string AirbagHighStrike { get; set; }
//收益增强结构
public string AnnualizedEnhanceRate { get; set; }
//凤凰期权
public string AutocallIsFixedCoupon { get; set; }
public string AutocallCoupon { get; set; }
public string AutocallCouponBarrier { get; set; }
public string AutocallCouponPayType { get; set; }
public string AutocallKOBarrier { get; set; }
public string AutocallKIBarrier { get; set; }
public string AutocallIncludeCouponAfterKI { get; set; }
public string AutocallKIPayoffType { get; set; }
public string AutocallKIStrike1 { get; set; }
public string AutocallKIStrike2 { get; set; }
//雪球期权
public string SnowballKOBarrier { get; set; }
public string SnowballKOPayoffType { get; set; }
public string SnowballIsFixedCoupon { get; set; }
public string SnowballKORebate { get; set; }
public string SnowballAnnualizedPremiumRate { get; set; }
public string SnowballKOObservationSettleDates { get; set; }
public string SnowballKOStrike1 { get; set; }
public string SnowballKOStrike2 { get; set; }
public string SnowballKORebateType { get; set; }
public string SnowballKIBarrier { get; set; }
public string SnowballKIPayoffType { get; set; }
public string SnowballKIStrike1 { get; set; }
public string SnowballKIStrike2 { get; set; }
public string SnowballNoKICoupon { get; set; }
//敲入敲出
public string KOObservationDates { get; set; }
public string KIObservationDates { get; set; }
#endregion
//持仓信息
public string PositionTradeAmount { get; set; }
public string PositionPv { get; set; }
public string PositionPnl { get; set; }
public string PositionVol { get; set; }
}
/// <summary>
/// 场内期权持仓数据字段
/// 使用兴证数据中心接口文档创建
/// </summary>
public class EodExOptionPositionExportFields
{
public string OptionCode { get; set; }
public string UnderlyingCode { get; set; }
public string ExerciseMode { get; set; }
public string Strike { get; set; }
public string PositionType { get; set; }
public string PositionTradeAmount { get; set; }
public string PositionPv { get; set; }
public string PositionPnl { get; set; }
public string PositionVol { get; set; }
}
/// <summary>
/// 收益互换持仓数据字段
/// 使用兴证数据中心接口文档创建
/// </summary>
public class EodPayOffSwapPositionExportFields
{
public string TradeNumber { get; set; }
public string AssetBookName { get; set; }
public string TraderName { get; set; }
public string ClientName { get; set; }
public string ClientNumber { get; set; }
public string TradeDate { get; set; }
public string ExerciseDate { get; set; }
public string StockEqvNotional { get; set; }
public string Comments { get; set; }
public string IsGetFloatingProfit { get; set; }
public string GetUnderlyingCode { get; set; }
public string GetLongShort { get; set; }
public string GetSpotPrice { get; set; }
public string GetTradePrice { get; set; }
public string GetMarginRate { get; set; }
public string GetFixedProfit { get; set; }
public string IsPayFloatingProfit { get; set; }
public string PayUnderlyingCode { get; set; }
public string PayLongShort { get; set; }
public string PaySpotPrice { get; set; }
public string PayTradePrice { get; set; }
public string PayFixedProfit { get; set; }
public string PayMarginRate { get; set; }
public string PositionStockEqvNotional { get; set; }
public string PositionPv { get; set; }
public string PositionPnl { get; set; }
}
/// <summary>
/// 远期持仓数据字段
/// 使用兴证数据中心接口文档创建
/// </summary>
public class EodForwardPositionExportFields
{
public string TradeNumber { get; set; }
public string AssetBookName { get; set; }
public string TraderName { get; set; }
public string ClientName { get; set; }
public string ClientNumber { get; set; }
public string UnderlyingCode { get; set; }
public string UnderlyingName { get; set; }
public string BasisUnderlyingCode { get; set; }
public string BasisGap { get; set; }
public string TradeDate { get; set; }
public string ExerciseDate { get; set; }
public string TradeSide { get; set; }
public string CallPut { get; set; }
public string TradeAmount { get; set; }
public string Strike { get; set; }
public string InitSpotPrice { get; set; }
public string OpenFee { get; set; }
public string TotalFee { get; set; }
public string AnnualMarginRate { get; set; }
public string AnnualStoragePrice { get; set; }
public string NoRiskRate { get; set; }
public string Comments { get; set; }
public string PositionTradeAmount { get; set; }
public string PositionPv { get; set; }
public string PositionPnl { get; set; }
}
}