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
{
///
/// 远期多次了结查询服务
///
public class ForwardMultiCloseService : YLBaseService
{
public ForwardMultiCloseService(OptUserInfo userInfo) : base(userInfo)
{
}
///
/// 获取分页数据(远期)
///
public IPagedList 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(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> 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>();
}
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;
}
///
/// 导出远期数据(最多10000行)
///
///
public byte[] ExportExcel2007(TradeMultiCloseQueryModel queryModel)
{
if (queryModel is null)
{
queryModel = new TradeMultiCloseQueryModel();
}
queryModel.PageSize = 10000;
//var mapper = new Mapper { IgnoreNotMapped = true };
//mapper.MapClass()
// .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 formatValue = (cv) => { return cv.ToString("yyyy-MM-dd"); };
var dc = new List();
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(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> BuildPredicate(TradeMultiCloseQueryModel queryModel)
{
var predicate = PredicateBuilder.Create(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;
}
}
}
///
/// 多次了结服务结果Model
///
public class TradeForwardMultiCloseResultModel : OtcTradeBase
{
///
/// 行权方式
///
public string ExerciseWay { get; set; }
///
/// 了结方式
///
public string CloseType { get; set; }
///
/// 了结日期
///
public DateTime? CloseDate { get; set; }
///
/// 了结标的价格
///
public double StrikePrice { get; set; }
///
/// 权利金(了结)
///
public double UnwindPrice { get; set; }
///
/// 了结金额
///
public double UnwindFee { get; set; }
///
/// 平仓盈亏
///
public double ClosePnl { get; set; }
///
/// 实现盈亏
///
public double RealizedPnl { get; set; }
///
/// 排序序号
///
[JsonIgnore]
public int OrderSeq { get; set; }
[JsonIgnore]
public int TradeCashId { get; set; }
///
/// 了结序号
///
public int CloseSeq { get; set; } = 1;
///
/// 远期价值(了结)
///
public double UnWindForwardValue { get; set; }
///
/// 远期价值(成交)
///
public double ForwardValue { get; set; }
///
/// 平仓数量
///
public double UnWindTradeAmount { get; set; }
///
/// 成交手续费(了结部分所占的开仓总费用)
///
public double TradeCommission { get; set; }
///
/// 了结远期价值(远期收益)
///
public double UnWindForwardProfits { get; set; }
///
/// 了结手续费(平仓费用 * 了结数量 / 每手数量)
///
public double UnWindCommission { get; set; }
///
/// 了结资金成本(了结部分的预付金占用成本)
///
public double UnWindCapitalCost { get; set; }
///
/// 标的名称
///
public string UnderlyingName { get; set; }
///
/// 交易标签
///
public List Tags { get; set; }
}
}