418 lines
18 KiB
C#
418 lines
18 KiB
C#
using Newtonsoft.Json;
|
|
using System.Data;
|
|
using System.Linq.Expressions;
|
|
using YLErp.Commons;
|
|
using YLErp.DBModels.Converts;
|
|
using YLErp.Models.Tag;
|
|
using YLErp.Modules.TagModule;
|
|
|
|
namespace YLErp.Modules.TradeModule.ForwardModule
|
|
{
|
|
/// <summary>
|
|
/// 远期多次了结查询服务
|
|
/// </summary>
|
|
public class ForwardMultiCloseService : YLBaseService
|
|
{
|
|
public ForwardMultiCloseService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取分页数据(远期)
|
|
/// </summary>
|
|
public IPagedList<TradeForwardMultiCloseResultModel> GetPagedDatas(TradeMultiCloseQueryModel queryModel)
|
|
{
|
|
if (queryModel is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(queryModel));
|
|
}
|
|
|
|
var tradPredicate = BuildPredicate(queryModel);
|
|
var basicQuery = from t in DbContext.trade.Where(tradPredicate)
|
|
select t;
|
|
var tradCashPredicate = PredicateBuilder.Create<trade_cash>(tc => tc.ValidState != "InValid" && !tc.IsDeleted
|
|
&& (tc.Action == "系统操作-行权费" || tc.Action == "系统操作-平仓费"));
|
|
if (queryModel.UnwindDateStart != null)
|
|
{
|
|
tradCashPredicate = tradCashPredicate.And(n => n.ValueDate >= queryModel.UnwindDateStart.Value);
|
|
}
|
|
if (queryModel.UnwindDateEnd != null)
|
|
{
|
|
tradCashPredicate = tradCashPredicate.And(n => n.ValueDate <= queryModel.UnwindDateEnd.Value);
|
|
}
|
|
var query = from t in basicQuery.Where(tradPredicate)
|
|
join tc in DbContext.trade_cash.Where(tradCashPredicate) on t.id equals tc.TradeId
|
|
join ft in DbContext.trade_forward on t.id equals ft.TradeId
|
|
//join client in DbContext.client on t.ClientId equals client.id
|
|
where "远期" == t.TradeType && !tc.IsDeleted
|
|
select new TradeForwardMultiCloseResultModel
|
|
{
|
|
id = t.id,
|
|
TradeNumber = t.TradeNumber,
|
|
ClientName = t.ClientName,
|
|
TradeDate = t.TradeDate,
|
|
ExerciseDate = t.ExerciseDate,
|
|
BuySell = t.BuySell,
|
|
TradeType = t.TradeType,
|
|
OptionType = t.OptionType == "看涨" ? "多头" : "空头",
|
|
UnderlyingCode = t.UnderlyingCode,
|
|
SpotPrice = t.SpotPrice,
|
|
Strike = t.Strike,
|
|
TradeSinglePrice = t.TradeSinglePrice ?? 0,
|
|
TradeAmount = t.TradeAmount,
|
|
CloseDate = tc.ValueDate,
|
|
StrikePrice = tc.FinalPrice ?? 0,
|
|
UnwindPrice = tc.UnwindPrice ?? 0,
|
|
FinalPrice = tc.FinalPrice ?? 0,
|
|
UnWindNotional = tc.UnwindNotional ?? tc.Notional,
|
|
OriginalNotional = t.OriginalNotional ?? 0,
|
|
ClosePnl = tc.Amount,
|
|
UnwindFee = tc.Amount,
|
|
CloseType = tc.Action,
|
|
UnWindTradeAmount = tc.UnwindTradeAmount ?? 0,
|
|
UnWindCapitalCost = tc.ExtraAmount ?? 0,//了结资金成本(预付金占用)
|
|
TradePrice = t.TradePrice, //远期开仓总费用
|
|
ForwardValue = ft.ForwardValue,//远期价值-成交
|
|
OrderSeq = tc.Action == "系统操作-行权费" ? 2 : 1,
|
|
TradeCashId = tc.id,
|
|
StructureType = t.StructureType,
|
|
Comments = t.Comments
|
|
};
|
|
query = query.OrderByDescending(x => x.id).ThenBy(x => x.OrderSeq).ThenBy(x => x.CloseDate).ThenBy(x => x.TradeCashId);
|
|
var pagedList = query.ToPagedList(queryModel);
|
|
TradeForwardMultiCloseResultModel preData = null;
|
|
|
|
Dictionary<int, List<TagDto>> tradeTagList = null;
|
|
if (pagedList != null && pagedList.Any())
|
|
{
|
|
using (var service = new TagService(OptUser))
|
|
{
|
|
tradeTagList = service.GetTagByTradeIds(pagedList.Select(p => p.id).Distinct().ToList());
|
|
}
|
|
}
|
|
if (tradeTagList == null)
|
|
{
|
|
tradeTagList = new Dictionary<int, List<TagDto>>();
|
|
}
|
|
foreach (var data in pagedList)
|
|
{
|
|
var underlying = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(data.UnderlyingCode);
|
|
|
|
if (preData?.id == data.id)
|
|
{
|
|
data.CloseSeq = preData.CloseSeq + 1;
|
|
}
|
|
preData = data;
|
|
|
|
var openFee = data.OriginalNotional > 0 ? (data.UnWindNotional ?? 0) / data.OriginalNotional.Value * (data.TradePrice ?? 0) : 0;
|
|
data.RealizedPnl = data.ClosePnl + openFee;
|
|
|
|
if (data.CloseType == "系统操作-行权费")
|
|
{
|
|
data.CloseType = "到期";
|
|
}
|
|
else if (data.CloseType == "系统操作-平仓费")
|
|
{
|
|
data.CloseType = "终止";
|
|
}
|
|
data.TradeCommission = openFee;
|
|
data.CountRatio = underlying?.CountRatio ?? 1;
|
|
var buySell = BuySellConvert.GetClientBuySell(data.BuySell);//客户角度 买入卖出
|
|
data.UnWindForwardValue = new ForwardTradeImportService(OptUser).GetForwardValue(data.Strike ?? 0, data.FinalPrice ?? 0, data.UnWindTradeAmount, data.CountRatio ?? 1, data.OptionType, data.BuySell);
|
|
data.UnderlyingName = underlying.UnderlyingName;
|
|
//拼装标签值
|
|
if (tradeTagList.ContainsKey(data.id))
|
|
{
|
|
data.Tags = tradeTagList[data.id];
|
|
}
|
|
|
|
}
|
|
|
|
return pagedList;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 导出远期数据(最多10000行)
|
|
/// </summary>
|
|
/// <param name="queryModel"></param>
|
|
public byte[] ExportExcel2007(TradeMultiCloseQueryModel queryModel)
|
|
{
|
|
if (queryModel is null)
|
|
{
|
|
queryModel = new TradeMultiCloseQueryModel();
|
|
}
|
|
|
|
queryModel.PageSize = 10000;
|
|
|
|
//var mapper = new Mapper { IgnoreNotMapped = true };
|
|
//mapper.MapClass<TradeForwardMultiCloseResultModel>()
|
|
// .Map("交易编号", o => o.TradeNumber)
|
|
// .Map("交易对手方", o => o.ClientName)
|
|
// .Map("成交日期", o => o.TradeDate)
|
|
// .Map("到期日期", o => o.ExerciseDate)
|
|
// .Map("买卖方向", o => o.BuySell)
|
|
// .Map("结构类型", o => o.TradeType)
|
|
// .Map("多空方向", o => o.OptionType)
|
|
// .Map("标的代码", o => o.UnderlyingCode)
|
|
// .Map("期初标的价格", o => o.SpotPrice)
|
|
// .Map("执行价格", o => o.Strike)
|
|
// .Map("远期价值(成交)", o => o.ForwardValue)
|
|
// .Map("成交数量", o => o.OriginalNotional)
|
|
// .Map("成交手续费", o => o.TradeCommission)
|
|
// .Map("了结序号", o => o.CloseSeq)
|
|
// .Map("了结方式", o => o.CloseType)
|
|
// .Map("了结日期", o => o.CloseDate)
|
|
// .Map("了结标的价格", o => o.StrikePrice)
|
|
// .Map("远期价值(了结)", o => o.UnWindForwardValue)
|
|
// .Map("了结数量", o => o.UnWindNotional)
|
|
// .Map("了结手续费", o => o.UnWindCommission)
|
|
// .Map("了结资金成本", o => o.UnWindCapitalCost)
|
|
// .Map("了结金额", o => o.UnwindFee)
|
|
// .Map("实现盈亏", o => o.RealizedPnl)
|
|
// .Format("yyyy-MM-dd", o => o.TradeDate)
|
|
// .Format("yyyy-MM-dd", o => o.ExerciseDate)
|
|
// .Format("yyyy-MM-dd", o => o.CloseDate)
|
|
// .Format("0.00", o => o.Strike);
|
|
|
|
//mapper.ForHeader(cell =>
|
|
//{
|
|
// if (cell.ColumnIndex < 2)
|
|
// {
|
|
// cell.Sheet.SetColumnWidth(cell.ColumnIndex, 20 * 256);
|
|
// }
|
|
// else if (cell.StringCellValue.EndsWith("日期"))
|
|
// {
|
|
// cell.Sheet.SetColumnWidth(cell.ColumnIndex, 12 * 256);
|
|
// }
|
|
// else
|
|
// {
|
|
// cell.Sheet.SetColumnWidth(cell.ColumnIndex, 10 * 256);
|
|
// }
|
|
|
|
//});
|
|
|
|
var pagedData = GetPagedDatas(queryModel);
|
|
|
|
Func<DateTime, string> formatValue = (cv) => { return cv.ToString("yyyy-MM-dd"); };
|
|
|
|
var dc = new List<ExcelHelper.DataColumnModel>();
|
|
dc.Add(new ExcelHelper.DataColumnModel("交易编号", "TradeNumber"));
|
|
dc.Add(new ExcelHelper.DataColumnModel("交易对手方", "ClientName"));
|
|
dc.Add(new ExcelHelper.DataColumnModel("成交日期", "TradeDate", (cv, obj) => formatValue(((DateTime)cv))));
|
|
dc.Add(new ExcelHelper.DataColumnModel("到期日期", "ExerciseDate", (cv, obj) => formatValue(((DateTime)cv))));
|
|
dc.Add(new ExcelHelper.DataColumnModel("买卖方向", "BuySell"));
|
|
dc.Add(new ExcelHelper.DataColumnModel("结构类型", "TradeType", (cv, obj) =>
|
|
{//掉期类型展示
|
|
if (obj is TradeForwardMultiCloseResultModel model)
|
|
{
|
|
return model.StructureType ?? cv;
|
|
}
|
|
return cv;
|
|
}
|
|
));
|
|
dc.Add(new ExcelHelper.DataColumnModel("多空方向", "OptionType"));
|
|
dc.Add(new ExcelHelper.DataColumnModel("标的名称", "UnderlyingName"));
|
|
dc.Add(new ExcelHelper.DataColumnModel("标的代码", "UnderlyingCode"));
|
|
dc.Add(new ExcelHelper.DataColumnModel("期初标的价格", "SpotPrice", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("执行价格", "Strike", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("远期价值(成交)", "ForwardValue", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("成交数量", "OriginalNotional", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("成交手续费", "TradeCommission", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("了结序号", "CloseSeq", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("了结方式", "CloseType"));
|
|
dc.Add(new ExcelHelper.DataColumnModel("了结日期", "CloseDate", (cv, obj) => formatValue(((DateTime)cv))));
|
|
dc.Add(new ExcelHelper.DataColumnModel("了结标的价格", "StrikePrice", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("远期价值(了结)", "UnWindForwardValue", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("了结数量", "UnWindNotional", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("了结手续费", "UnWindCommission", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("了结资金成本", "UnWindCapitalCost", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("了结金额", "UnwindFee", typeof(double)));
|
|
dc.Add(new ExcelHelper.DataColumnModel("实现盈亏", "RealizedPnl", typeof(double)));
|
|
new ExcelHelper().ListToExcel<TradeForwardMultiCloseResultModel>(dc.ToArray(), pagedData.Items.ToList(), "多次了结", true, out var buffer);
|
|
return buffer;
|
|
//using (var stream = new MemoryStream())
|
|
//{
|
|
// mapper.Save(stream, pagedData.Items, "多次了结", overwrite: true);
|
|
// return stream.ToArray();
|
|
//}
|
|
}
|
|
|
|
private Expression<Func<trade, bool>> BuildPredicate(TradeMultiCloseQueryModel queryModel)
|
|
{
|
|
var predicate = PredicateBuilder.Create<trade>(t => t.ValidState != ConsGlobal.InValid);
|
|
if (queryModel.UserAssets != null || queryModel.UserClients != null)
|
|
{
|
|
predicate = predicate.And(n => queryModel.UserAssets.Contains(n.AssetId) || queryModel.UserClients.Contains(n.ClientId));
|
|
}
|
|
if (queryModel.TradeDateStart != null)
|
|
{
|
|
predicate = predicate.And(n => n.TradeDate >= queryModel.TradeDateStart.Value);
|
|
}
|
|
if (queryModel.TradeDateEnd != null)
|
|
{
|
|
predicate = predicate.And(n => n.TradeDate <= queryModel.TradeDateEnd.Value);
|
|
}
|
|
if (queryModel.ExerciseDateStart != null)
|
|
{
|
|
predicate = predicate.And(n => n.ExerciseDate >= queryModel.ExerciseDateStart.Value);
|
|
}
|
|
if (queryModel.ExerciseDateEnd != null)
|
|
{
|
|
predicate = predicate.And(n => n.ExerciseDate <= queryModel.ExerciseDateEnd.Value);
|
|
}
|
|
if (queryModel.AssetUnitIds != null && queryModel.AssetUnitIds.Any(a => a > 0))
|
|
{
|
|
predicate = predicate.And(n => queryModel.AssetUnitIds.Contains(n.AssetId));
|
|
}
|
|
if (queryModel.ClientIdList.Any())
|
|
{
|
|
predicate = predicate.And(n => queryModel.ClientIdList.Contains(n.ClientId));
|
|
}
|
|
if (!string.IsNullOrWhiteSpace(queryModel.TradeNumber))
|
|
{
|
|
var TradeNumber = queryModel.TradeNumber.Trim();
|
|
predicate = predicate.And(n => n.TradeNumber.Contains(TradeNumber));
|
|
}
|
|
if (queryModel.UnderlyingIdList != null && queryModel.UnderlyingIdList.Any(n => n > 0))
|
|
{
|
|
predicate = predicate.And(n => queryModel.UnderlyingIdList.Contains(n.UnderlyingId));
|
|
}
|
|
|
|
if (queryModel.TagIds != null && queryModel.TagIds.Count > 0)
|
|
{
|
|
var tradeTagIdQuery = from tt in DbContext.trade_tag
|
|
where queryModel.TagIds.Contains(tt.TagId)
|
|
select tt.TradeId;
|
|
predicate = predicate.And(p => tradeTagIdQuery.Contains(p.id));
|
|
}
|
|
|
|
return predicate;
|
|
}
|
|
|
|
private int GetDirection(string buySell, string callPut)
|
|
{
|
|
if ((buySell == "买入" && callPut == "空头")
|
|
|| (buySell == "卖出" && callPut == "多头"))
|
|
{
|
|
return 1;
|
|
}
|
|
else if ((buySell == "买入" && callPut == "多头")
|
|
|| (buySell == "卖出" && callPut == "空头"))
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 多次了结服务结果Model
|
|
/// </summary>
|
|
public class TradeForwardMultiCloseResultModel : OtcTradeBase
|
|
{
|
|
/// <summary>
|
|
/// 行权方式
|
|
/// </summary>
|
|
public string ExerciseWay { get; set; }
|
|
|
|
/// <summary>
|
|
/// 了结方式
|
|
/// </summary>
|
|
public string CloseType { get; set; }
|
|
|
|
/// <summary>
|
|
/// 了结日期
|
|
/// </summary>
|
|
public DateTime? CloseDate { get; set; }
|
|
|
|
/// <summary>
|
|
/// 了结标的价格
|
|
/// </summary>
|
|
public double StrikePrice { get; set; }
|
|
|
|
/// <summary>
|
|
/// 权利金(了结)
|
|
/// </summary>
|
|
public double UnwindPrice { get; set; }
|
|
|
|
/// <summary>
|
|
/// 了结金额
|
|
/// </summary>
|
|
public double UnwindFee { get; set; }
|
|
|
|
/// <summary>
|
|
/// 平仓盈亏
|
|
/// </summary>
|
|
public double ClosePnl { get; set; }
|
|
|
|
/// <summary>
|
|
/// 实现盈亏
|
|
/// </summary>
|
|
public double RealizedPnl { get; set; }
|
|
|
|
/// <summary>
|
|
/// 排序序号
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public int OrderSeq { get; set; }
|
|
|
|
[JsonIgnore]
|
|
public int TradeCashId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 了结序号
|
|
/// </summary>
|
|
public int CloseSeq { get; set; } = 1;
|
|
|
|
/// <summary>
|
|
/// 远期价值(了结)
|
|
/// </summary>
|
|
public double UnWindForwardValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// 远期价值(成交)
|
|
/// </summary>
|
|
public double ForwardValue { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
/// 平仓数量
|
|
/// </summary>
|
|
public double UnWindTradeAmount { get; set; }
|
|
|
|
/// <summary>
|
|
/// 成交手续费(了结部分所占的开仓总费用)
|
|
/// </summary>
|
|
public double TradeCommission { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
/// 了结远期价值(远期收益)
|
|
/// </summary>
|
|
public double UnWindForwardProfits { get; set; }
|
|
|
|
/// <summary>
|
|
/// 了结手续费(平仓费用 * 了结数量 / 每手数量)
|
|
/// </summary>
|
|
public double UnWindCommission { get; set; }
|
|
|
|
/// <summary>
|
|
/// 了结资金成本(了结部分的预付金占用成本)
|
|
/// </summary>
|
|
public double UnWindCapitalCost { get; set; }
|
|
|
|
/// <summary>
|
|
/// 标的名称
|
|
/// </summary>
|
|
public string UnderlyingName { get; set; }
|
|
|
|
/// <summary>
|
|
/// 交易标签
|
|
/// </summary>
|
|
public List<TagDto> Tags { get; set; }
|
|
}
|
|
}
|