using Microsoft.EntityFrameworkCore;
using System.Text;
using YLErp.BLL;
using YLErp.BLL.Calculation.V2;
using YLErp.BLL.Eod;
using YLErp.BLL.EodSettlement;
using YLErp.Commons;
using YLErp.DBModels.Consts;
using YLErp.DBModels.Enums;
using YLErp.DBModels.Helpers;
using YLErp.Modules.ClientModule;
using YLErp.Modules.DataProviderModule;
using YLErp.QdpModule;
namespace YLErp.Modules.TradeModule.DealModule
{
///
/// 将单个交易标记为到期(并增加一条收益为零的trade_cash记录,直接到期的交易记录期末价格为0)
///
public class TradeExpireConfirmService : TradeServiceBase
{
public TradeExpireConfirmService(OptUserInfo userInfo) : base(userInfo)
{
}
public TradeExpireConfirmService(YLBaseService baseService) : base(baseService)
{
}
public TradeExpireConfirmResult TradeExpireConfirm(int tradeId, double spotPrice = 0)
{
var td = DbContext.trade.Find(tradeId);
var error = checkCanTradeExpire(td);
//如果有配对交易,配对交易也要到期
if (!string.IsNullOrEmpty(td.PairTrade))
{
var pairid = Convert.ToInt32(td.PairTrade);
var pairtd = DbContext.trade.Find(pairid);
if (pairtd.TradeStatus == ConsTrade.已到期)
{
//执行单笔已到期
}
else
{
var error2 = checkCanTradeExpire(pairtd);
if (string.IsNullOrEmpty(error) && string.IsNullOrEmpty(error2))
{
//2个交易都可以到到期才到期
tradeExpireInner(td, spotPrice);
tradeExpireInner(pairtd, spotPrice);
//生成文档
if (PS.Config.IsAutoGenerateContracts)
{
new TradeContractGenerateService(this).GenerateContractsAsync(new List { td.id, pairid });
}
AddTradeOperationHistoryAndSetParentTradeInfo(false, td, "过期交易到期");
AddTradeOperationHistoryAndSetParentTradeInfo(false, pairtd, "过期交易到期");
DbContext.SaveChanges();
return new TradeExpireConfirmResult(td)
{
Success = true,
Message = $"确认到期成功,且配对交易{pairtd.TradeNumber}也到期成功"
};
}
return new TradeExpireConfirmResult(td)
{
Success = false,
Message = error + error2
};
}
}
//无匹配交易
if (string.IsNullOrEmpty(error))
{
tradeExpireInner(td, spotPrice);
//生成文档
if (PS.Config.IsAutoGenerateContracts)
{
new TradeContractGenerateService(this).GenerateContractsAsync(new List { td.id });
}
SaveTradeOperationHistory(td, "过期交易到期");
return new TradeExpireConfirmResult(td) { Success = true, Message = "确认到期成功" };
}
return new TradeExpireConfirmResult(td) { Success = false, Message = error };
}
///
/// 检查交易是否可以到期,返回错误信息,空为成功
///
private string checkCanTradeExpire(trade td)
{
if (PS.Config.TradeElement.ExecuteAfterGeneratedConfirmDoc && !td.HasGeneratedConfirmBook() && td.TradeType != "自定义交易")
{
return "请先去生成交易确认书";
}
var valueDate = valuedateBLL.ValueDate;
if (td.TradeStatus == ConsTrade.确认成交 && ((td.ExerciseMode == "European" && td.ExerciseDate <= valueDate) || (td.ExerciseMode == "American" && valueDate >= td.StartDate) || string.IsNullOrEmpty(td.ExerciseMode)))
{
return string.Empty;
}
return $"确认到期失败,交易必须为[确认成交]状态并且[欧式期权]必须到期日{td.ExerciseDate}之后,美式期权必须在开始日{td.StartDate}之后";
}
///
/// 执行到期
///
private void tradeExpireInner(trade td, double spotPrice = 0)
{
//到期日期如果是节假日,取节假日后的第一个工作日
var exerciseDate = QdpCalendarHelper.GetNonHoliday(td.ExerciseDate ?? valuedateBLL.ValueDate);
var valueDate = valuedateBLL.ValueDate;
td.TradeStatus = ConsTrade.已到期;
td.UnWindDate = exerciseDate;
td.OptDate = DateTime.Now;
// 直接到期的交易设置
var tc = DbContext.trade_cash.FirstOrDefault(t => t.TradeId == td.id && t.Action == ClientCashInCashOut.系统操作_行权费 && !t.IsDeleted);
if (tc == null)
{
tc = new trade_cash();
DbContext.trade_cash.Add(tc);
}
#region 设置期末价格和执行价格
var finalPrice = EodPriceQueryService.TryGetEodPrice(exerciseDate, td.UnderlyingCode, out var eodPrice)
? eodPrice.GetPrice(td.SettlementType) : 0;
if (finalPrice <= 0)
{
throw new Exception("标的收盘价不合法,请检查后再进行到期操作");
}
SettlementCalcCommons.SetPossibleExec(tc, td, finalPrice, true);
if (td.TradeType != "亚式期权")
{
tc.FinalPrice = finalPrice;
tc.Strike = td.Strike;
}
else
{
tc.SpotPrice = spotPrice;
}
//修改只收买方行权费
tc.ExtraAmount = Math.Abs(td.StockEqvNotional * (valuedateBLL.SystemDate.ExerciseCostRatioReal ?? 0)) * ("卖出".Equals(td.BuySell) ? 1 : 0);
tc.Amount += tc.ExtraAmount ?? 0;
#endregion
tc.ValidState = "Valid";
tc.OptId = UserId;
tc.OptName = UserName;
tc.OptDate = DateTime.Now;
tc.Action = ClientCashInCashOut.系统操作_行权费;
tc.IsLastAction = true;
tc.ValueDate = exerciseDate;
tc.Notional = td.Notional;
var CountRatio = UnderlyingDataProvider.GetCountRatio(td.UnderlyingCode);
tc.TradeAmount = tc.Notional / CountRatio;
tc.Status = TradeCashStatusEnum.已执行;
tc.TradeType = td.BuySell;
tc.TradeId = td.id;
tc.ParentTradeId = td.ParentTradeId;
tc.ExerciseWay = TradeCashExerciseWayEnum.到期行权;
tc.UnwindVol = 0;//到期交易不需要存平仓波动率
DbContext.SaveChanges();
if (tc.IsPossibleExec)
{
new TradeCashService(this).SaveTradeCashDetail(tc);
//增加出入金记录
var cl = DataCacheProvider.GetClientDataSource().GetData(td.ClientId);
var ee = new ClientCashInCashOut
{
Direction = "应收",
Number = UniqueTimeId.GetStr(),
ClientId = cl.id,
ClientNumber = cl.Number,
ClientName = cl.Name,
//客户和交易员反方向
Money = tc.Amount * -1,
HappenDate = tc.ValueDate,
State = ClientCashInCashOut.已确认,
//ee.OpenBankId = bc.id + "";
//ee.OpenBankCard = bc.Card;
TradeId = tc.TradeId,
TradeCashId = tc.id,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = tc.OptDate,
CreatorId = tc.OptId,
CreatorName = tc.OptName,
CreateDate = tc.OptDate,
Action = ClientCashInCashOut.系统操作_行权费,
TradeNumber = td.TradeNumber,
IsGroup = td.IsGroup
};
DbContext.ClientCashInCashOut.Add(ee);
td.TradeStatus = ConsTrade.已执行;
}
//结构化子交易到期行权时,检查另外一个兄弟子交易是否已了结,如果已了结,则主交易状态也跟着当前子交易状态变化
if (td.ParentTradeId > 0)
{
var otherTrade = DbContext.trade.Where(x => x.ParentTradeId == td.ParentTradeId && x.id != td.id);
if (otherTrade.All(n => ConsTrade.TradeCompleteStatus.Contains(n.TradeStatus)))
{
var parentTrade = DbContext.trade.Find(td.ParentTradeId);
parentTrade.TradeStatus = td.TradeStatus;
parentTrade.UnWindDate = td.UnWindDate;
}
}
//删除E/Bod数据
RemoveEodTradeAndFutureInfo(false, td.id, tc.ValueDate);
DbContext.SaveChanges();
}
///
/// 将多个交易标记为到期
///
public void MultipleTradeExpireConfirm(IEnumerable tradeIds, out string successMsg)
{
var valueDate = valuedateBLL.ValueDate;
successMsg = "执行到期成功:";
//批量行权到期 获取所有交易到期日小于当前系统日期非通道交易
var buySellList = new List { "卖出", "买入" };
//所有应行权到期的通道自营交易(如果前一天是假日,要显示包含假日的交易)
var preday = QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(-1));
var dateEnd = valueDate.AddDays(1);
IQueryable tradeQuery = DbContext.trade;
if (tradeIds != null && tradeIds.Any(n => n > 0))
{
var selectParentTradeIds = DbContext.trade.Where(t => tradeIds.Contains(t.id) && t.ParentTradeId != 0).Select(x => x.ParentTradeId).ToHashSet().ToArray();
tradeQuery = DbContext.trade.Where(t => tradeIds.Contains(t.id) || tradeIds.Contains(t.ParentTradeId) || selectParentTradeIds.Contains(t.ParentTradeId));
}
tradeQuery = tradeQuery.Where(t => t.ClientId > 0
&& t.ExerciseDate > preday && t.ExerciseDate < dateEnd && t.TradeStatus == ConsTrade.确认成交
&& t.ValidState != "InValid" && t.ClientId > 0 && t.TradeNumber != null
&& !ConsTrade.NonOptionTradeTypes.Contains(t.TradeType) && t.TradeType != "自定义交易");
var needKnockInTradeIds = tradeQuery.Where(t => t.TradeType == "雪球期权" || t.TradeType == "凤凰期权").Select(x => x.id).ToList();
var unKnockInTradeIds = DbContext.trade_autocall.Where(x => needKnockInTradeIds.Contains(x.TradeId) && x.KnockInOutStatus != ConsTrade.KnockState.KnockedIn).Select(x => x.TradeId).Union(DbContext.trade_snowball.Where(x => needKnockInTradeIds.Contains(x.TradeId) && x.KnockInOutStatus != "KnockedIn").Select(x => x.TradeId)).ToList();
tradeQuery = tradeQuery.Where(x => !unKnockInTradeIds.Contains(x.id));
var tradeUnwindTrades = tradeQuery.ToList();
if (!tradeUnwindTrades.Any())
{
throw new ServiceException($"不存在可批量执行到期的交易,或者勾选的交易不可被批量执行到期");
}
var tradeCashList = new List();
var clientCashList = new List();
trade_cash tradeCash = null;
//日终价格
var underlyingIds = tradeUnwindTrades.Select(t => t.UnderlyingId).ToList();
var EodPriceProvider = new EodPriceProvider(valueDate);
//批量结算的全是现金流交易就不用结算价
if (!EodPriceQueryService.CheckDbExists(valueDate) && tradeQuery.Any(t => t.TradeType != "现金流交易"))
{
throw new ServiceException($"当日交易的结算价或收盘价未找到!");
}
var sbMsg = new StringBuilder().AppendLine(successMsg);
var parentTradeIds = new List();
foreach (var t in tradeUnwindTrades)
{
if (t.ParentTradeId > 0 && t.IsGroup == 0)
{
parentTradeIds.Add(t.ParentTradeId);
}
if (PS.Config.TradeElement.ExecuteAfterGeneratedConfirmDoc && !t.HasGeneratedConfirmBook() && t.TradeType != "远期" && t.TradeType != "现金流交易")
{
throw new ServiceException($"交易{t.TradeNumber}的交易确认书没有生成。");
}
double settlePrice = 0;
var CountRatio = 1;
if (t.TradeType != "现金流交易")
{
//结算价
if (EodPriceProvider.TryGetEodPrice(t.UnderlyingCode, out var eodPrice))
{
settlePrice = eodPrice.GetPrice(t.SettlementType);
}
else
{
throw new ServiceException($"交易{t.TradeNumber},标的[{t.UnderlyingCode}]{valueDate}结算价或收盘价或参考价不存在!");
}
CountRatio = UnderlyingDataProvider.GetCountRatio(t.UnderlyingCode);
}
var client = ClientDataQueryService.GetClient(t.ClientId);
if (client == null)
{
throw new ServiceException($"交易{t.TradeNumber}的客户{t.ClientName}在系统中不存在!请检查数据后再操作。");
}
if (t.TradeType == "收益互换")
{
//t.trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == t.id);
//if(t.trade_swap == null)
//{
// throw new ServiceException($"交易{t.TradeNumber}对应的trade_swap数据不存在!");
//}
//var unwindPercentRate = t.OriginalNotional > 0 ? t.Notional / t.OriginalNotional : 0;
//var initialAmount = t.SpotPrice > 0 ? (settlePrice / (t.FinalPrice ?? t.SpotPrice) - 1) * (t.OriginalStockEqvNotional * (t.FinalPrice ?? t.SpotPrice) / t.SpotPrice) * unwindPercentRate * (t.BuySell == "买入" ? 1 : -1) * (t.OptionType == "看涨" ? 1 : -1) : 0;
//int days = (valueDate - (t.UnWindDate ?? t.StartDate.Value)).Days;
//var extraAmount = t.OriginalStockEqvNotional * unwindPercentRate * t.trade_swap.GetSwapRate * ((double)days / t.trade_swap.AnnualDays) * (t.BuySell == "买入" ? -1 : 1);
//var amount = (initialAmount ?? 0) + (extraAmount ?? 0);
//tradeCash = new trade_cash
//{
// ValueDate = valueDate,
// TradeId = t.id,
// ExceciseType = "到期行权",
// CallPut = t.CallPut,
// Notional = t.Notional,
// UnwindNotional = t.Notional,
// TradeAmount = t.Notional / CountRatio,
// UnwindPercentRate = unwindPercentRate,
// NotionalPercentRate = unwindPercentRate,
// FinalPrice = settlePrice.Value,
// Amount = amount,
// ExtraAmount = extraAmount,
// Action = ClientCashInCashOut.系统操作_互换,
// Status = TradeCashStatusEnum.已执行,
// OptId = UserId,
// OptName = UserName,
// OptDate = DateTime.Now,
// ExerciseWay = TradeCashExerciseWayEnum.到期行权
//};
//tradeCashList.Add(tradeCash);
//clientCashList.Add(new ClientCashInCashOut
//{
// Direction = "应收",
// Number = UniqueTimeId.GetStr(),
// ClientId = client.id,
// ClientNumber = client.Number,
// ClientName = client.Name,
// ClientIdentityNumber = client.IdentificationNumber,
// //客户和交易员反方向
// Money = amount * -1,
// HappenDate = valueDate == DateTime.Now.Date ? DateTime.Now : valueDate,
// State = ClientCashInCashOut.已确认,
// TradeId = tradeCash.TradeId,
// OptId = tradeCash.OptId,
// OptName = tradeCash.OptName,
// OptDate = tradeCash.OptDate,
// Action = ClientCashInCashOut.系统操作_互换,
// TradeNumber = t.TradeNumber
//});
//t.TradeStatus = ConsTrade.已到期;
//t.UnWindDate = valueDate;
//t.FinalPrice = settlePrice;
}
else
{
var parentTradeCash = DbContext.trade_cash.OrderByDescending(x => x.id).FirstOrDefault(x => x.TradeId == t.ParentTradeId && x.Action != "系统操作-期权费" && x.Status == null && x.ValidState != "InValid");
var parentTrade = DbContext.trade.Find(t.ParentTradeId);
if (t.IsGroup == 2)
{
//主交易和子交易都是当天到期
if (parentTrade.ExerciseDate > preday && parentTrade.ExerciseDate < dateEnd)
{
if (parentTradeCash == null)
{
parentTradeCash = new trade_cash()
{
Action = ClientCashInCashOut.系统操作_行权费,
ExerciseWay = "到期行权",
IsLastAction = true,
TradeType = parentTrade.BuySell,
Notional = parentTrade.Notional,
TradeAmount = parentTrade.TradeAmount,
UnwindNotional = parentTrade.Notional,
UnwindTradeAmount = parentTrade.TradeAmount,
UnwindPercentRate = parentTrade.OriginalNotional > 0 ? parentTrade.Notional / parentTrade.OriginalNotional : 0,
TradeId = t.ParentTradeId,
HappenedDate = valueDate,
ValueDate = valueDate,
OptId = UserId,
OptName = UserName,
OptDate = DateTime.Now
};
parentTrade.TradeStatus = "已到期";
parentTrade.UnWindDate = valueDate;
parentTrade.FinalPrice = settlePrice;
parentTrade.UnWindNotional = parentTrade.Notional;
parentTrade.Notional = 0;
parentTrade.TradeAmount = 0;
parentTrade.StockEqvNotional = 0;
DbContext.trade_cash.Add(parentTradeCash);
DbContext.SaveChanges();
#region---存入ClientCashInCashOut---
var cl = ClientDataQueryService.GetClient(parentTrade.ClientId, true);
var ee = new ClientCashInCashOut
{
Direction = "应收",
Number = UniqueTimeId.GetStr(),
ClientId = cl.id,
ClientNumber = cl.Number,
ClientName = cl.Name,
HappenDate = parentTradeCash.ValueDate,
State = ClientCashInCashOut.已确认,
OptId = parentTradeCash.OptId,
OptName = parentTradeCash.OptName,
OptDate = parentTradeCash.OptDate,
CreatorId = parentTradeCash.OptId,
CreatorName = parentTradeCash.OptName,
CreateDate = parentTradeCash.OptDate,
TradeId = parentTradeCash.TradeId,
TradeCashId = parentTradeCash.id,
Action = parentTradeCash.Action,
TradeNumber = parentTrade.TradeNumber,
IsGroup = parentTrade.IsGroup
};
DbContext.ClientCashInCashOut.Add(ee);
#endregion
}
}
else
{
if (parentTradeCash == null)
{
//主交易非当日到期
parentTrade.UnWindDate = valueDate;
parentTrade.FinalPrice = settlePrice;
var childrenExerciseDateCount = DbContext.trade.Where(x => x.ParentTradeId == parentTrade.id && x.ValidState != "InValid").Select(x => x.ExerciseDate).Distinct().Count();
parentTrade.UnWindNotional = 1.0 / childrenExerciseDateCount * parentTrade.OriginalNotional;
parentTradeCash = new trade_cash()
{
Action = ClientCashInCashOut.系统操作_平仓费,
ExerciseWay = "提前终止行权",
IsLastAction = false,
TradeType = parentTrade.BuySell,
Notional = parentTrade.Notional,
TradeAmount = parentTrade.TradeAmount,
UnwindNotional = parentTrade.UnWindNotional,
UnwindTradeAmount = parentTrade.UnWindNotional / (parentTrade.CountRatio ?? 1),
UnwindPercentRate = parentTrade.OriginalNotional > 0 ? parentTrade.UnWindNotional / parentTrade.OriginalNotional : 0,
TradeId = t.ParentTradeId,
HappenedDate = valueDate,
ValueDate = valueDate,
OptId = UserId,
OptName = UserName,
OptDate = DateTime.Now
};
parentTrade.Notional -= (parentTradeCash.UnwindNotional ?? 0);
parentTrade.TradeAmount -= (parentTradeCash.UnwindTradeAmount ?? 0);
parentTrade.StockEqvNotional -= ((parentTrade.OriginalStockEqvNotional ?? 0) * (parentTradeCash.UnwindPercentRate ?? 0));
DbContext.trade_cash.Add(parentTradeCash);
DbContext.SaveChanges();
#region---存入ClientCashInCashOut---
var cl = ClientDataQueryService.GetClient(parentTrade.ClientId, true);
var ee = new ClientCashInCashOut
{
Direction = "应收",
Number = UniqueTimeId.GetStr(),
ClientId = cl.id,
ClientNumber = cl.Number,
ClientName = cl.Name,
HappenDate = parentTradeCash.ValueDate,
State = ClientCashInCashOut.已确认,
OptId = parentTradeCash.OptId,
OptName = parentTradeCash.OptName,
OptDate = parentTradeCash.OptDate,
CreatorId = parentTradeCash.OptId,
CreatorName = parentTradeCash.OptName,
CreateDate = parentTradeCash.OptDate,
TradeId = parentTradeCash.TradeId,
TradeCashId = parentTradeCash.id,
Action = parentTradeCash.Action,
TradeNumber = parentTrade.TradeNumber,
IsGroup = parentTrade.IsGroup
};
DbContext.ClientCashInCashOut.Add(ee);
#endregion
}
}
var tradeCashGroupAction = new trade_cash_group_action()
{
TradeId = t.id,
ParentTradeId = t.ParentTradeId,
ParentTradeCashId = parentTradeCash.id,
Status = "已完成",
OptId = UserId,
OptName = UserName,
OptDate = DateTime.Now,
IsFinishedUnwindPercent = true
};
DbContext.trade_cash_group_action.Add(tradeCashGroupAction);
}
tradeCash = new trade_cash
{
ValueDate = valueDate,
TradeId = t.id,
ParentTradeId = t.ParentTradeId,
ExceciseType = "现金",
CallPut = t.CallPut,
Strike = t.IsMoneynessOptionData ? (t.Strike * t.SpotPrice) : t.Strike,
Notional = t.Notional,
UnwindNotional = t.Notional,
UnwindPercentRate = t.OriginalNotional > 0 ? t.Notional / t.OriginalNotional : 0,
FinalPrice = settlePrice,
Action = ClientCashInCashOut.系统操作_行权费,
IsLastAction = true,
Status = TradeCashStatusEnum.已执行,
OptId = UserId,
OptName = UserName,
OptDate = DateTime.Now,
ExerciseWay = TradeCashExerciseWayEnum.到期行权,
TradeType = t.BuySell
};
tradeCash.SpotPrice = DataCacheProvider.GetUnderlyingDataSource().GetPrice(t.UnderlyingCode);
tradeCash.TradeAmount = tradeCash.Notional / CountRatio;
//计算行权收益
SettlementCalcCommons.SetPossibleExec(tradeCash, t, tradeCash.FinalPrice ?? 0.0, true);
if (t.TradeType == "现金流交易")
{
var udm = new underlying_manager
{
QuotationDate = valueDate
};
var OptionValue = ValueCalculator.GetOptionValueResultV2(
userId: OptUser.UserId.ToString(),
underlying: udm,
trade: t,
vols: new double[] { t.StockEqvNotional },
spotPrices: new double[] { udm.Price ?? 0.0 },
fixing: null,
timeToMaturityDays: 0,
preciseTimeMode: true,
request: QdpPricingRequest.BASIC_PRICING);
var amount = OptionValue.Pv;
tradeCash.IsPossibleExec = true;
tradeCash.Amount = OtcFormatHelper.FormatValue(amount, 2);
tradeCash.InitialAmount = OtcFormatHelper.FormatValue(amount, 2);
}
//额外的行权费
//根据买卖方向 针对买方才会收行权费
var ExtraAmount = Math.Abs(t.StockEqvNotional * (valuedateBLL.SystemDate.ExerciseCostRatioReal ?? 0)) * ("卖出".Equals(t.BuySell) ? 1 : 0);
//行权净收益
var Amount = tradeCash.Amount + ExtraAmount;
//判断客户行权如果收益小于0 则行权收益为0 则不可行权
var flag = true;
if (EodOperationBase.GetSign(t.BuySell) * Amount <= 0 && (t.TradeType != "雪球期权" && t.TradeType != "凤凰期权"))
{
Amount = 0;
flag = false;
}
//查看是否可以行权 行权收益为正数时可行权
if (tradeCash.IsPossibleExec && flag)
{
sbMsg.Append("交易编号[").Append(t.TradeNumber).Append("],行权收益:").Append(Amount).AppendLine(",行权。");
tradeCash.Amount = Amount;
tradeCash.ExtraAmount = ExtraAmount;
tradeCash.UnwindType = "全部行权";
t.TradeStatus = ConsTrade.已执行;
clientCashList.Add(new ClientCashInCashOut
{
Direction = "应收",
Number = UniqueTimeId.GetStr(),
ClientId = client.id,
ClientNumber = client.Number,
ClientName = client.Name,
//客户和交易员反方向
Money = Amount * -1,
HappenDate = valueDate == DateTime.Now.Date ? DateTime.Now : valueDate,
State = ClientCashInCashOut.已确认,
//ee.OpenBankId = bc.id + "";
//ee.OpenBankCard = bc.Card;
TradeId = tradeCash.TradeId,
OptId = tradeCash.OptId,
OptName = tradeCash.OptName,
OptDate = tradeCash.OptDate,
CreatorId = tradeCash.OptId,
CreatorName = tradeCash.OptName,
CreateDate = tradeCash.OptDate,
Action = ClientCashInCashOut.系统操作_行权费,
TradeNumber = t.TradeNumber,
IsGroup = t.IsGroup
});
}
else
{
sbMsg.Append("交易编号[").Append(t.TradeNumber).AppendLine("],到期。");
tradeCash.Amount = 0.0;
tradeCash.ExtraAmount = 0.0;
tradeCash.UnwindType = "到期";
tradeCash.ValueDate = t.ExerciseDate.Value;
t.TradeStatus = "已到期";
}
if (t.TradeType != "现金流交易")
{
tradeCash.UnwindPrice = TradeHelper.GetTradeSinglePriceByTradePrice(tradeCash.Amount, t.Notional, t.PrincipalSum(), t.BuySell, t.TradeType, false);
tradeCash.UnwindPricePercentRate = TradeHelper.GetPremiumRateByTradePrice(tradeCash.Amount, t.StockEqvNotional, t.ParticipationRate, t.PrincipalSum(), t.AnnualizeFactor, t.BuySell, t.TradeType, false);
t.FinalPrice = tradeCash.FinalPrice;
}
t.UnWindDate = valueDate;
//行权/到期都不需要平仓波动率
tradeCash.UnwindVol = 0;
tradeCashList.Add(tradeCash);
if (t.IsGroup == 2)
{
tradeCash.ParentTradeCashId = parentTradeCash.id;
parentTradeCash.FinalPrice = settlePrice;
parentTradeCash.Amount += tradeCash.Amount;
parentTradeCash.UnwindPrice = TradeHelper.GetTradeSinglePriceByTradePrice(parentTradeCash.Amount, parentTradeCash.UnwindNotional, parentTrade.PrincipalSum(), parentTrade.BuySell, parentTrade.TradeType, false);
parentTradeCash.UnwindPricePercentRate = TradeHelper.GetPremiumRateByTradePrice(parentTradeCash.Amount, parentTrade.OriginalStockEqvNotional * parentTradeCash.UnwindPercentRate, parentTrade.ParticipationRate, parentTrade.PrincipalSum(), parentTrade.AnnualizeFactor, parentTrade.BuySell, parentTrade.TradeType, false);
//当天到期的子交易均已经到期处理了
if (!DbContext.trade.Any(x => x.ParentTradeId == parentTrade.id && x.ValidState != "InValid" && x.ExerciseDate > preday && x.ExerciseDate < dateEnd && x.id != t.id && !ConsTrade.TradeCompleteStatus.Contains(x.TradeStatus)))
{
parentTradeCash.Status = TradeCashStatusEnum.已执行;
AddTradeOperationHistoryAndSetParentTradeInfo(false, parentTrade, "批量执行到期");
}
}
DbContext.SaveChanges();
}
AddTradeOperationHistoryAndSetParentTradeInfo(false, t, "批量执行到期");
};
if (tradeCashList.Count > 0)
{
DbContext.trade_cash.AddRange(tradeCashList);
DbContext.SaveChanges();
}
if (clientCashList.Count > 0)
{
clientCashList.ForEach(x => x.TradeCashId = tradeCashList.First(y => y.TradeId == x.TradeId).id);
DbContext.ClientCashInCashOut.AddRange(clientCashList);
}
DbContext.SaveChanges();
var tradeCashDetails = new List();
tradeCashList.ForEach(x =>
{
var tradeCashDetail = new trade_cash_detail()
{
TradeId = x.TradeId,
TradeCashId = x.id,
Amount = x.Amount,
ExtraAmount = x.ExtraAmount,
SinglePrice = x.UnwindPrice,
SinglePricePercentRate = x.UnwindPricePercentRate,
Action = x.Action,
ValueDate = x.ValueDate,
OptDate = DateTime.Now,
OptId = x.OptId,
OptName = x.OptName
};
tradeCashDetails.Add(tradeCashDetail);
});
DbContext.trade_cash_detail.AddRange(tradeCashDetails);
DbContext.SaveChanges();
//结构化子交易到期时,检查子交易是否都已了结,如果已了结,则主交易状态也跟着当前子交易状态变化
if (parentTradeIds.Count > 0)
{
foreach (var id in parentTradeIds)
{
var tradeStatus = ConsTrade.确认成交;
var UnwindDate = DateTime.MinValue;
var tradeChildren = DbContext.trade.Where(x => x.ParentTradeId == id);
foreach (var child in tradeChildren)
{
if (ConsTrade.TradeCompleteStatus.Contains(child.TradeStatus))
{
if (child.UnWindDate > UnwindDate)
{
UnwindDate = child.UnWindDate ?? DateTime.MinValue;
tradeStatus = child.TradeStatus;
}
}
else
{
tradeStatus = ConsTrade.确认成交;
}
}
if (tradeStatus != ConsTrade.确认成交)
{
var tradeParent = DbContext.trade.Find(id);
if (tradeParent != null)
{
tradeParent.TradeStatus = tradeStatus;
}
DbContext.SaveChanges();
}
}
}
//生成文档
if (PS.Config.IsAutoGenerateContracts)
{
new TradeContractGenerateService(this).GenerateContractsAsync(tradeCashList.Select(tc => tc.TradeId).ToList());
}
successMsg = sbMsg.ToString();
}
}
///
/// 到期确认操作结果
///
public class TradeExpireConfirmResult
{
public trade Trade;
public bool Success;
public string Message;
public TradeExpireConfirmResult(trade trade)
{
Trade = trade;
}
}
}