using YLErp.BLL;
using YLErp.DBModels.Enums;
using YLErp.DBModels.Helpers;
using YLErp.Modules.EodModule;
using YLErp.QdpModule;
namespace YLErp.Modules.TradeModule.DealModule
{
///
/// 交易回退服务
///
public class TradeBackService : TradeServiceBase
{
public TradeBackService(OptUserInfo userInfo) : base(userInfo)
{
}
public TradeBackService(YLBaseService baseService) : base(baseService)
{
}
public TradeBackService(OptUserInfo userInfo, YLContext dbContext) : base(userInfo, dbContext)
{
}
public trade Execute(int tradeId, bool backToBegin, TradeBackActionEnum actionEnum)
{
var trade = DbContext.trade.Find(tradeId);
if (trade == null)
{
throw new ServiceException("交易数据不存在");
}
new TradeExtendService(UserInfo, DbContext).SetTradeExtend(new[] { trade }, tracking: true);
if (trade.TradeType == "累计期权")
{
backToBegin = true;
if (trade.trade_accumulator_option.SettlementMode == "实物交割" || trade.trade_accumulator_option.SettlementMode == "现金实物合并结算")
{
var query = from ob in DbContext.autocall_observation
join tf in DbContext.trade on ob.ConvTradeNumber equals tf.TradeNumber
where ob.TradeId == trade.id && (ob.SettlementMode == "转远期" || ob.SettlementMode == "转掉期" || ob.SettlementMode == "现金当日&转远期") && tf.ValidState != ConsGlobal.InValid
select ob;
if (query.Any())
{
throw new ServiceException($"操作失败,当前累计期权交易({trade.TradeNumber})已结算为远期交易,请将所有结算后的远期交易删除后重新执行回退操作!");
}
}
}
var valueDate = trade.TradeDate.Value;
var tradeCashIds = new List();
var actions = new List()
{
"系统操作-行权费",
"系统操作-平仓费",
"系统操作-票息",
"系统操作-互换"
};
var tcQuery = DbContext.trade_cash.Where(x => x.TradeId == tradeId && (actions.Contains(x.Action) || x.Action == "系统操作-期权费" && x.ValueDate != trade.TradeDate && x.ValueDate != trade.PremiumPayDate) && x.ValidState != ConsGlobal.InValid && !x.IsDeleted);
var eodTrade = DbContext.eod_trade.Where(O => O.TradeId == tradeId && O.ValueDate == trade.TradeDate).FirstOrDefault();
var originTrade = eodTrade?.trade;
if (originTrade == null)
{
originTrade = trade;
new TradeExtendService(UserInfo, DbContext).SetTradeExtend(new[] { originTrade });
}
var stockEqvNotionalUnwind = (originTrade.OriginalStockEqvNotional ?? 0) - originTrade.StockEqvNotional;
var extensionTimeService = new ExtensionTimeService(UserInfo, DbContext);
if (backToBegin)
{
var tcTemp = DbContext.trade_cash.Where(x => x.TradeId == tradeId && x.Action == "系统操作-期权费" && x.ValidState != ConsGlobal.InValid && !x.IsDeleted).FirstOrDefault();
if (tcTemp == null)
{
throw new ServiceException("未查询到该交易的开仓记录,请删除该笔交易重新操作");
}
originTrade.TradeStatus = ConsTrade.确认成交;
originTrade.OriginalNotional = tcTemp.Notional;
originTrade.Notional = tcTemp.Notional;
originTrade.StockEqvNotional = originTrade.OriginalStockEqvNotional ?? 0;
DividendService.SetDividendTradeData(trade, originTrade);
valueDate = trade.TradeDate.Value;
tradeCashIds.AddRange(tcQuery.Select(O => O.id).ToList());
trade.UnWindDate = null;
trade.FinalPrice = null;
trade.UnWindNotional = null;
trade.UnWindPrice = null;
trade.HasPartialUnWind = null;
extensionTimeService.DelExtensionTime(tradeId, DateTime.MinValue, actionEnum != TradeBackActionEnum.EditMaturityDate);
}
else
{
if (!tcQuery.Any())
{
throw new ServiceException("未查询到该交易的了结记录,不可回退");
}
//有行权记录先回撤行权记录,没有行权记录,依次倒序撤回平仓记录
var tradeCash = tcQuery.OrderByDescending(x => x.id).FirstOrDefault();
var et = extensionTimeService.QueryExtensionTimeList(tradeId).Where(O => O.OptDate > tradeCash.ValueDate).OrderByDescending(O => O.OptDate).FirstOrDefault();
if (et != null)
{
extensionTimeService.DelExtensionTime(et.TradeId, et.id);
return trade;
}
trade.Notional = tradeCash.Notional;
if (trade.TradeType == "现金流交易")
{
if (tradeCash.UnwindType == "全部平仓")
{
trade.StockEqvNotional = tradeCash.Notional;
}
else
{
trade.StockEqvNotional = trade.StockEqvNotional + tradeCash.UnwindNotional.Value;
}
}
else
{
if (trade.IsUsePremiumRate == true)
{
//后期将会将所有已了结的交易均处理为0
if (ConsTrade.TradeCompleteStatus.Contains(trade.TradeStatus))
{
trade.StockEqvNotional = 0;
}
trade.StockEqvNotional += trade.OriginalStockEqvNotional * tradeCash.UnwindPercentRate ?? 0;
}
else
{
if (trade.TradeType == "远期" && PS.Config.ErpElement.ForwardTradePriceModel == 0 && !string.IsNullOrWhiteSpace(trade.BasisUnderlyingCode))
{
trade.StockEqvNotional += TradeHelper.GetStockEqvNotional(tradeCash.UnwindNotional / trade.OriginalNotional * trade.OriginalStockEqvNotional, trade.ParticipationRate, trade.AnnualizeFactor);
}
else
{
trade.StockEqvNotional = TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor);
}
}
}
valueDate = tradeCash.ValueDate;
tradeCashIds.Add(tradeCash.id);
//分步回退时将倒数第二条平仓记录赋值给trade
var lastSecondTradeCash = tcQuery.Where(x => x.id != tradeCash.id).OrderByDescending(x => x.id).FirstOrDefault();
if (lastSecondTradeCash != null && lastSecondTradeCash.Action == "系统操作-平仓费")
{
trade.UnWindDate = lastSecondTradeCash.ValueDate;
trade.FinalPrice = lastSecondTradeCash.FinalPrice;
trade.UnWindNotional = lastSecondTradeCash.UnwindNotional;
trade.UnWindPrice = lastSecondTradeCash.UnwindPrice;
trade.HasPartialUnWind = 1;
}
else
{
trade.UnWindDate = null;
trade.FinalPrice = null;
trade.UnWindNotional = null;
trade.UnWindPrice = null;
trade.HasPartialUnWind = null;
}
}
trade.TradeAmount = trade.Notional;
var varietyList = VarietyBLL.GetAllvarietyModel();
if (!string.IsNullOrWhiteSpace(trade.UnderlyingAssetClass))
{
var variety = varietyList.FirstOrDefault(O => O.VarietyName == trade.UnderlyingAssetClass);
if (variety != null)
{
trade.TradeUnit = variety.TradeUnit;
trade.TradeAmount /= variety.CountRatio;
}
}
trade.CheckStatus = null;
trade.OptId = UserId;
trade.OptName = UserName;
trade.OptDate = DateTime.Now;
trade.TradeStatus = ConsTrade.确认成交;
trade.IsApproval = false;
trade.ProcessOrderId = 0;
trade.ProcessOptDate = null;
trade.ProcessStatus = null;
trade.DividendDate = new DateTime(2000, 1, 1);
trade.SettlementFlag = 0;
//if (trade.TradeType == "结构化交易")
//{
// var tradeChildren = DbContext.trade.Where(x => x.ParentTradeId == trade.id).ToList();
// tradeChildren.ForEach(x =>
// {
// Execute(x.id, true, actionEnum);
// });
//}
//结构化交易回退时传入的是子交易的Id,此时只需要删掉主交易的Eod记录即可;
if (trade.ParentTradeId > 0)
{
RemoveEodTradeAndFutureInfo(false, trade.ParentTradeId, valueDate, backToBegin: backToBegin);
}
if (backToBegin)
{
if (trade.TradeType == "障碍期权")
{
trade.trade_barrier_option.KnockInOutStatus = null;
trade.trade_barrier_option.KnockInOutDate = null;
}
else if (trade.TradeType == "双鲨期权")
{
trade.trade_double_sharkfin_option.KnockInOutStatus = null;
trade.trade_double_sharkfin_option.KnockInOutDate = null;
}
else if (trade.TradeType == "凤凰期权")
{
trade.trade_autocall.KnockInOutStatus = null;
trade.trade_autocall.KnockInOutDate = null;
var autoCallObservations = DbContext.autocall_observation.Where(x => x.TradeId == trade.id);
DbContext.autocall_observation.RemoveRange(autoCallObservations);
}
else if (trade.TradeType == "雪球期权")
{
if (trade.trade_snowball.IsInitialKnockedIn)
{
trade.trade_snowball.KnockInOutStatus = ConsTrade.KnockState.KnockedIn;
trade.trade_snowball.KnockInOutDate = trade.TradeDate;
}
else
{
trade.trade_snowball.KnockInOutStatus = null;
trade.trade_snowball.KnockInOutDate = null;
}
var autoCallObservations = DbContext.autocall_observation.Where(x => x.TradeId == trade.id);
DbContext.autocall_observation.RemoveRange(autoCallObservations);
}
else if (trade.TradeType == "区间累积期权")
{
var autoCallObservations = DbContext.autocall_observation.Where(x => x.TradeId == trade.id);
DbContext.autocall_observation.RemoveRange(autoCallObservations);
}
else if (trade.TradeType == "累计期权")
{
trade.trade_accumulator_option.KnockOutDate = null;
var autoCallObservations = DbContext.autocall_observation.Where(x => x.TradeId == trade.id);
DbContext.autocall_observation.RemoveRange(autoCallObservations);
new OptionTradeActionRestoreService(this).RestoreTradeDataToSpecialDay(trade, trade.TradeDate.Value);
var accumulator = trade.trade_accumulator_option;
if (accumulator != null)
{
var customObservDates = QdpHelper.ParseObservationDate(accumulator.KOObservationDates);
if (customObservDates == null)
{
customObservDates = Qdp.Pricing.Base.Implementations.CalendarImpl.Get("chn")
.BizDaysBetweenDatesExcluStartDay(trade.TradeDate.Value, trade.ExerciseDate.Value).ToArray();
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(trade.UnderlyingCode);
accumulator.OriginalAccumuTradeAmount = (originTrade.OriginalNotional ?? 0) / underlying.CountRatio / customObservDates.Length;
accumulator.AccumuTradeAmount = accumulator.OriginalAccumuTradeAmount;
}
}
else if (trade.TradeType == "收益互换")
{
trade.trade_swap.GetFinalPrice = null;
trade.trade_swap.PayFinalPrice = null;
if (trade.IsGroup == 2)
{
var parentTrade = DbContext.trade.Find(trade.ParentTradeId);
parentTrade.StockEqvNotional += stockEqvNotionalUnwind;
parentTrade.TradeStatus = "确认成交";
var swapDetail = DbContext.trade_swap_detail.FirstOrDefault(x => x.TradeId == trade.ParentTradeId && x.ChildTradeId == trade.id);
swapDetail.Notional = trade.Notional;
}
}
else if (trade.TradeType == "气囊结构")
{
trade.trade_airbag.KnockInOutStatus = null;
trade.trade_airbag.KnockInOutDate = null;
trade.trade_airbag.KnockInOutNotional = null;
}
new ManuallyTradeObservationPriceService(OptUser).RemoveManuallyTradeObservationPrice(trade.id);
}
var actionService = new TradeActionDataService(this);
RemoveEodTradeAndFutureInfo(false, trade.id, valueDate, tradeCashIds, backToBegin: backToBegin);
AddTradeOperationHistoryAndSetParentTradeInfo(false, trade,"交易回退");
var backAction = actionService.CreateTradeAction(tradeId, BLL.valuedateBLL.ValueDate, TradeActionType.BackTrade);
DbContext.TradeAction.Add(backAction);
DbContext.SaveChanges();
actionService.SetInvalid(x => x.IsValid && x.TradeId == trade.id, backAction.id);
return trade;
}
public trade Execute(int tradeId, DateTime valueDate, bool ignoreBodTrade = false)
{
var trade = DbContext.trade.Find(tradeId);
if (trade == null)
{
throw new ServiceException("交易数据不存在");
}
new TradeExtendService(UserInfo, DbContext).SetTradeExtend(new[] { trade }, tracking: true);
if (valueDate == trade.TradeDate)
{
Execute(tradeId, true, TradeBackActionEnum.backTrade);
}
else
{
var bodTrade = DbContext.bod_Trade.FirstOrDefault(x => x.TradeId == trade.id && x.ValueDate == valueDate);
if (bodTrade != null)
{
if (trade.TradeType == "累计期权")
{
if (trade.trade_accumulator_option.SettlementMode == "实物交割" || trade.trade_accumulator_option.SettlementMode == "现金实物合并结算")
{
var query = from ob in DbContext.autocall_observation
join tf in DbContext.trade on ob.ConvTradeNumber equals tf.TradeNumber
where ob.TradeId == trade.id && (ob.SettlementMode == "转远期" || ob.SettlementMode == "转掉期" || ob.SettlementMode == "现金当日&转远期") && ob.PaymentDate >= valueDate && tf.ValidState != ConsGlobal.InValid
select ob;
if (query.Any())
{
throw new ServiceException($"操作失败,当前累计期权交易({trade.TradeNumber})已结算为远期交易,请将所有结算后的远期交易删除后重新执行回退操作!");
}
}
}
var ets = DbContext.ExtensionTime.Where(x => x.OptDate >= valueDate && x.IsValid).ToList();
if (ets.Any())
{
var extensionTimeService = new ExtensionTimeService(UserInfo, DbContext);
extensionTimeService.DelExtensionTime(trade.id, valueDate, false, true);
}
trade.ExerciseDate = bodTrade.trade.ExerciseDate;
trade.SettlementDate = bodTrade.trade.SettlementDate;
trade.SettlementFlag = bodTrade.trade.SettlementFlag;
//延期结算 >= 到期日才会有,为了回退取镜像数据
if (trade.ExerciseDate > valueDate && trade.SettlementFlag == 1)
{
trade.SettlementFlag = 0;
}
trade.SpotPrice = bodTrade.trade.SpotPrice;
trade.Strike = bodTrade.trade.Strike;
trade.OriginalNotional = bodTrade.trade.OriginalNotional;
trade.Notional = bodTrade.trade.Notional;
trade.TradeAmount = bodTrade.trade.TradeAmount;
trade.StockEqvNotional = bodTrade.trade.StockEqvNotional;
trade.UnWindDate = bodTrade.trade.UnWindDate;
trade.FinalPrice = bodTrade.trade.FinalPrice;
trade.UnWindNotional = bodTrade.trade.UnWindNotional;
trade.UnWindPrice = bodTrade.trade.UnWindPrice;
trade.HasPartialUnWind = bodTrade.trade.HasPartialUnWind;
trade.CheckStatus = bodTrade.trade.CheckStatus;
trade.TradeStatus = bodTrade.trade.TradeStatus;
trade.ProcessOrderId = bodTrade.trade.ProcessOrderId;
trade.ProcessOptDate = bodTrade.trade.ProcessOptDate;
trade.ProcessStatus = bodTrade.trade.ProcessStatus;
trade.DividendDate = bodTrade.trade.DividendDate;
trade.IsApproval = bodTrade.trade.IsApproval;
trade.OptId = UserId;
trade.OptName = UserName;
trade.OptDate = DateTime.Now;
if (trade.ParentTradeId > 0)
{
RemoveEodTradeAndFutureInfo(false, trade.ParentTradeId, valueDate, isDelTradeCashIncludeStartDay: true);
}
if (trade.TradeType == "障碍期权")
{
trade.trade_barrier_option.KnockInOutStatus = bodTrade.trade.trade_barrier_option.KnockInOutStatus;
trade.trade_barrier_option.KnockInOutDate = bodTrade.trade.trade_barrier_option.KnockInOutDate;
}
else if (trade.TradeType == "二元期权")
{
trade.trade_binary_option.UpperBarrier = bodTrade.trade.trade_binary_option.UpperBarrier;
}
else if (trade.TradeType == "双鲨期权")
{
trade.trade_double_sharkfin_option.BarrierHigh = bodTrade.trade.trade_double_sharkfin_option.BarrierHigh;
trade.trade_double_sharkfin_option.BarrierLow = bodTrade.trade.trade_double_sharkfin_option.BarrierLow;
trade.trade_double_sharkfin_option.StrikeHigh = bodTrade.trade.trade_double_sharkfin_option.StrikeHigh;
trade.trade_double_sharkfin_option.StrikeLow = bodTrade.trade.trade_double_sharkfin_option.StrikeLow;
trade.trade_double_sharkfin_option.KnockInOutStatus = bodTrade.trade.trade_double_sharkfin_option.KnockInOutStatus;
trade.trade_double_sharkfin_option.KnockInOutDate = bodTrade.trade.trade_double_sharkfin_option.KnockInOutDate;
}
else if (trade.TradeType == "凤凰期权")
{
trade.trade_autocall.CouponBarrier = bodTrade.trade.trade_autocall.CouponBarrier;
trade.trade_autocall.KIBarrier = bodTrade.trade.trade_autocall.KIBarrier;
trade.trade_autocall.KOBarrier = bodTrade.trade.trade_autocall.KOBarrier;
trade.trade_autocall.SpreadStrike = bodTrade.trade.trade_autocall.SpreadStrike;
trade.trade_autocall.SpreadStrike1 = bodTrade.trade.trade_autocall.SpreadStrike1;
trade.trade_autocall.KnockInOutStatus = bodTrade.trade.trade_autocall.KnockInOutStatus;
trade.trade_autocall.KnockInOutDate = bodTrade.trade.trade_autocall.KnockInOutDate;
}
else if (trade.TradeType == "雪球期权")
{
trade.trade_snowball.KIBarrier = bodTrade.trade.trade_snowball.KIBarrier;
trade.trade_snowball.KOBarrier = bodTrade.trade.trade_snowball.KOBarrier;
trade.trade_snowball.SpreadStrikeAtKO = bodTrade.trade.trade_snowball.SpreadStrikeAtKO;
trade.trade_snowball.SpreadStrikeAtKO1 = bodTrade.trade.trade_snowball.SpreadStrikeAtKO1;
trade.trade_snowball.SpreadStrikeAtMaturity = bodTrade.trade.trade_snowball.SpreadStrikeAtMaturity;
trade.trade_snowball.SpreadStrikeAtMaturity1 = bodTrade.trade.trade_snowball.SpreadStrikeAtMaturity1;
trade.trade_snowball.KnockInOutStatus = bodTrade.trade.trade_snowball.KnockInOutStatus;
trade.trade_snowball.KnockInOutDate = bodTrade.trade.trade_snowball.KnockInOutDate;
}
else if (trade.TradeType == "气囊结构")
{
trade.trade_airbag.HighStrike = bodTrade.trade.trade_airbag.HighStrike;
trade.trade_airbag.Barrier = bodTrade.trade.trade_airbag.Barrier;
}
else if (trade.TradeType == "区间累积期权")
{
trade.trade_rangeaccrual.UpperRange = bodTrade.trade.trade_rangeaccrual.UpperRange;
trade.trade_rangeaccrual.LowerRange = bodTrade.trade.trade_rangeaccrual.LowerRange;
}
else if (trade.TradeType == "累计期权")
{
trade.trade_accumulator_option.KOBarrier = bodTrade.trade.trade_accumulator_option.KOBarrier;
trade.trade_accumulator_option.KnockOutDate = bodTrade.trade.trade_accumulator_option.KnockOutDate;
trade.trade_accumulator_option.OriginalAccumuTradeAmount = bodTrade.trade.trade_accumulator_option.OriginalAccumuTradeAmount;
trade.trade_accumulator_option.AccumuTradeAmount = bodTrade.trade.trade_accumulator_option.AccumuTradeAmount;
}
else if (trade.TradeType == "收益互换")
{
trade.trade_swap.GetSpotPrice = bodTrade.trade.trade_swap.GetSpotPrice;
trade.trade_swap.PaySpotPrice = bodTrade.trade.trade_swap.PaySpotPrice;
trade.trade_swap.GetFinalPrice = bodTrade.trade.trade_swap.GetFinalPrice;
trade.trade_swap.PayFinalPrice = bodTrade.trade.trade_swap.PayFinalPrice;
}
var removeAutoCallObservations = DbContext.autocall_observation.Where(x => x.TradeId == trade.id && x.EndDate >= valueDate);
DbContext.autocall_observation.RemoveRange(removeAutoCallObservations);
var autoCallObservations = DbContext.autocall_observation.Where(x => x.TradeId == trade.id && x.EndDate < valueDate && x.PaymentDate >= valueDate).ToList();
autoCallObservations.ForEach(x => x.PaymentDate = trade.ExerciseDate.Value);
if (trade.TradeType == "累计期权")
{
//由于回退操作是回退到valueDate的开盘状态,而换月操作是valueDate的日中操作,所以这里应该取前一天的;
var preValueDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(-1));
new OptionTradeActionRestoreService(this).RestoreTradeDataToSpecialDay(trade, preValueDate);
}
new ManuallyTradeObservationPriceService(OptUser).RemoveManuallyTradeObservationPrice(trade.id, valueDate);
}
else
{
//黑箱交易子交易有可能在回退日期之前就已经完全了结了,而其他子交易以及主交易,在回退日期之后还是存续状态,需要回退
if (ignoreBodTrade)
{
return trade;
}
var lastBodTrade = DbContext.bod_Trade.Where(x => x.TradeId == trade.id && x.ValueDate < valueDate).OrderByDescending(x => x.ValueDate).FirstOrDefault();
if (lastBodTrade == null)
{
throw new ServiceException($"未查询到该交易在{valueDate.ToString("yyyy-MM-dd")}之前的收盘数据,只能回退到开仓日");
}
else
{
throw new ServiceException($"未查询到该交易在{valueDate.ToString("yyyy-MM-dd")}前一天的收盘数据,最近一次可以回退的日期为{lastBodTrade.ValueDate.ToString("yyyy-MM-dd")}");
}
}
}
var actionService = new TradeActionDataService(this);
using (var trans = DbContext.Database.BeginTransaction())
{
RemoveEodTradeAndFutureInfo(false, trade.id, valueDate, isDelTradeCashIncludeStartDay: true);
AddTradeOperationHistoryAndSetParentTradeInfo(false, trade, "交易回退");
var backAction = actionService.CreateTradeAction(tradeId, BLL.valuedateBLL.ValueDate, TradeActionType.BackTrade);
DbContext.TradeAction.Add(backAction);
DbContext.SaveChanges();
actionService.SetInvalid(x => x.IsValid && x.TradeId == trade.id, backAction.id);
trans.Commit();
}
return trade;
}
#region 分组回退
///
/// 回退分组交易用
///
///
///
///
public trade BackGroup(int tradeId, bool backToBegin, TradeBackActionEnum actionEnum)
{
var tradeIds = new List();
var tradeCashIds = new List();
var extensionTimeService = new ExtensionTimeService(UserInfo, DbContext);
//主交易处理
var trade = DbContext.trade.Find(tradeId);
var valueDate = trade.TradeDate.Value;
tradeIds.Add(tradeId);
tradeCashIds.AddRange(BackGroupItem(tradeId, backToBegin, valueDate));
var tradeCashGrouActions = DbContext.trade_cash_group_action.Where(x => tradeCashIds.Contains(x.ParentTradeCashId));
DbContext.trade_cash_group_action.RemoveRange(tradeCashGrouActions);
//DbContext.SaveChanges();
//子交易处理
if (backToBegin)
{
var tradeChildren = DbContext.trade.Where(x => x.ParentTradeId == tradeId).ToList();
tradeIds.AddRange(tradeChildren.Select(x => x.id).ToList());
foreach (var tradeChild in tradeChildren)
{
tradeCashIds.AddRange(BackGroupItem(tradeChild.id, backToBegin, valueDate));
}
}
else
{
var tradeCashId = tradeCashIds.FirstOrDefault();
var tradeCashChildren = DbContext.trade_cash.Where(x => x.ParentTradeCashId == tradeCashId).ToList();
var tradeCash = tradeCashChildren.FirstOrDefault();
if (tradeCash != null)
{
var et = extensionTimeService.QueryExtensionTimeList(tradeId).Where(O => O.OptDate > tradeCash.ValueDate).OrderByDescending(O => O.OptDate).FirstOrDefault();
if (et != null)
{
extensionTimeService.DelExtensionTime(et.TradeId, et.id);
return trade;
}
}
foreach (var tradeCashChild in tradeCashChildren)
{
tradeCashIds.AddRange(BackGroupChildItemByStep(tradeCashChild.TradeId, tradeCashChild.id, valueDate));
tradeIds.AddRange(tradeCashChildren.Select(x => x.TradeId));
}
}
extensionTimeService.DelExtensionTime(tradeId, DateTime.MinValue, actionEnum != TradeBackActionEnum.EditMaturityDate);
RemoveGroupEodTradeAndFutureInfo(tradeIds, valueDate, tradeCashIds);
DbContext.SaveChanges();
return trade;
}
private List BackGroupItem(int tradeId, bool backToBegin, DateTime valueDate)
{
var trade = DbContext.trade.Find(tradeId);
var tradeCashIds = new List();
var actions = new List()
{
"系统操作-行权费",
"系统操作-平仓费",
"系统操作-票息",
"系统操作-互换"
};
var tcQuery = DbContext.trade_cash.Where(x => x.TradeId == tradeId && actions.Contains(x.Action) && x.ValidState != "InValid" && !x.IsDeleted);
var eodTrade = DbContext.eod_trade.Where(O => O.TradeId == tradeId && O.ValueDate == trade.TradeDate).FirstOrDefault();
var originTrade = eodTrade?.trade;
if (originTrade == null)
{
originTrade = trade;
}
if (backToBegin)
{
var tcTemp = DbContext.trade_cash.Where(x => x.TradeId == tradeId && x.Action == "系统操作-期权费" && x.ValidState != ConsGlobal.InValid && !x.IsDeleted).FirstOrDefault();
if (tcTemp == null)
{
throw new ServiceException("未查询到该交易的开仓记录,请删除该笔交易重新操作");
}
originTrade.TradeStatus = ConsTrade.确认成交;
originTrade.OriginalNotional = tcTemp.Notional;
originTrade.Notional = tcTemp.Notional;
originTrade.StockEqvNotional = originTrade.OriginalStockEqvNotional ?? 0;
DividendService.SetDividendTradeData(trade, originTrade);
valueDate = trade.TradeDate.Value;
tradeCashIds.AddRange(tcQuery.Select(O => O.id).ToList());
trade.UnWindDate = null;
trade.FinalPrice = null;
trade.UnWindNotional = null;
trade.UnWindPrice = null;
trade.HasPartialUnWind = null;
}
else
{
if (!tcQuery.Any())
{
throw new ServiceException("未查询到该交易的了结记录,不可回退");
}
//有行权记录先回撤行权记录,没有行权记录,依次倒序撤回平仓记录
var tradeCash = tcQuery.OrderByDescending(x => x.id).FirstOrDefault();
trade.Notional = tradeCash.Notional;
if (trade.TradeType == "现金流交易")
{
if (tradeCash.UnwindType == "全部平仓")
{
trade.StockEqvNotional = tradeCash.Notional;
}
else
{
trade.StockEqvNotional = trade.StockEqvNotional + tradeCash.UnwindNotional.Value;
}
}
else
{
if (trade.IsUsePremiumRate == true)
{
//后期将会将所有已了结的交易均处理为0
if (ConsTrade.TradeCompleteStatus.Contains(trade.TradeStatus))
{
trade.StockEqvNotional = 0;
}
trade.StockEqvNotional += trade.OriginalStockEqvNotional * tradeCash.UnwindPercentRate ?? 0;
}
else
{
if (trade.TradeType == "远期" && PS.Config.ErpElement.ForwardTradePriceModel == 0 && !string.IsNullOrWhiteSpace(trade.BasisUnderlyingCode))
{
trade.StockEqvNotional += TradeHelper.GetStockEqvNotional(tradeCash.UnwindNotional / trade.OriginalNotional * trade.OriginalStockEqvNotional, trade.ParticipationRate, trade.AnnualizeFactor);
}
else
{
trade.StockEqvNotional = TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor);
}
}
}
valueDate = tradeCash.ValueDate;
tradeCashIds.Add(tradeCash.id);
//分步回退时将倒数第二条平仓记录赋值给trade
var lastSecondTradeCash = tcQuery.Where(x => x.id != tradeCash.id).OrderByDescending(x => x.id).FirstOrDefault();
if (lastSecondTradeCash != null && lastSecondTradeCash.Action == "系统操作-平仓费")
{
trade.UnWindDate = lastSecondTradeCash.ValueDate;
trade.FinalPrice = lastSecondTradeCash.FinalPrice;
trade.UnWindNotional = lastSecondTradeCash.UnwindNotional;
trade.UnWindPrice = lastSecondTradeCash.UnwindPrice;
trade.HasPartialUnWind = 1;
}
else
{
trade.UnWindDate = null;
trade.FinalPrice = null;
trade.UnWindNotional = null;
trade.UnWindPrice = null;
trade.HasPartialUnWind = null;
}
}
trade.TradeAmount = trade.Notional;
var varietyList = VarietyBLL.GetAllvarietyModel();
if (!string.IsNullOrWhiteSpace(trade.UnderlyingAssetClass))
{
var variety = varietyList.FirstOrDefault(O => O.VarietyName == trade.UnderlyingAssetClass);
if (variety != null)
{
trade.TradeUnit = variety.TradeUnit;
trade.TradeAmount /= variety.CountRatio;
}
}
trade.CheckStatus = null;
trade.OptId = UserId;
trade.OptName = UserName;
trade.OptDate = DateTime.Now;
trade.TradeStatus = ConsTrade.确认成交;
trade.ProcessOrderId = 0;
trade.ProcessOptDate = null;
trade.ProcessStatus = null;
trade.DividendDate = new DateTime(2000, 1, 1);
if (backToBegin && (trade.TradeType == "障碍期权" || trade.StructureType == "障碍期权"))
{
var trade_barrier_option = DbContext.trade_barrier_option.Where(x => x.TradeId == trade.id).FirstOrDefault();
trade_barrier_option.KnockInOutStatus = null;
trade_barrier_option.KnockInOutDate = null;
}
if (backToBegin && (trade.TradeType == "双鲨期权" || trade.StructureType == "双鲨期权"))
{
var trade_double_sharkfin_option = DbContext.trade_double_sharkfin_option.Where(x => x.TradeId == trade.id).FirstOrDefault();
trade_double_sharkfin_option.KnockInOutStatus = null;
trade_double_sharkfin_option.KnockInOutDate = null;
}
if (backToBegin && (trade.TradeType == "凤凰期权" || trade.StructureType == "凤凰期权"))
{
var trade_autocall = DbContext.trade_autocall.Where(x => x.TradeId == trade.id).FirstOrDefault();
trade_autocall.KnockInOutStatus = null;
trade_autocall.KnockInOutDate = null;
var autoCallObservations = DbContext.autocall_observation.Where(x => x.TradeId == trade.id);
DbContext.autocall_observation.RemoveRange(autoCallObservations);
}
if (backToBegin && (trade.TradeType == "雪球期权" || trade.StructureType == "雪球期权"))
{
var trade_snowball = DbContext.trade_snowball.Where(x => x.TradeId == trade.id).FirstOrDefault();
trade_snowball.KnockInOutStatus = null;
trade_snowball.KnockInOutDate = null;
}
if (backToBegin && (trade.TradeType == "区间累积期权" || trade.StructureType == "区间累积期权"))
{
var autoCallObservations = DbContext.autocall_observation.Where(x => x.TradeId == trade.id);
DbContext.autocall_observation.RemoveRange(autoCallObservations);
}
if (backToBegin && (trade.TradeType == "收益互换" || trade.StructureType == "收益互换"))
{
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == trade.id);
trade_swap.GetFinalPrice = null;
trade_swap.PayFinalPrice = null;
var trade_swap_details = DbContext.trade_swap_detail.Where(x => x.TradeId == trade.id).ToList();
trade_swap_details.ForEach(x =>
{
x.Notional = x.OriginalNotional;
x.SwapDate = null;
x.FinalPrice = null;
});
}
if (backToBegin)
{
new ManuallyTradeObservationPriceService(OptUser).RemoveManuallyTradeObservationPrice(trade.id);
}
DateTime mindate = trade.TradeDate ?? DateTime.MinValue;
var delTCArr = DbContext.trade_cash.Where(O => tradeCashIds.Contains(O.id));
if (delTCArr.Any())
{
delTCArr.ToList().ForEach(O => { O.ValidState = "InValid"; O.Status = TradeCashStatusEnum.已执行; O.OptDate = DateTime.Now; O.IsDeleted = true; });
mindate = delTCArr.Min(O => (DateTime?)O.ValueDate).GetValueOrDefault();
}
var trList = DbContext.trade_contract_r.Where(O => O.TradeId == tradeId && O.Type == "交易确认书").ToList();
foreach (var item in trList)
{
string infoTag = "_" + item.ContractCode.Replace("_", "-") + "_" + "了结_";
var notes = DbContext.sac_report_notes.Where(x => x.IsValid && x.InfoTag.Contains(infoTag) && x.ReportDate >= mindate).ToList();
foreach (var note in notes)
{
note.changeStatus = true;
}
}
AddTradeOperationHistoryAndSetParentTradeInfo(false, trade, "交易回退");
DbContext.SaveChanges();
return tradeCashIds;
}
private List BackGroupChildItemByStep(int tradeId, int tradeCashId, DateTime valueDate)
{
var trade = DbContext.trade.Find(tradeId);
var tradeCashIds = new List();
var actions = new List()
{
"系统操作-行权费",
"系统操作-平仓费",
"系统操作-票息",
"系统操作-互换"
};
var tradeCash = DbContext.trade_cash.Find(tradeCashId);
var eodTrade = DbContext.eod_trade.Where(O => O.TradeId == tradeId && O.ValueDate == trade.TradeDate).FirstOrDefault();
var originTrade = eodTrade?.trade;
if (originTrade == null)
{
originTrade = trade;
}
if (tradeCash == null)
{
throw new ServiceException("未查询到该交易的了结记录,不可回退");
}
trade.Notional = tradeCash.Notional;
if (trade.TradeType == "现金流交易")
{
if (tradeCash.UnwindType == "全部平仓")
{
trade.StockEqvNotional = tradeCash.Notional;
}
else
{
trade.StockEqvNotional = trade.StockEqvNotional + tradeCash.UnwindNotional.Value;
}
}
else
{
if (trade.TradeType == "远期" && PS.Config.ErpElement.ForwardTradePriceModel == 0 && !string.IsNullOrWhiteSpace(trade.BasisUnderlyingCode))
{
trade.StockEqvNotional += TradeHelper.GetStockEqvNotional(tradeCash.UnwindNotional / trade.OriginalNotional * trade.OriginalStockEqvNotional, trade.ParticipationRate, trade.AnnualizeFactor);
}
else
{
trade.StockEqvNotional = TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor);
}
}
valueDate = tradeCash.ValueDate;
tradeCashIds.Add(tradeCash.id);
//分步回退时将倒数第二条平仓记录赋值给trade
var lastSecondTradeCash = DbContext.trade_cash.Where(x => x.TradeId == tradeId && x.id != tradeCash.id && x.ValidState != "InValid" && !x.IsDeleted).OrderByDescending(x => x.id).FirstOrDefault();
if (lastSecondTradeCash != null && lastSecondTradeCash.Action == "系统操作-平仓费")
{
trade.UnWindDate = lastSecondTradeCash.ValueDate;
trade.FinalPrice = lastSecondTradeCash.FinalPrice;
trade.UnWindNotional = lastSecondTradeCash.UnwindNotional;
trade.UnWindPrice = lastSecondTradeCash.UnwindPrice;
trade.HasPartialUnWind = 1;
}
else
{
trade.UnWindDate = null;
trade.FinalPrice = null;
trade.UnWindNotional = null;
trade.UnWindPrice = null;
trade.HasPartialUnWind = null;
}
trade.TradeAmount = trade.Notional;
var varietyList = VarietyBLL.GetAllvarietyModel();
if (!string.IsNullOrWhiteSpace(trade.UnderlyingAssetClass))
{
var variety = varietyList.FirstOrDefault(O => O.VarietyName == trade.UnderlyingAssetClass);
if (variety != null)
{
trade.TradeUnit = variety.TradeUnit;
trade.TradeAmount /= variety.CountRatio;
}
}
trade.CheckStatus = null;
trade.OptId = UserId;
trade.OptName = UserName;
trade.OptDate = DateTime.Now;
trade.TradeStatus = ConsTrade.确认成交;
trade.ProcessOrderId = 0;
trade.ProcessOptDate = null;
trade.ProcessStatus = null;
trade.DividendDate = new DateTime(2000, 1, 1);
DateTime mindate = trade.TradeDate ?? DateTime.MinValue;
var delTCArr = DbContext.trade_cash.Where(O => tradeCashIds.Contains(O.id));
if (delTCArr.Any())
{
delTCArr.ToList().ForEach(O => { O.ValidState = "InValid"; O.Status = TradeCashStatusEnum.已执行; O.OptDate = DateTime.Now; O.IsDeleted = true; });
mindate = delTCArr.Min(O => (DateTime?)O.ValueDate).GetValueOrDefault();
}
var trList = DbContext.trade_contract_r.Where(O => O.TradeId == tradeId && O.Type == "交易确认书").ToArray();
foreach (var item in trList)
{
string infoTag = "_" + item.ContractCode.Replace("_", "-") + "_" + "了结_";
var notes = (from note in DbContext.sac_report_notes
where
note.IsValid &&
note.InfoTag.Contains(infoTag) &&
note.ReportDate >= mindate
select note);
foreach (var note in notes)
{
note.changeStatus = true;
}
}
AddTradeOperationHistoryAndSetParentTradeInfo(false, trade, "交易回退");
DbContext.SaveChanges();
return tradeCashIds;
}
#endregion
}
public enum TradeBackActionEnum
{
backTrade,
backTradeStepped,
EditMaturityDate
}
}