从山证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
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,273 @@
using Qdp.Pricing.Base.Enums;
using YLErp.Configuration;
namespace YLErp.Modules.TradeModule.OrderModule
{
partial class TradeAbstractService
{
/// <summary>
/// 雪球期权生成交易摘要
/// </summary>
private static IEnumerable<(string text, string value)> GenerateTradeAbstract_snowball(trade td, InnerWrap wrap)
{
if (td is null)
{
throw new ArgumentNullException(nameof(td));
}
if (wrap is null)
{
throw new ArgumentNullException(nameof(wrap));
}
var snowball = td.trade_snowball;
if (snowball == null)
{
throw new ServiceException("雪球期权扩展信息不存在,无法生成交易摘要");
}
//专业版雪球
if (snowball.PrepaymentUsed)
{
return GenerateTradeAbstract_specialsnowball(td, wrap);
}
td.TradeOriginalAmount = td.OriginalNotional / wrap.CountRatio;
var list = new List<(string, string)> {
("交易编号", td.TradeNumber),
("成交日期", td.TradeDate.OtcFormatDate()),
("买卖方向", td.ClientName),
("#", td.BuySell == "买入" ? "卖出" : "买入"),
("标的代码", td.UnderlyingCode),
};
if (wrap.UnderlyingInstrumentType == "Stock")
{
list.Add(("标的名称", wrap.UnderlyingName));
}
list.Add(("期权类型", "雪球 " + td.OptionType));
list.Add(("标的价格", td.SpotPrice.OtcFormatUmPrice() + (PS.Config.Is浙期 ? " 元" : "")));
if (td.TradeType != "自定义交易" && (td.TradeType != "亚式期权" || td.trade_asian_option.StrikeType != "Floating") && td.TradeType != "雪球期权")
{
list.Add(("执行价格", wrap.strikeFmt(td.Strike) + (PS.Config.Is浙期 ? " 元" : "")));
}
if (!wrap.IsUsePremiumRate)
{
list.Add(("成交数量", td.TradeOriginalAmount.OtcFormatNotional(wrap.CountRatio, PS.Config.IsUseDisplayNotional) + (PS.Config.IsUseDisplayNotional ? wrap.QuoteUnit : wrap.TradeUnitString)));
}
if (PS.Config.Is方顿)
{
list.Add(("保底收益总额", td.OriginalPrincipalSum.OtcFormatMoney() + " 元"));
}
if (PS.Config.Company != CompanyEnum.屿 && !PS.Config.Is润和)
{
list.AddRange(new[] {
("名义本金", OtcFormatExtensions.OtcFormat(td.StockEqvNotionalToShow, OtcFormatFlag.StockEqvNotional))
});
}
if (!snowball.IsInitialKnockedIn)
{
list.Add(("敲入价格", wrap.strikeFmt(snowball.KIBarrier) + (PS.Config.Is浙期 ? " 元" : "")));
}
else
{
list.Add(("初始敲入", "是"));
}
list.Add(("敲出价格", wrap.strikeFmt(snowball.KOBarrier) + (PS.Config.Is浙期 ? " 元" : "")));
switch (snowball.KIPayoffType)
{
case KIPayoffTypeEnum.None:
break;
case KIPayoffTypeEnum.ToCallOption:
case KIPayoffTypeEnum.ToPutOption:
list.Add(("执行价格一", wrap.strikeFmt(snowball.SpreadStrikeAtMaturity1)));
break;
case KIPayoffTypeEnum.ToCallSpreadOption:
case KIPayoffTypeEnum.ToPutSpreadOption:
list.Add(("执行价格一", wrap.strikeFmt(snowball.SpreadStrikeAtMaturity)));
list.Add(("执行价格二", wrap.strikeFmt(snowball.SpreadStrikeAtMaturity1)));
break;
default:
break;
}
var kiObsInfo = "每日观察";
if (!string.IsNullOrWhiteSpace(snowball.ObservationDates))
{
kiObsInfo = snowball.ObservationDates;
}
switch (snowball.KOPayoffType)
{
case KOPayoffTypeEnum.ToOption:
list.Add(("敲出执行价1", wrap.strikeFmt(snowball.SpreadStrikeAtKO1) + (PS.Config.Is浙期 ? " 元" : "")));
break;
case KOPayoffTypeEnum.ToSpreadOption:
list.Add(("敲出执行价1", wrap.strikeFmt(snowball.SpreadStrikeAtKO1) + (PS.Config.Is浙期 ? " 元" : "")));
list.Add(("敲出执行价2", wrap.strikeFmt(snowball.SpreadStrikeAtKO) + (PS.Config.Is浙期 ? " 元" : "")));
break;
case KOPayoffTypeEnum.Rebate:
list.Add(("敲出票息", snowball.KORebate.OtcFormatPercent()));
break;
default:
kiObsInfo = "";
break;
}
list.Add(("未敲入未敲出收益率", snowball.Coupon.OtcFormat(OtcFormatFlag.percent)));
list.Add(("票息年化", snowball.IsFixedCoupon ? "否" : "是"));
if (!string.IsNullOrWhiteSpace(kiObsInfo) && !snowball.IsInitialKnockedIn)
{
list.Add(("敲入观察日期", kiObsInfo));
}
var koInfo = "";
if (!string.IsNullOrWhiteSpace(snowball.KOObservationDates))
{
var KOObservationDates = QdpModule.QdpHelper.ParseAutocallCustomizedInfo(snowball.KOObservationDates);
for (var i = 0; i < KOObservationDates.Item1.Length; i++)
{
var splitStr = ", ";
if (i == KOObservationDates.Item1.Length - 1)
{
splitStr = "";
}
var couponInfo = PS.Config.Is浙期 ? ":" + KOObservationDates.Item3[i].OtcFormat(OtcFormatFlag.percent) + splitStr : splitStr;
koInfo += KOObservationDates.Item1[i].DateTime.ToString("yyyy-MM-dd") + couponInfo;
}
}
list.Add(("到期日期", td.ExerciseDate.OtcFormatDate()));
list.Add(("敲出观察日期", koInfo));
return list;
}
/// <summary>
/// 专业版雪球期权生成交易摘要
/// </summary>
private static IEnumerable<(string text, string value)> GenerateTradeAbstract_specialsnowball(trade td, InnerWrap wrap)
{
if (td is null)
{
throw new ArgumentNullException(nameof(td));
}
if (wrap is null)
{
throw new ArgumentNullException(nameof(wrap));
}
var snowball = td.trade_snowball;
if (snowball == null)
{
throw new ServiceException("雪球期权扩展信息不存在,无法生成交易摘要");
}
td.TradeOriginalAmount = td.OriginalNotional / wrap.CountRatio;
var list = new List<(string, string)> {
("交易编号", td.TradeNumber),
("成交日期", td.TradeDate.OtcFormatDate()),
("买卖方向", td.ClientName),
("#", td.BuySell == "买入" ? "卖出" : "买入"),
("标的代码", td.UnderlyingCode),
};
if (wrap.UnderlyingInstrumentType == "Stock")
{
list.Add(("标的名称", wrap.UnderlyingName));
}
list.Add(("期权类型", "雪球 " + td.OptionType));
list.Add(("标的价格", td.SpotPrice.OtcFormatUmPrice() + (PS.Config.Is浙期 ? " 元" : "")));
if (!wrap.IsUsePremiumRate)
{
list.Add(("成交数量", td.TradeOriginalAmount.OtcFormatNotional(wrap.CountRatio, PS.Config.IsUseDisplayNotional) + (PS.Config.IsUseDisplayNotional ? wrap.QuoteUnit : wrap.TradeUnitString)));
}
if (PS.Config.Is方顿)
{
list.Add(("保底收益总额", td.OriginalPrincipalSum.OtcFormatMoney() + " 元"));
}
if (PS.Config.Company != CompanyEnum.屿 && !PS.Config.Is润和)
{
list.AddRange(new[] {
("名义本金", OtcFormatExtensions.OtcFormat(td.StockEqvNotionalToShow, OtcFormatFlag.StockEqvNotional))
});
}
list.Add(("预付金比例", snowball.PrepaymentRatio.OtcFormatFlex(2, percent: true)));
//list.Add(("预付金返息率", snowball.PrepaymentInterestRate.OtcFormatFlex(2, percent: true)));
list.Add(("预付金折现率", snowball.PrepaymentConvertCashRate.OtcFormatFlex(2, percent: true)));
if (snowball.IsInitialKnockedIn)
{
list.Add(("初始敲入", "是"));
}
else
{
list.Add(("敲入价格", wrap.strikeFmt(snowball.KIBarrier) + (PS.Config.Is浙期 ? " 元" : "")));
list.Add(("敲入观察设置", snowball.KIObservationType == KIObservationType.OnlyEndDate ? "仅到期日观察" : "每日观察"));
}
list.Add(("敲入执行价格", wrap.strikeFmt(snowball.SpreadStrikeAtMaturity1) + (PS.Config.Is浙期 ? " 元" : "")));
list.Add(("敲入参与率", snowball.KIParticipationRate.OtcFormatFlex(2, percent: true)));
list.Add(("保本比率", snowball.PrincipalProtectionRate.OtcFormatFlex(2, percent: true)));
list.Add(("首日是否计息", snowball.CouponIncludeStartDate == true ? "是" : "否"));
list.Add(("终日是否计息", snowball.CouponIncludeEndDate == true ? "是" : "否"));
var couponDayCount = "非年化";
switch (snowball.CouponDayCount)
{
case nameof(DayCount.Act365):
couponDayCount = "按365日年化";
break;
case nameof(DayCount.Act360):
couponDayCount = "按360日年化";
break;
case nameof(DayCount.Monthly):
couponDayCount = "按月年化";
break;
}
list.Add(("计息年化方式", couponDayCount));
list.Add(("票息率", snowball.KORebate.OtcFormatFlex(2, percent: true)));
list.Add(("红利票息", snowball.Coupon.OtcFormatFlex(2, percent: true)));
list.Add(("增强参与率", snowball.EnhancedParticipationRate.OtcFormatFlex(2, percent: true)));
list.Add(("敲出价格", wrap.strikeFmt(snowball.KOBarrier) + (PS.Config.Is浙期 ? " 元" : "")));
var koInfo = "";
if (!string.IsNullOrWhiteSpace(snowball.KOObservationDates))
{
var KOObservationDates = QdpModule.QdpHelper.ParseAutocallCustomizedInfo(snowball.KOObservationDates);
if (KOObservationDates != null && KOObservationDates.Item1.Length > 0)
{
for (var i = 0; i < KOObservationDates.Item1.Length; i++)
{
var splitStr = ", ";
if (i == KOObservationDates.Item1.Length - 1)
{
splitStr = "";
}
var couponInfo = PS.Config.Is浙期 ? ":" + KOObservationDates.Item3?[i].OtcFormat(OtcFormatFlag.percent) + splitStr : splitStr;
koInfo += KOObservationDates.Item1[i].DateTime.ToString("yyyy-MM-dd") + couponInfo;
}
}
}
list.Add(("到期日期", td.ExerciseDate.OtcFormatDate()));
list.Add(("敲出观察日期", koInfo));
return list;
}
}
}
@@ -0,0 +1,219 @@
using YLErp.BLL;
namespace YLErp.Modules.TradeModule.OrderModule
{
/// <summary>
/// 交易删除
/// </summary>
public class TradeInvalidService : TradeServiceBase
{
public TradeInvalidService(OptUserInfo userInfo) : base(userInfo)
{
}
public TradeInvalidService(YLBaseService baseService) : base(baseService)
{
}
/// <summary>
/// 无效某条交易
/// </summary>
public void InvalidTrade(int id, bool needCheckStatus)
{
var dbTrade = DbContext.trade.Find(id);
InvalidTrade(dbTrade, needCheckStatus);
}
/// <summary>
/// 无效某条交易
/// </summary>
public void InvalidTrade(string tradeNumber, bool needCheckStatus)
{
if (string.IsNullOrWhiteSpace(tradeNumber))
{
throw new ArgumentException($"“{nameof(tradeNumber)}”不能为 null 或空白。", nameof(tradeNumber));
}
var dbTrade = DbContext.trade.FirstOrDefault(n => n.TradeNumber == tradeNumber);
InvalidTrade(dbTrade, needCheckStatus);
}
/// <summary>
/// 无效某条交易
/// </summary>
private void InvalidTrade(trade dbTrade, bool needCheckStatus)
{
if (dbTrade == null)
{
throw new ServiceException("找不到交易信息");
}
if (needCheckStatus && dbTrade.TradeStatus != ConsTrade. && dbTrade.TradeStatus != ConsTrade. && dbTrade.TradeStatus != ConsTrade. && (!PS.Config.IsGuoJun ? dbTrade.TradeStatus != ConsTrade. : true))
{
throw new ServiceException($"交易状态为{dbTrade.TradeStatus},不能被删除。");
}
//结构化交易删除子交易,则主交易相关所有记录均会被删除
if (dbTrade.ParentTradeId > 0 && dbTrade.TradeType != "收益互换")
{
dbTrade = DbContext.trade.Find(dbTrade.ParentTradeId);
if (dbTrade == null)
{
throw new ServiceException("找不到结构化交易信息");
}
}
var ids = new HashSet<int> { dbTrade.id };
if (dbTrade.TradeType == "结构化交易" || dbTrade.IsGroup == 1)
{
var subTrades = DbContext.trade.Where(t => t.ParentTradeId == dbTrade.id).ToList();
InnerInvalidTrade(dbTrade);
foreach (var subTrade in subTrades)
{
ids.Add(subTrade.id);
InnerInvalidTrade(subTrade);
}
}
else
{
InnerInvalidTrade(dbTrade);
//组合收益互换
if (dbTrade.ParentTradeId > 0)
{
var parentTrade = DbContext.trade.Find(dbTrade.ParentTradeId);
if (parentTrade != null)
{
parentTrade.OriginalStockEqvNotional -= dbTrade.OriginalStockEqvNotional;
parentTrade.StockEqvNotional -= dbTrade.StockEqvNotional;
parentTrade.StockEqvNotionalReal -= dbTrade.StockEqvNotionalReal;
var tradePrice = (parentTrade.TradePrice ?? 0) * (parentTrade.BuySell == "买入" ? -1 : 1) - (dbTrade.TradePrice ?? 0) * (dbTrade.BuySell == "买入" ? -1 : 1);
parentTrade.TradePrice = Math.Abs(tradePrice);
parentTrade.BuySell = tradePrice >= 0 ? "卖出" : "买入";
if (parentTrade.StockEqvNotional <= 0)
{
parentTrade.TradeStatus = "已平仓";
}
}
var swapDetail = DbContext.trade_swap_detail.FirstOrDefault(x => x.ChildTradeId == dbTrade.id);
if (swapDetail != null)
{
swapDetail.ValidState = "InValid";
}
}
if (dbTrade.TradeType == "收益互换" && PS.Config.IsGuoJun)
{
var flowid = DbContext.trade_swap.Where(x => x.TradeId == dbTrade.id).Select(x => x.FlowId).ToList();
var swapflowmore = DbContext.trade_swap_flow_more.Where(x => flowid.Contains(x.id)).ToList();
swapflowmore.ForEach(x =>
{
x.IsDelete = true;
});
}
}
//设置相关提成失效
SetCommissionInVaild(ids);
DbContext.SaveChanges();
}
public void InnerInvalidTrade(trade dbTrade)
{
dbTrade.OptId = UserId;
dbTrade.OptName = UserName;
dbTrade.OptDate = OptDate;
dbTrade.ValidState = ConsGlobal.InValid;
if (!string.IsNullOrWhiteSpace(dbTrade.TradeNumber))
{
var contractBll = new TradeContractBLL(UserId, UserName);
contractBll.DeleteConfirmBook(dbTrade.id);
if (dbTrade.TradeNumber.StartsWith("CW"))
{
dbTrade.TradeNumber = dbTrade.TradeNumber.Replace("CW", "XX");
}
else //if (PS.Config.Is光大光子)
{
dbTrade.TradeNumber = dbTrade.TradeNumber.Insert(0, "XX");
}
}
var tradeMarginTemplates = DbContext.trade_margin_template.Where(x => x.TradeId == dbTrade.id);
if(tradeMarginTemplates.Any())
{
DbContext.trade_margin_template.RemoveRange(tradeMarginTemplates);
}
RemoveEodTradeAndFutureInfo(true, dbTrade.id, DateTime.MinValue);
new DealModule.TradeConfirmService(this).EditReportStatus(dbTrade.id);
AddTradeOperationHistoryAndSetParentTradeInfo(true, dbTrade, "删除交易");
}
//设置相关提成失效
public void SetCommissionInVaild(HashSet<int> tradeIds)
{
var commissions = DbContext.SalesCommissionInfo.Where(o => tradeIds.Contains(o.TradeID)).ToArray();
foreach (var item in commissions)
{
item.IsValid = false;
item.OptDate = DateTime.Now;
}
}
/// <summary>
/// 批量删除当日交易‘新增待确认’状态的交易
/// </summary>
public int InvalidTodayUnconfirmedTrades(HashSet<int> ids)
{
if (ids is null || !ids.Any())
{
return 0;
}
var valueDate = valuedateBLL.ValueDate;
var tradeList = DbContext.trade.Where(t => t.TradeDate == valueDate && ids.Contains(t.id) && t.ValidState != ConsGlobal.InValid && t.TradeStatus == ConsTrade.).ToList();
if (!tradeList.Any())
{
return 0;
}
var pids = tradeList.Select(n => n.ParentTradeId).ToHashSet();
pids.Remove(0);
if (pids.Any())
{
var pTrades = DbContext.trade.Where(t => t.TradeDate == valueDate && !ids.Contains(t.id) && (pids.Contains(t.id) || pids.Contains(t.ParentTradeId))).ToArray();
tradeList.AddRange(pTrades);
}
var childrenTrades = DbContext.trade.Where(t => t.TradeDate == valueDate && !ids.Contains(t.id) && ids.Contains(t.ParentTradeId)).ToArray();
if (childrenTrades.Any())
{
tradeList.AddRange(childrenTrades);
}
foreach (var t in tradeList)
{
ids.Add(t.id);
InnerInvalidTrade(t);
}
SetCommissionInVaild(ids);
DbContext.SaveChanges();
return tradeList.Count;
}
}
}
@@ -0,0 +1,212 @@
using Qdp.Pricing.Base.Enums;
using YLErp.QdpModule;
namespace YLErp.Modules.TradeModule.OrderModule
{
/// <summary>
/// 扩展存储
/// </summary>
class TradeSaveExtend : YLBaseService
{
private readonly bool isAddNew;
public TradeSaveExtend(YLBaseService baseService, bool isAddNew)
: base(baseService)
{
this.isAddNew = isAddNew;
}
/// <summary>
/// 保存并写入数据库
/// </summary>
public int Save(trade baseTrade, trade dbTrade, bool useSaveChange = true)
{
switch (baseTrade.TradeType == "结构化交易" ? baseTrade.StructureType : baseTrade.TradeType)
{
case "香草期权":
case "合成价差期权":
return 0;
case "亚式期权":
dbTrade.trade_asian_option = InnerSaveExtend(baseTrade, baseTrade.trade_asian_option);
break;
case "彩虹期权":
dbTrade.trade_rainbow_option = InnerSaveExtend(baseTrade, baseTrade.trade_rainbow_option);
break;
case "障碍期权":
dbTrade.trade_barrier_option = InnerSaveExtend(baseTrade, baseTrade.trade_barrier_option);
break;
case "二元期权":
dbTrade.trade_binary_option = InnerSaveExtend(baseTrade, baseTrade.trade_binary_option);
break;
case "价差期权":
dbTrade.trade_spread_option = InnerSaveExtend(baseTrade, baseTrade.trade_spread_option);
break;
case "双鲨期权":
dbTrade.trade_double_sharkfin_option = InnerSaveExtend(baseTrade, baseTrade.trade_double_sharkfin_option);
break;
case "凤凰期权":
if (string.IsNullOrEmpty(baseTrade.trade_autocall.KOObservationDates))
{
if (dbTrade.trade_autocall==null)
{
dbTrade.trade_autocall = new trade_autocall();
}
var autocallmonthlyDates = QdpObservationHelper.GetDatesWithFixedTerm(baseTrade.TradeDate ?? System.DateTime.Now, baseTrade.ExerciseDate ?? System.DateTime.Now, "1M", bdc: BusinessDayConvention.Following, alignEnd: true);
dbTrade.trade_autocall.KOObservationDates = $"{string.Join(",", autocallmonthlyDates.Select(O => O.OtcFormatDate()))};" +
$"{string.Join(",", autocallmonthlyDates.Select(O => baseTrade.trade_autocall.KOBarrier.OtcFormatFlex(2)))};" +
$"{string.Join(",", autocallmonthlyDates.Select(O => baseTrade.trade_autocall.Coupon.OtcFormatFlex(2)))}";
baseTrade.trade_autocall.KOObservationDates = dbTrade.trade_autocall.KOObservationDates;
}
dbTrade.trade_autocall = InnerSaveExtend(baseTrade, baseTrade.trade_autocall);
break;
case "雪球期权":
if (string.IsNullOrEmpty(baseTrade.trade_snowball.KOObservationDates))
{
if (dbTrade.trade_snowball == null)
{
dbTrade.trade_snowball = new trade_snowball();
}
var snowballmonthlyDates = QdpObservationHelper.GetDatesWithFixedTerm(baseTrade.TradeDate ?? System.DateTime.Now, baseTrade.ExerciseDate ?? System.DateTime.Now, "1M", bdc: BusinessDayConvention.Following, alignEnd: true);
dbTrade.trade_snowball.KOObservationDates = $"{string.Join(",", snowballmonthlyDates.Select(O => O.OtcFormatDate()))};" +
$"{string.Join(",", snowballmonthlyDates.Select(O => baseTrade.trade_snowball.KOBarrier.OtcFormatFlex(2)))};" +
$"{string.Join(",", snowballmonthlyDates.Select(O => baseTrade.trade_snowball.KORebate.OtcFormatFlex(2)))}";
if (dbTrade.trade_snowball.KOPayoffType == KOPayoffTypeEnum.Rebate)
{
baseTrade.trade_snowball.KOObservationSettleDates = $"{string.Join(",", snowballmonthlyDates.Select(O => O.OtcFormatDate()))}";
}
baseTrade.trade_snowball.KOObservationDates = dbTrade.trade_snowball.KOObservationDates;
}
dbTrade.trade_snowball = InnerSaveExtend(baseTrade, baseTrade.trade_snowball);
break;
case "区间累积期权":
dbTrade.trade_rangeaccrual = InnerSaveExtend(baseTrade, baseTrade.trade_rangeaccrual);
break;
case "气囊结构":
dbTrade.trade_airbag = InnerSaveExtend(baseTrade, baseTrade.trade_airbag);
break;
case "收益增强结构":
dbTrade.trade_underlying_enhance = InnerSaveExtend(baseTrade, baseTrade.trade_underlying_enhance);
break;
case "远期":
dbTrade.trade_forward = InnerSaveExtend(baseTrade, baseTrade.trade_forward);
break;
case "收益互换":
if (baseTrade.trade_swap.IsGetFloatingProfit)
{
var underlyingManager = DataCacheProvider.GetUnderlyingDataSource().GetData(baseTrade.trade_swap.GetUnderlyingCode);
var CountRatio = underlyingManager?.CountRatio ?? 1;
baseTrade.trade_swap.GetNotional = baseTrade.trade_swap.GetTradeAmount * CountRatio;
dbTrade.OriginalNotional = baseTrade.trade_swap.GetNotional;
dbTrade.Notional = baseTrade.trade_swap.GetNotional ?? 0;
dbTrade.TradeAmount = baseTrade.trade_swap.GetTradeAmount ?? 0;
dbTrade.SpotPrice = baseTrade.trade_swap.GetSpotPrice;
}
if (baseTrade.trade_swap.IsPayFloatingProfit)
{
var underlyingManager = DataCacheProvider.GetUnderlyingDataSource().GetData(baseTrade.trade_swap.PayUnderlyingCode);
var CountRatio = underlyingManager?.CountRatio ?? 1;
baseTrade.trade_swap.PayNotional = baseTrade.trade_swap.PayTradeAmount * CountRatio;
dbTrade.OriginalNotional = baseTrade.trade_swap.PayNotional;
dbTrade.Notional = baseTrade.trade_swap.PayNotional ?? 0;
dbTrade.TradeAmount = baseTrade.trade_swap.PayTradeAmount ?? 0;
dbTrade.SpotPrice = baseTrade.trade_swap.PaySpotPrice;
}
DbContext.SaveChanges();
dbTrade.trade_swap = InnerSaveExtend(baseTrade, baseTrade.trade_swap);
dbTrade.get_trade_swap_details = InnerSaveTradeSwapDetail(baseTrade, baseTrade.get_trade_swap_details, true);
dbTrade.pay_trade_swap_details = InnerSaveTradeSwapDetail(baseTrade, baseTrade.pay_trade_swap_details, false);
if (baseTrade.ParentTradeId > 0)
{
var detail = DbContext.trade_swap_detail.FirstOrDefault(x => x.TradeId == baseTrade.ParentTradeId && x.ChildTradeId == baseTrade.id);
if (detail != null)
{
detail.LongShort = detail.IsForGet ? baseTrade.trade_swap.GetLongShort : baseTrade.trade_swap.PayLongShort;
detail.Notional = detail.IsForGet ? baseTrade.trade_swap.GetNotional : baseTrade.trade_swap.PayNotional;
detail.UnderlyingCode = detail.IsForGet ? baseTrade.trade_swap.GetUnderlyingCode : baseTrade.trade_swap.PayUnderlyingCode;
detail.SpotPrice = detail.IsForGet ? baseTrade.trade_swap.GetSpotPrice : baseTrade.trade_swap.PaySpotPrice;
detail.OriginalNotional = detail.Notional;
}
else
{
detail = new trade_swap_detail()
{
IsForGet = baseTrade.trade_swap.IsGetFloatingProfit
};
detail.LongShort = detail.IsForGet ? baseTrade.trade_swap.GetLongShort : baseTrade.trade_swap.PayLongShort;
detail.Notional = detail.IsForGet ? baseTrade.trade_swap.GetNotional : baseTrade.trade_swap.PayNotional;
detail.UnderlyingCode = detail.IsForGet ? baseTrade.trade_swap.GetUnderlyingCode : baseTrade.trade_swap.PayUnderlyingCode;
detail.SpotPrice = detail.IsForGet ? baseTrade.trade_swap.GetSpotPrice : baseTrade.trade_swap.PaySpotPrice;
detail.OriginalNotional = detail.Notional;
detail.TradeId = baseTrade.ParentTradeId;
detail.ChildTradeId = baseTrade.id;
DbContext.trade_swap_detail.Add(detail);
}
DbContext.SaveChanges();
}
break;
case "现金流交易":
dbTrade.trade_cashflow = InnerSaveExtend(baseTrade, baseTrade.trade_cashflow);
break;
case "自定义交易":
dbTrade.trade_custom = InnerSaveExtend(baseTrade, baseTrade.trade_custom);
break;
case "累计期权":
dbTrade.trade_accumulator_option = InnerSaveExtend(baseTrade, baseTrade.trade_accumulator_option);
break;
case "Risky期权":
dbTrade.trade_risky_option = InnerSaveExtend(baseTrade, baseTrade.trade_risky_option);
break;
default: return 0;
}
return useSaveChange ? DbContext.SaveChanges() : 0;
}
private List<trade_swap_detail> InnerSaveTradeSwapDetail(trade baseTrade, List<trade_swap_detail> tradeSwapDetails, bool isForGet)
{
if (tradeSwapDetails != null && tradeSwapDetails.Any())
{
var tradeSwapDetailsExist = DbContext.trade_swap_detail.Where(x => x.TradeId == baseTrade.id && x.IsForGet == isForGet);
DbContext.trade_swap_detail.RemoveRange(tradeSwapDetailsExist);
tradeSwapDetails.ForEach(x =>
{
x.ExerciseDate = baseTrade.ExerciseDate;
x.IsForGet = isForGet;
x.OriginalNotional = x.Notional;
x.SwapTimeAndRate = isForGet ? baseTrade.trade_swap.PaySwapTimeAndRate : baseTrade.trade_swap.GetSwapTimeAndRate;
x.TradeId = baseTrade.id;
SetDBModelOpt(x);
});
DbContext.trade_swap_detail.AddRange(tradeSwapDetails);
DbContext.SaveChanges();
}
return tradeSwapDetails;
}
//保存扩展数据
private T InnerSaveExtend<T>(trade baseTrade, T extend) where T : TradeExtendBase
{
SetDBModelOpt(extend);
extend.TradeId = baseTrade.id;
var exist = isAddNew ? null : DbContext.Set<T>().FirstOrDefault(n => n.TradeId == baseTrade.id);
if (exist == null)
{
extend.id = 0;
DbContext.Set<T>().Add(extend);
}
else
{
extend.id = exist.id;
UpdateEntity(exist, extend);
}
return extend;
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,51 @@
namespace YLErp.Modules.TradeModule.OrderModule
{
partial class TradeSavePreHandler
{
private static void CheckSnowball(trade req)
{
var snowball = req.trade_snowball;
if (snowball.PrepaymentUsed)
{
if (snowball.SpreadStrikeAtMaturity1 == null)
{
throw new ServiceException("敲入执行价格 必须填写");
}
snowball.KOObservationDates = snowball.KOObservationDates?.Trim(new[] { ' ', ';' });
if (string.IsNullOrWhiteSpace(snowball.KOObservationDates))
{
throw new ServiceException("敲出观察频率 必须填写");
}
req.Strike = snowball.SpreadStrikeAtMaturity1;
snowball.IsAnnualized2 = false;
snowball.AnnualizeFactor2 = 1;
req.MetaDic[nameof(snowball.AnnualizeFactor2)] = "/";
snowball.KOPayoffType = KOPayoffTypeEnum.Rebate;
snowball.KIPayoffType = KIPayoffTypeEnum.Prepayment;
}
else
{
if (!snowball.IsAnnualized2 || !snowball.AnnualizeFactor2.HasValue)
{
snowball.AnnualizeFactor2 = 1;
req.MetaDic[nameof(snowball.AnnualizeFactor2)] = "/";
}
if (snowball.KIPayoffType == KIPayoffTypeEnum.None)
{
req.Strike = req.IsMoneynessOptionData ? 1 : req.SpotPrice;
}
else
{
req.Strike = snowball.SpreadStrikeAtMaturity1;
}
}
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,537 @@
using YLErp.BLL;
using YLErp.BLL.Eod;
using YLErp.Configuration;
using YLErp.Modules.CalculationModule;
namespace YLErp.Modules.TradeModule.OrderModule
{
/// <summary>
/// 不要再合并3.9
/// </summary>
public class TradeTerminationAbstractService
{
/// <summary>
///
/// </summary>
public static string GetAbstractInfoText(trade_cash tc, trade td, bool isUnwind, bool useHeader = false, bool derive = false)
{
var items = isUnwind ? GetUnwindAbstractInfoItems(tc, td).ToList() : GetExerciseAbstractInfoItems(tc, td).ToList();
var bodyIndent = string.Empty;
if (items.Any())
{
//var maxLen = items.Max(n => n.text.Length);
//bodyIndent = new string(' ', maxLen + 1);
//items = items.Select(n => (n.text == "#" ? bodyIndent : n.text.PadLeft(maxLen, ' '), n.value)).ToList();
items = items.Select(n => (n.text == "#" ? new string(' ', 5) : n.text, n.value)).ToList();
}
var headIndent = bodyIndent.Length > 3 ? bodyIndent.Substring(0, bodyIndent.Length - 3) : string.Empty;
var list = new List<(string text, string value)>();
if (derive == true)
{
list = new List<(string text, string value)>() {
(headIndent, PS.Config.CompanyName),
(headIndent, "【场外了结记录摘要】"),
(string.Empty, "####")
};
}
else
{
list = new List<(string text, string value)>();
}
list.AddRange(items);
return string.Join("\r\n", list.Select(
n => string.IsNullOrEmpty(n.text) ? n.value : n.text.EndsWith(" ") ? n.text + n.value : n.text + "" + n.value));
}
/// <summary>
/// 生成平仓摘要
/// </summary>
public static IEnumerable<(string text, string value)> GetUnwindAbstractInfoItems(trade_cash tc, trade td)
{
if (td.TradeType == "远期")
{
return GetUnwindAbstractInfoItems_Forward(tc, td);
}
if (td.TradeType == "雪球期权")
{
return GetUnwindAbstractInfoItems_snowball(tc, td, true);
}
if (td.TradeType == "现金流交易")
{
return GetUnwindAbstractInfoItems_cashflow(tc, td);
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
var QuoteUnitString = " 元/" + (PS.Config.IsUseDisplayNotional ? underlying.QuoteUnitString : underlying.TradeUnitString);
var IsUsePremiumRate = td.IsUsePremiumRate == true;
var SpotPrice = underlying.UnderlyingInstrumentType == "CommodityFutures" ? td.SpotPrice : td.InitialSpotPrice;
var strikeFmt = new Func<double?, string>(d => d.OtcFormatUmPrice(td.IsMoneynessOption == "是"));
var premiumFmt = IsUsePremiumRate
? new Func<double?, string>(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.premiumRateP))
: new Func<double?, string>(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.tradeSinglePrice));
var tradeAmount = td.TradeAmount.OtcFormatNotional() + (td.UnderlyingInstrumentType == "Stock"
? " 股" : " " + td.QuoteUnitSingle);
var tradeType = GetTradeType(td);
var istrade_barrier = td.TradeType == "障碍期权";
//如果是组合标的
if (underlying.UnderlyingType == "组合标的")
{
if (!string.IsNullOrWhiteSpace(td.SyntheticUnderlyingTipsInfo))
{
td.UnderlyingCode = td.SyntheticUnderlyingTipsInfo;
}
else
{
td.UnderlyingCode = synthetic_underlyingBLL.GetUnderlyingTipsInfo(td.UnderlyingCode);
}
}
var list = new List<(string, string)>();
if (PS.Config.Is厦门象屿)
{
list.Add(("平仓信息", ""));
}
list.AddRange(new[]{
("交易编号", td.TradeNumber),
("开仓日期", td.TradeDate.OtcFormatDate()),
("开仓方向", td.ClientName),
("#", td.BuySell == "买入" ? "卖出" : "买入"),
("期权类型",(PS.Config.Is光大光子 && td.TradeType=="自定义交易")?td.StructureIntroduction : tradeType),
("标的代码",td.UnderlyingCode),
});
if (istrade_barrier)
{
list.Add(("观察频率", td.trade_barrier_option.ObservationDates ?? "每日观察"));
list.Add(("报价单位", QuoteUnitString));
list.Add(("障碍水平", strikeFmt(td.trade_barrier_option.BarrierPrice)));
}
var actualExerciseDate = td.ExerciseDate;
if (td.MetaDic == null || td.MetaDic.Count == 0)
{
var exerciseDate = new TradeMetaService(OptUserInfo.SystemUser).GetTradeMeta(td.id, "ActualExerciseDate");
if (!string.IsNullOrWhiteSpace(exerciseDate) && DateTime.TryParse(exerciseDate, out var tempDate))
{
actualExerciseDate = tempDate;
}
}
list.Add(("执行价格", strikeFmt(td.Strike)));
list.Add(("到期日期", actualExerciseDate.OtcFormatDate()));
if (istrade_barrier)
{
list.Add(("补偿金额", IsUsePremiumRate ? premiumFmt(td.trade_barrier_option.RebateRate) : strikeFmt(td.trade_barrier_option.Rebate)));
list.Add(("高障碍补偿金额", IsUsePremiumRate ? premiumFmt(td.trade_barrier_option.RebateHighRate) : strikeFmt(td.trade_barrier_option.RebateHigh)));
list.Add(("补偿支付", td.trade_barrier_option.RebateTypeCn));
}
list.Add(("平仓日期", tc.ValueDate.OtcFormatDate()));
bool ActualHasMinusValueOptions = valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1 ? ConsTrade.HasMinusValueOptions.Contains(td.TradeType) : !ConsTrade.HasMinusValueOptions.Contains(td.TradeType);
if (IsUsePremiumRate)
{
list.Add(("标的价格", td.SpotPrice.OtcFormatUmPrice() + " (开仓)"));
list.Add((new string(' ', 5), tc.FinalPrice.OtcFormatUmPrice() + " (平仓)"));
var premiumRate = td.PremiumRate * (valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1 ? EodOperationBase.GetSign(td.BuySell) : 1);
list.Add(("期权费率", premiumFmt(premiumRate) + " (开仓) "));
//计算出交易员角度的值
var unwindPricePercentRate = tc.UnwindPricePercentRate * (ActualHasMinusValueOptions ? 1 : EodOperationBase.GetSign(td.BuySell));
//结算视角需要客户视角
unwindPricePercentRate *= (valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1 ? -1 : 1);
list.Add((new string(' ', 5), premiumFmt(unwindPricePercentRate) + "(平仓)"));
}
else
{
using (var db = DbContextFactory.GetYLDbContext())
{
list.Add(("标的价格", td.SpotPrice.OtcFormatUmPrice() + " (开仓)"));
list.Add((new string(' ', 5), tc.FinalPrice.OtcFormatUmPrice() + " (平仓)"));
var openPrice = td.TradeSinglePrice * (valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1 ? EodOperationBase.GetSign(td.BuySell) : 1);
list.Add((" 权利金", premiumFmt(openPrice) + " (开仓) "));
//计算出交易员角度的值
var unwindPrice = tc.UnwindPrice * (ActualHasMinusValueOptions ? 1 : EodOperationBase.GetSign(td.BuySell));
//结算视角需要客户视角
unwindPrice *= (valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1 ? -1 : 1);
list.Add((new string(' ', 5), premiumFmt(unwindPrice) + "(平仓)"));
}
}
var amount = tc.Amount * (valuedateBLL.SystemDate.UnwindAmountAngle == 1 ? -1 : EodOperationBase.GetSign(td.BuySell));
if (IsUsePremiumRate)
{
list.AddRange(new[] {
("平仓比例", tc.UnwindPercentRate.OtcFormatPercent()),
("平仓总额", (amount).OtcFormatMoney()+"元"),
("实现盈亏",(-TradeCalcHelper.CalcChildTradeSumWinLoss(td,tc,IsUsePremiumRate,underlying.CountRatio)).OtcFormatMoney()+" 元")
});
}
else
{
list.AddRange(new[] {
("平仓数量",(td.UnderlyingInstrumentType=="Stock"?tc.UnwindNotional.OtcFormatNotional()+"股":
tc.UnwindTradeAmount.OtcFormatNotional(underlying.CountRatio,PS.Config.IsUseDisplayNotional)+ " " +(td.QuoteUnitSingle == "吨" &&PS.Config.IsUseDisplayNotional&& underlying.UnderlyingType == "鸡蛋" ? "半吨":td.QuoteUnitSingle) )),
("平仓总额", (amount).OtcFormatMoney()+"元"),
("实现盈亏",(-TradeCalcHelper.CalcChildTradeSumWinLoss(td,tc,IsUsePremiumRate,underlying.CountRatio)).OtcFormatMoney()+" 元")
});
}
return list;
}
/// <summary>
/// 生成行权摘要
/// </summary>
public static IEnumerable<(string text, string value)> GetExerciseAbstractInfoItems(trade_cash tc, trade td)
{
if (td.TradeType == "雪球期权")
{
return GetUnwindAbstractInfoItems_snowball(tc, td, false);
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
var IsUsePremiumRate = td.IsUsePremiumRate == true;
var QuoteUnitString = "";
if (underlying != null)
{
QuoteUnitString = " 元/" + (PS.Config.IsUseDisplayNotional ? underlying.QuoteUnitString : underlying.TradeUnitString);
var SpotPrice = underlying.UnderlyingInstrumentType == "CommodityFutures" ? td.SpotPrice : td.InitialSpotPrice;
}
///行权价格式
var strikeFmt = new Func<double?, string>(d => d.OtcFormatUmPrice(td.IsMoneynessOption == "是"));
var premiumFmt = IsUsePremiumRate
? new Func<double?, string>(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.premiumRateP))
: new Func<double?, string>(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.tradeSinglePrice));
var single = new Func<double?, string>(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.tradeSinglePrice));
var tradeAmount = td.TradeAmount.OtcFormatNotional() + (td.UnderlyingInstrumentType == "Stock"
? " 股" : " " + td.QuoteUnitSingle);
var istrade_barrier = td.TradeType == "障碍期权";
var actionName = "行权";
//如果是组合标的
if (underlying != null)
{
if (underlying.UnderlyingType == "组合标的")
{
if (!string.IsNullOrWhiteSpace(td.SyntheticUnderlyingTipsInfo))
{
td.UnderlyingCode = td.SyntheticUnderlyingTipsInfo;
}
else
{
td.UnderlyingCode = synthetic_underlyingBLL.GetUnderlyingTipsInfo(td.UnderlyingCode);
}
}
}
var list = new List<(string, string)>();
if (PS.Config.Is厦门象屿)
{
list.Add(("行权信息", ""));
}
list.AddRange(new[] {
("交易编号", td.TradeNumber),
("开仓日期", td.TradeDate.OtcFormatDate()),
("开仓方向", td.ClientName),
("#", td.BuySell == "买入" ? "卖出" : "买入"),
("期权类型", td.StructureType!=null?td.StructureType: GetTradeType(td)),
("标的代码",td.UnderlyingCode),
});
if (istrade_barrier)
{
list.Add(("观察频率", td.trade_barrier_option.ObservationDates ?? "每日观察"));
list.Add(("报价单位", QuoteUnitString));
list.Add(("障碍水平", strikeFmt(td.trade_barrier_option.BarrierPrice)));
}
if (td.TradeType != "雪球期权" && td.TradeType != "凤凰期权")
{
list.Add(("执行价格", strikeFmt(td.Strike)));
}
list.Add(("到期日期", td.ExerciseDate.OtcFormatDate()));
if (istrade_barrier)
{
tradeBLL.SetFieldsByTradeType(td);
list.Add(("补偿金额", IsUsePremiumRate ? premiumFmt(td.trade_barrier_option.RebateRate) : premiumFmt(td.trade_barrier_option.Rebate)));
list.Add(("高障碍补偿金额", IsUsePremiumRate ? premiumFmt(td.trade_barrier_option.RebateHighRate) : strikeFmt(td.trade_barrier_option.RebateHigh)));
list.Add(("补偿支付", td.trade_barrier_option.RebateTypeCn));
}
if (IsUsePremiumRate)
{
list.Add(("期权费率", premiumFmt(td.PremiumRate) + " (开仓) "));
}
else
{
list.Add((" 权利金", premiumFmt(td.TradeSinglePrice ?? 0) + " (开仓) "));
}
list.Add(($"{actionName}日期", tc.ValueDate.ToString("yyyy-MM-dd")));
if (td.UnderlyingInstrumentType == "CommodityFutures")
{
list.Add(("标的价格", td.SpotPrice.OtcFormatUmPrice() + " (开仓)"));
list.Add((new string(' ', 5), (tc.FinalPrice ?? 0).OtcFormatUmPrice() + (PS.Config.Is厦门象屿 ? "(到期)" : "(行权)")));
}
else
{
list.Add(("标的价格", td.InitialSpotPrice.OtcFormatUmPrice() + " (开仓)"));
list.Add((new string(' ', 5), tc.FinalPrice.OtcFormatUmPrice() + $" ({actionName})"));
}
var UnwindPrice = 0.00;
if (tc.UnwindPrice == null)
{
UnwindPrice = 0.00;
}
else
{
UnwindPrice = Math.Abs(tc.UnwindPrice.Value);
}
if (underlying != null)
{
list.AddRange(new[] {
($"{actionName}收益",single(UnwindPrice)+ " 元"),
($"{actionName}数量",(tc.IsLastAction? tc.Notional / underlying.CountRatio: (tc.UnwindTradeAmount!=null?tc.UnwindTradeAmount:0.0000)).OtcFormatNotional(underlying.CountRatio,PS.Config.IsUseDisplayNotional)+ " " +(PS.Config.IsUseDisplayNotional ? underlying.QuoteUnitString : underlying.TradeUnitString)),
($"{actionName}总额",(-tc.Amount).OtcFormatMoney()+ " 元"),
});
}
list.Add(("实现盈亏", (-TradeCalcHelper.CalcChildTradeSumWinLoss(td, tc)).OtcFormatMoney() + " 元"));
return list;
}
private static string GetTradeType(trade td)
{
var result = "";
switch (td.StructureType ?? td.TradeType)
{
case "远期":
case "掉期":
result = (td.StructureType.TrimToNull() ?? td.TradeType) + (td.OptionType == "看涨" || td.OptionType == "多头" ? "多头" : "空头");
break;
case "二元期权":
result = td.ExerciseMode == "American" ? td.ExerciseModeCn + td.TradeType.Replace("期权", "") + "期权" : td.ExerciseModeCn + td.TradeType.Replace("期权", "") + td.OptionType + "期权";
break;
case "雪球期权":
result = "雪球 " + td.OptionType;
break;
case "双鲨期权":
result = td.ExerciseModeCn + td.TradeType.Replace("期权", "") + td.OptionType + "期权";
break;
case "亚式期权":
case "香草期权":
case "障碍期权":
case "合成价差期权":
case "累计期权":
if (td.ParentTradeId == 0)
{
result = PS.Config.Is瑞达 && td.TradeType == "香草期权" ? td.ExerciseModeCn + td.OptionType + "期权" : td.ExerciseModeCn + td.TradeType.Replace("期权", "") + td.OptionType + "期权";
}
else
{
var tradelists = DbContextFactory.GetYLDbContext().trade.Where(x => x.id == td.ParentTradeId).FirstOrDefault();
result = tradelists?.StructureType ?? tradelists?.TradeType ?? td.StructureType ?? td.TradeType;
}
break;
case "现金流交易":
result = td.TradeType;
break;
default:
result = td.TradeType;
switch (td.TradeType)
{
case "结构化交易":
result = td.StructureType;
break;
case "凤凰期权":
case ConsGlobal.TradeType.CashFlow:
case ConsGlobal.TradeType.Forward:
case ConsGlobal.TradeType.PayoffSwap:
break;
case "自定义交易":
result = td.StructureIntroduction.TrimToNull() ?? td.StructureType.TrimToNull() ?? td.TradeType;
break;
case "气囊结构":
case "区间累积期权":
case "收益增强结构":
result = td.ExerciseModeCn + td.TradeType;
break;
default:
result = td.ExerciseModeCn + td.TradeType.Replace("期权", "") + td.OptionType + "期权";
break;
}
break;
}
return result;
}
/// <summary>
/// 雪球期权生成交易摘要
/// </summary>
public static IEnumerable<(string text, string value)> GetUnwindAbstractInfoItems_snowball(trade_cash tc, trade td, bool isUnwind)
{
var snowball = td.trade_snowball;
if (snowball == null)
{
throw new ServiceException("雪球期权扩展信息不存在,无法生成交易摘要");
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
var QuoteUnitString = " 元/" + (PS.Config.IsUseDisplayNotional ? underlying.QuoteUnitString : underlying.TradeUnitString);
var IsUsePremiumRate = td.IsUsePremiumRate == true;
var SpotPrice = underlying.UnderlyingInstrumentType == "CommodityFutures" ? td.SpotPrice : td.InitialSpotPrice;
var strikeFmt = td.IsMoneynessOption == "是"
? new Func<double?, string>(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.percent))
: new Func<double?, string>(d => OtcFormatExtensions.OtcFormatFlex(d, 2, 4));
var premiumFmt = IsUsePremiumRate
? new Func<double?, string>(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.premiumRateP))
: new Func<double?, string>(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.tradeSinglePrice));
var tradeAmount = td.TradeAmount.OtcFormatNotional() + (td.UnderlyingInstrumentType == "Stock"
? " 股" : " " + td.QuoteUnitSingle);
var list = new List<(string, string)>();
var action = tc.Action.Substring(5, 2);
if (PS.Config.Is厦门象屿)
{
list.Add(($"{action}信息", ""));
}
list.AddRange(new[] {
("交易编号", td.TradeNumber),
("开仓日期", td.TradeDate.OtcFormatDate()),
("开仓方向", td.ClientName),
("#", td.BuySell == "买入" ? "卖出" : "买入"),
("期权类型", GetTradeType(td)),
("标的名称",td.UnderlyingAssetName),
("标的代码",td.UnderlyingCode),
("名义本金",OtcFormatExtensions.OtcFormat(td.StockEqvNotionalToShow, OtcFormatFlag.StockEqvNotional))
});
if (snowball.KORebate > 0)
{
list.Add(("  票息", snowball.KORebate.OtcFormatPercent()));
}
//var suffix = isUnwind ? " (平仓)" : "(行权)";
var action_2 = $"({action})";
list.Add(("期初价格", td.SpotPrice.OtcFormatUmPrice()));
if (!snowball.IsInitialKnockedIn)
{
list.Add(("敲入价格", strikeFmt(snowball.KIBarrier)));
}
else
{
list.Add(("初始敲入", "是"));
}
list.Add(("敲出价格", strikeFmt(snowball.KOBarrier)));
list.Add(("执行价格", strikeFmt(td.Strike)));
list.Add(("到期日期", td.ExerciseDate.OtcFormatDate()));
list.Add(("终止价格", tc.FinalPrice.OtcFormatUmPrice() + action_2));
list.Add(("终止日期", tc.ValueDate.OtcFormatDate()));
var amount = tc.Amount * (valuedateBLL.SystemDate.UnwindAmountAngle == 1 ? -1 : EodOperationBase.GetSign(td.BuySell));
list.Add(("结算金额", (amount).OtcFormatMoney() + "元"));
return list;
}
/// <summary>
/// 远期平仓摘要
/// </summary>
public static IEnumerable<(string text, string value)> GetUnwindAbstractInfoItems_Forward(trade_cash tc, trade td)
{
var snowball = td.trade_forward;
if (snowball == null)
{
throw new ServiceException("远期扩展信息不存在,无法生成交易摘要");
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
var QuoteUnitString = " 元/" + (PS.Config.IsUseDisplayNotional ? underlying.QuoteUnitString : underlying.TradeUnitString);
var IsUsePremiumRate = td.IsUsePremiumRate == true;
var strikeFmt = new Func<double?, string>(d => d.OtcFormatUmPrice(td.IsMoneynessOption == "是"));
var premiumFmt = IsUsePremiumRate
? new Func<double?, string>(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.premiumRateP))
: new Func<double?, string>(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.tradeSinglePrice));
var tradeAmount = td.TradeAmount.OtcFormatNotional() + (td.UnderlyingInstrumentType == "Stock"
? " 股" : " " + td.QuoteUnitSingle);
var winloss = TradeCalcHelper.CalcWinLoss(tradeType: td.TradeType, buySell: td.BuySell, tradePrice: td.TradePrice ?? 0, tcUnwindPercent: tc.UnwindPercentRate ?? (tc.UnwindNotional / td.OriginalNotional) ?? 0, tcAmount: tc.Amount);
var list = new List<(string, string)>();
if (PS.Config.Is厦门象屿)
{
list.Add(("平仓信息", ""));
}
var actualExerciseDate = td.ExerciseDate;
if (td.MetaDic == null || td.MetaDic.Count == 0)
{
var exerciseDate = new TradeMetaService(OptUserInfo.SystemUser).GetTradeMeta(td.id, "ActualExerciseDate");
if (!string.IsNullOrWhiteSpace(exerciseDate) && DateTime.TryParse(exerciseDate, out var tempDate))
{
actualExerciseDate = tempDate;
}
}
list.AddRange(new[] {
("交易编号", td.TradeNumber),
("开仓日期", td.TradeDate.OtcFormatDate()),
("开仓方向", td.ClientName),
("#", td.BuySell == "买入" ? "卖出" : "买入"),
("结构类型", (td.StructureType.TrimToNull()??td.TradeType) + (td.OptionType == "看涨" ? "多头" : "空头")),
("标的代码",td.UnderlyingCode),
("执行价格",td.Strike.OtcFormatUmPrice(td.IsMoneynessOption == "是")),
("到期日期", actualExerciseDate.OtcFormatDate()),
("平仓日期", tc.ValueDate.OtcFormatDate()),
("标的价格", td.SpotPrice.OtcFormatUmPrice()),
(new string(' ', 5),tc.FinalPrice.OtcFormatUmPrice() + "(平仓)"),
("平仓数量",td.UnderlyingInstrumentType=="Stock"?tc.UnwindNotional.OtcFormatNotional()+"股":
tc.UnwindTradeAmount.OtcFormatNotional(underlying.CountRatio,PS.Config.IsUseDisplayNotional)+ " " +(td.QuoteUnitSingle == "吨" && underlying.UnderlyingType == "鸡蛋" ? "半吨":td.QuoteUnitSingle)),
("平仓总额", (-tc.Amount).OtcFormatMoney() + "元"), //客户角度,故为相反金额
("实现盈亏",(-winloss).OtcFormatMoney() + " 元")
});
return list;
}
/// <summary>
/// 现金流平仓摘要
/// </summary>
public static IEnumerable<(string text, string value)> GetUnwindAbstractInfoItems_cashflow(trade_cash tc, trade td)
{
var cashflow = td.trade_cashflow;
if (cashflow == null)
{
throw new ServiceException("现金流扩展信息不存在,无法生成交易摘要");
}
var list = new List<(string, string)>();
if (PS.Config.Is厦门象屿)
{
list.Add(("平仓信息", ""));
}
//客户角度,故为相反金额
var amount = tc.Amount * (valuedateBLL.SystemDate.UnwindAmountAngle == 1 ? -1 : EodOperationBase.GetSign(td.BuySell));
list.AddRange(new[] {
("交易编号", td.TradeNumber),
("开仓日期", td.TradeDate.OtcFormatDate()),
("开仓方向", td.ClientName),
("#", td.BuySell == "买入" ? "卖出" : "买入"),
("平仓日期", tc.ValueDate.OtcFormatDate()),
("名义本金",(tc.UnwindPercentRate * td.OriginalStockEqvNotional).OtcFormatNotional() + "元"),
("平仓总额", (amount).OtcFormatMoney() + "元"),
});
return list;
}
}
}