Files
zszq-trs/YLErpDAL/Modules/TradeModule/DealModule/TradeUnwindService.cs
T

1900 lines
85 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.EntityFrameworkCore.Storage;
using YLErp.BLL;
using YLErp.BLL.Eod;
using YLErp.Commons;
using YLErp.CustomizedBizLogic;
using YLErp.DBModels.Consts;
using YLErp.DBModels.Helpers;
using YLErp.Enums;
using YLErp.Model;
using YLErp.Model.Enum;
using YLErp.Modules.ClientModule;
using YLErp.Modules.EodModule;
using YLErp.Modules.TradeDalModule;
using YLErp.QdpModule;
namespace YLErp.Modules.TradeModule.DealModule
{
/// <summary>
/// 交易平仓操作
/// </summary>
public class TradeUnwindService : TradeCashService
{
public TradeUnwindService(YLBaseService baseService) : base(baseService)
{
}
public TradeUnwindService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// isPairTrade是否 配对交易平仓
/// 规则:配对被执行的那一条的amounttrade_cash表格)和moneyclientcashincashout 表格)应该是手动执行那一条的数值*-1
/// </summary>
public trade_cash UnwindTrade(trade td, TradeCashReq req, bool isFromRecheck = false, bool isFromExercise = false)
{
if (td is null)
{
throw new ArgumentNullException(nameof(td));
}
if (td.TradeType == "结构化交易")
{
throw new ServiceException("操作失败,结构化交易主交易不支持此操作");
}
if (ConsTrade.TradeCompleteStatus.Contains(td.TradeStatus))
{
throw new ServiceException("操作失败,交易已了结!");
}
if (PS.Config.TradeElement.ExecuteAfterGeneratedConfirmDoc && !td.HasGeneratedConfirmBook())
{
if (td.TradeType != "远期" && td.TradeType != "自定义交易" && td.TradeType != "现金流交易")//临时写法,需要完善远期确认书
{
throw new ServiceException("请先去生成交易确认书");
}
}
//是否部分平仓
var isPartialClose = true;
var tradeCashInvalid = DbContext.trade_cash.FirstOrDefault(t => t.TradeId == td.id && t.Action == ClientCashInCashOut.系统操作_平仓费 && t.ValidState == ConsGlobal.InValid && !t.IsDeleted);
if (req != null)
{
unwindPreHandle(req, td, isFromExercise, out isPartialClose);
}
else
{
if (td.IsUsePremiumRate == true)
{
if (tradeCashInvalid != null &&
td.OriginalStockEqvNotional > 0
&& (tradeCashInvalid.UnwindPercentRate >= td.StockEqvNotional / td.OriginalStockEqvNotional || tradeCashInvalid.UnwindType == "全部平仓"))
{
isPartialClose = false;
}
}
else
{
if (tradeCashInvalid != null && (tradeCashInvalid.UnwindNotional >= td.Notional || tradeCashInvalid.UnwindType == "全部平仓"))
{
isPartialClose = false;
}
}
}
td.OptId = UserId;
td.OptName = UserName;
td.OptDate = DateTime.Now;
if (req != null)
{
td.UnWindNotional = req.UnwindNotional;
}
else
{
td.UnWindNotional = tradeCashInvalid == null ? 0 : tradeCashInvalid.UnwindNotional;
}
if (isPartialClose)
{
td.TradeStatus = ConsTrade.确认成交;
if (td.TradeType == "累计期权" && !isFromExercise)
{
var unwindPercent = (td.UnWindNotional ?? 0) / td.Notional;
var accumulator = DbContext.trade_accumulator_option.FirstOrDefault(x => x.TradeId == td.id);
if (accumulator != null)
{
accumulator.AccumuTradeAmount -= accumulator.OriginalAccumuTradeAmount * unwindPercent;
}
}
td.Notional -= (td.UnWindNotional ?? 0);
if (td.TradeType != "现金流交易")
{
var CountRatio = UnderlyingDataProvider.GetCountRatio(td.UnderlyingCode);
td.TradeAmount = td.Notional / CountRatio;
}
else
{
td.TradeAmount -= (tradeCashInvalid == null ? 0 : tradeCashInvalid.UnwindNotional ?? 0);
}
if (td.IsUsePremiumRate == true)
{
if (req != null)
{
td.StockEqvNotional -= (td.OriginalStockEqvNotional * req.UnwindPercentRate) ?? 0;
}
else
{
td.StockEqvNotional -= (td.OriginalStockEqvNotional * tradeCashInvalid.UnwindPercentRate) ?? 0;
}
}
else
{
if (td.TradeType == "远期" && PS.Config.ErpElement.ForwardTradePriceModel == 0 && !string.IsNullOrWhiteSpace(td.BasisUnderlyingCode))
{
td.StockEqvNotional -= TradeHelper.GetStockEqvNotional((req != null ? req.UnwindNotional : tradeCashInvalid.UnwindNotional) / td.OriginalNotional * td.OriginalStockEqvNotional, 1, 1);
}
else
{
td.StockEqvNotional = TradeHelper.GetStockEqvNotional(Math.Abs(td.Notional * (td.SpotPrice ?? 0.0)), td.ParticipationRate, td.AnnualizeFactor);
}
}
//td.PrincipalSum = TradeHelper.GetPrincipalSumReal(td.StockEqvNotional, td.OriginalStockEqvNotional, td.OriginalPrincipalSum);
td.HasPartialUnWind = 1;
}
else if (isFromExercise)
{
td.TradeStatus = ConsTrade.已执行;
}
else
{
td.TradeStatus = ConsTrade.已平仓;
}
//增加现金交割交易记录
var tc = CloseTrade_TradeCashSave(td, req, isFromRecheck, !isFromExercise, !isPartialClose);
if (!isPartialClose)
{
td.Notional = 0;
td.TradeAmount = 0;
td.StockEqvNotional = 0;
}
var groupAction = DbContext.trade_cash_group_action.FirstOrDefault(x => x.TradeId == td.id && x.Status != "已完成");
if (groupAction != null)
{
groupAction.Status = "已完成";
tc.ParentTradeCashId = groupAction.ParentTradeCashId;
tc.ParentTradeId = groupAction.ParentTradeId;
}
tc.ValidState = "Valid";
tc.ExerciseWay = TradeCashExerciseWayEnum.提前终止行权;
//加入平仓份额和平仓日期
td.UnWindDate = tc.ValueDate;
td.FinalPrice = tc.FinalPrice;
if (td.TradeType != "收益互换")
{
new TradeCashService(this).SaveTradeCashDetail(tc);
}
// if (isPairTrade) req.UnwindNotional = req.UnwindNotional * -1;
var dt = (td.TradeType == "远期" || td.TradeType == "掉期") && PS.Config.Is浙期 && td.ExerciseDate == tc.ValueDate ? td.SettlementDate : tc.ValueDate;
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, dt);
AddTradeOperationHistoryAndSetParentTradeInfo(false, td, isPartialClose ? "部分平仓" : "全部平仓");
//删除E/Bod数据
RemoveEodTradeAndFutureInfo(false, td.id, tc.ValueDate);
DbContext.SaveChanges();
return tc;
}
/// <summary>
/// 来自:UnwindTradeJson
/// </summary>
public TradeUnwindResultModel UnwindTrade(TradeCashReq req, IDbContextTransaction trans = null)
{
if (req?.ValueDate == null)
{
throw new Exception("平仓日期不应为空");
}
//修改交易主表信息交易状态为已执行
var td = DbContext.trade.Find(req.TradeId);
var valueDate = SystemValueDate;
//从页面操作上来看,req.ValueDate是无用的
//当有用的时候需要赋值给valueDate
if (req.ValueDate.HasValue)
{
if (req.ValueDate < td.TradeDate)
{
throw new ServiceException("平仓日期不能小于交易日期");
}
if (req.ValueDate > valueDate)
{
throw new ServiceException("平仓日期不能大于系统日期");
}
}
valueDate = req.ValueDate ?? valueDate;
var isFromRecheck = false;
trade_cash tc = null;
var notrans = trans == null;
if (notrans)
{
trans = DbContext.Database.BeginTransaction();
}
try
{
//平仓复核逻辑验证
if ((valuedateBLL.SystemDate.CloseReCheck == 1) && td.TradeStatus == ConsTrade.平仓待复核)
{
//检查平仓单价
tc = DbContext.trade_cash.OrderByDescending(x => x.id).FirstOrDefault(dd => dd.TradeId == req.TradeId && dd.Action == ClientCashInCashOut.系统操作_平仓费 && dd.ValidState == ConsGlobal.InValid && !dd.IsDeleted).Clone();
if (td.TradeType == "远期")
{
if (req.FinalPrice != tc.FinalPrice)
{
throw new ServiceException("远期交易,标的价格不一致!复核不通过");
}
if (req.ValueDate != tc.ValueDate)
{
throw new ServiceException("远期交易,平仓日期不一致!复核不通过");
}
}
if (valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1)
{
//添加根据交易方向判断资金方向
tc.UnwindPrice = tc.UnwindPrice * (td.TradeType == "远期" || ConsTrade.HasMinusValueOptions.Contains(td.TradeType) ? 1 : EodOperationBase.GetSign(td.BuySell));
tc.UnwindPricePercentRate = tc.UnwindPricePercentRate * (td.TradeType == "远期" || ConsTrade.HasMinusValueOptions.Contains(td.TradeType) ? 1 : EodOperationBase.GetSign(td.BuySell));
}
else
{
//添加根据交易方向判断资金方向
tc.UnwindPrice = tc.UnwindPrice * (td.TradeType == "远期" || !ConsTrade.HasMinusValueOptions.Contains(td.TradeType) ? 1 : EodOperationBase.GetSign(td.BuySell));
tc.UnwindPricePercentRate = tc.UnwindPricePercentRate * (td.TradeType == "远期" || !ConsTrade.HasMinusValueOptions.Contains(td.TradeType) ? 1 : EodOperationBase.GetSign(td.BuySell));
}
if (valuedateBLL.SystemDate.UnwindAmountAngle == 0)
{
tc.Amount = tc.Amount * (td.TradeType == "远期" || td.TradeType == "收益互换" ? 1 : EodOperationBase.GetSign(td.BuySell));
tc.QuoteAmount = tc.QuoteAmount * (td.TradeType == "远期" || td.TradeType == "收益互换" ? 1 : EodOperationBase.GetSign(td.BuySell));
}
if (req.AmountCheck == (tc.QuoteAmount ?? tc.Amount) || req.UnwindPricePercentRateCheck == tc.UnwindPricePercentRate && req.UnwindPricePercentRateCheck != null || req.UnwindPriceCheck == tc.UnwindPrice && req.UnwindPriceCheck != null)
{
req.UnwindPercentRate = (tc.UnwindPercentRate * 100) ?? req.UnwindPercentRate;
isFromRecheck = true;
td.CheckStatus = Convert.ToInt32(TradeCheckEnum.StatusOfUnwind);
td.UnWindDate = valueDate;
DbContext.SaveChanges();
}
else
{
//审核失败
throw new ServiceException("平仓费不一致!复核不通过");
}
}
var result = new TradeUnwindResultModel(td);
//存在审批流程时,走审批成功流程(需求②:按交易状态查对应流程)
if (valuedateBLL.SystemDate.CloseReApprove == 1 && TradeProcessCountByCategory(td) > 0)
{
result.ApprovalProcess = true;
var reqModel = new TradeOpenReqModel
{
tradeId = td.id,
status = "pass",
comments = "平仓复核审批成功",
ignoreMoneyCheck = false,
notNeedOperationHistory = true
};
var openResult = new TradeOpenService(this).UpdateTradeProcessLog(reqModel);
if (openResult.RetCode != TradeOpenRetCode.Success && !string.IsNullOrWhiteSpace(openResult.ErrorMsg))
{
throw new ServiceException("复核审批失败");
}
//生成文档
if (PS.Config.IsAutoGenerateContracts && (td.TradeStatus == ConsTrade.已平仓 || (td.TradeStatus == ConsTrade.确认成交 && td.HasPartialUnWind == 1)))
{
new TradeContractGenerateService(this).GenerateContractsAsync(new List<int> { td.id });
}
SaveTradeOperationHistory(td, "平仓复核");
if (notrans)
{
trans.Commit();
}
if (td.TradeStatus == ConsTrade.已平仓 || (td.TradeStatus == ConsTrade.确认成交 && td.HasPartialUnWind == 1))
{
if (PS.Config.SalesCommissionCalculation == "公式1")
{
//销售提成
new SalesModule.SalesCommissionDetailDataService(this).CalcuSalesCommissionDetail(tc);
}
if (PS.Config.Company == Configuration.CompanyEnum.招证)
{
new BizLogicZhaoZheng().GenerateZhaoZhengDealNumber(td, tc);
}
if (PS.Config.Company == Configuration.CompanyEnum.物产中大)
{
new BizLogicWCZD().GenerateWCZDNumber(DbContext, td, tc.ValueDate, tc.id);
}
}
return result;
}
else
{
if (td.Warning)
{
new TradeDalService(OptUser).RollbackToBeforeSettle(td, req.ValueDate.Value);
}
result.TradeCash = UnwindTrade(td, req, isFromRecheck);
//配对 平仓(不需要复核且不需要审批的平仓操作)
if (req.IsUnwindPairTrade && !string.IsNullOrEmpty(td.PairTrade))
{
result.HasPairTrade = true;
var pairTradeId = Convert.ToInt32(td.PairTrade);
//var pairTrade = DbContext.trade.Find(pairTradeId);
var pairTrade = new TradeDalService(this).GetTradeOrEodTrade(new[] { pairTradeId }, valueDate, true).FirstOrDefault();
if (pairTrade.Warning)
{
new TradeDalService(OptUser).RollbackToBeforeSettle(pairTrade, valueDate);
}
//配对交易平仓总份额取各自剩余的总份额
req.Notional = pairTrade.Notional;
//UnwindNotional >= Notional代表全部品仓,配对交易的平仓份额为自己剩余的总份额
//UnwindNotional < td.Notional部分平仓,配对的两笔交易部分平仓份额相等,即req.UnwindNotional不变
if (req.UnwindNotional >= pairTrade.Notional)
{
req.UnwindNotional = pairTrade.Notional;
req.UnwindPercentRate = req.Notional > 0 ? (req.UnwindNotional / req.Notional) ?? 0 : 0;
}
try
{
UnwindTrade(pairTrade, req, isFromRecheck);
result.PairTradeUnwindSuccess = true;
SaveTradeOperationHistory(pairTrade, "提交平仓");
}
catch (Exception ex)
{
result.PairTradeUnwindException = ex;
LogFactory.GetLogger("平仓配对交易").Error(ex);
}
}
//生成文档
if (PS.Config.IsAutoGenerateContracts)
{
var tradeIdList = new List<int> { td.id };
if (req.IsUnwindPairTrade && result.HasPairTrade && result.PairTradeUnwindSuccess)
{
tradeIdList.Add(Convert.ToInt32(td.PairTrade));
}
new TradeContractGenerateService(this).GenerateContractsAsync(tradeIdList);
}
SaveTradeOperationHistory(td, "提交平仓");
if (notrans)
{
trans.Commit();
}
return result;
}
}
catch
{
if (notrans)
{
trans.Rollback();
}
throw;
}
finally
{
if (notrans)
{
trans.Dispose();
}
}
}
/// <summary>
/// 分组了结 主交易平仓复核
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
/// <exception cref="ServiceException"></exception>
public void UnwindParentTrade(SaveGroupTradeCashReq req)
{
var parentTradeId = req.trade_cash.TradeId;
var td = DbContext.trade.Find(parentTradeId);
var subTradeIds = DbContext.trade_cash_group_action.Where(x => x.ParentTradeId == parentTradeId && x.Status == "待完成").Select(x => x.TradeId).ToList();
var allTd = DbContext.trade.Where(x => x.id == parentTradeId || subTradeIds.Contains(x.id)).ToList();
using (var trans = BeginTransaction())
{
//平仓复核逻辑验证
if ((valuedateBLL.SystemDate.CloseReCheck == 1) && (td.TradeStatus == ConsTrade.平仓待复核 || td.TradeStatus == ConsTrade.行权待复核))
{
//检查平仓单价
var tc = DbContext.trade_cash.OrderByDescending(x => x.id).FirstOrDefault(dd => dd.TradeId == req.trade_cash.TradeId && (dd.Action == ClientCashInCashOut.系统操作_平仓费 || dd.Action == ClientCashInCashOut.系统操作_行权费) && dd.ValidState == ConsGlobal.InValid && dd.Status == null && !dd.IsDeleted);
if (valuedateBLL.SystemDate.UnwindAmountAngle == 0 && td.BuySell == "卖出")
{
req.trade_cash.Amount *= -1;
}
if (tc.Amount == req.trade_cash.Amount)
{
allTd.ForEach(x =>
{
x.CheckStatus = Convert.ToInt32(TradeCheckEnum.StatusOfUnwind);
x.UnWindDate = tc.ValueDate;
});
DbContext.SaveChanges();
}
else
{
//审核失败
throw new ServiceException("平仓费不一致!复核不通过");
}
}
//存在审批流程时,走审批成功流程(需求②:按交易状态查对应流程)
if (valuedateBLL.SystemDate.CloseReApprove == 1 && TradeProcessCountByCategory(td) > 0)
{
var reqModel = new TradeOpenReqModel
{
tradeId = td.id,
status = "pass",
comments = "平仓复核审批成功",
ignoreMoneyCheck = false,
notNeedOperationHistory = true
};
var openResult = new TradeOpenService(this).UpdateParentTradeProcessLog(reqModel);
if (openResult.RetCode != TradeOpenRetCode.Success && !string.IsNullOrWhiteSpace(openResult.ErrorMsg))
{
throw new ServiceException("复核审批失败");
}
allTd.ForEach(x =>
{
//生成文档
if (PS.Config.IsAutoGenerateContracts && (x.TradeStatus == ConsTrade.已平仓 || (x.TradeStatus == ConsTrade.确认成交 && x.HasPartialUnWind == 1)))
{
new TradeContractGenerateService(this).GenerateContractsAsync(new List<int> { x.id });
}
});
}
else
{
td.IsApproval = false;//复核完成将审核重置
td.TradeOldStatus = td.TradeStatus;
if (req.trade_cash.UnwindType == "全部平仓")
{
td.TradeStatus = "已平仓";
}
else if (req.trade_cash.UnwindType == "部分平仓" || req.trade_cash.UnwindType == "部分提前行权")
{
td.TradeStatus = "确认成交";
}
else if (req.trade_cash.UnwindType == "全部提前行权" || req.trade_cash.UnwindType == "到期行权")
{
td.TradeStatus = "已执行";
}
else if (req.trade_cash.UnwindType == "到期")
{
td.TradeStatus = "已到期";
}
var tradeCashGroupActions = DbContext.trade_cash_group_action.Where(x => x.ParentTradeId == td.id && x.Status == "待完成");
var parentTradeCashId = tradeCashGroupActions.FirstOrDefault().ParentTradeCashId;
var parentTradeCash = DbContext.trade_cash.Find(parentTradeCashId);
parentTradeCash.ValidState = ConsGlobal.Valid;
//设置成开户状态,写日志
td.CheckTradeUpdate = Convert.ToInt32(TradeCheckEnum.StatusOfNew);
td.OptId = UserId;
td.OptName = UserName;
td.OptDate = OptDate;
td.TradeAmount -= (parentTradeCash.UnwindTradeAmount ?? 0);
td.Notional -= (parentTradeCash.UnwindNotional ?? 0);
td.StockEqvNotional -= (td.OriginalStockEqvNotional * parentTradeCash.UnwindPercentRate ?? 0);
td.UnWindNotional = parentTradeCash.UnwindNotional;
td.UnWindDate = parentTradeCash.ValueDate;
td.FinalPrice = parentTradeCash.FinalPrice;
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
req.childTradeCashs.ForEach(x =>
{
var tradeCashReq = new TradeCashReq()
{
ValueDate = req.trade_cash.ValueDate,
TradeId = x.TradeId,
TradeAmount = x.TradeAmount,
Notional = x.Notional,
UnwindFee = x.Amount,
Amount = x.Amount,
UnwindTradeAmount = x.UnwindTradeAmount,
UnwindNotional = (x.UnwindTradeAmount ?? 0) * underlying.CountRatio,
UnwindPercentRate = x.UnwindPercentRate ?? 0,
UnwindStockEqvNotional = x.UnwindStockEqvNotional,
CallPut = x.OptionType,
ExceciseType = "现金",
FinalPrice = req.trade_cash.FinalPrice,
UnwindType = req.trade_cash.UnwindType
};
if (req.trade_cash.UnwindType.Contains("到期"))
{
new TradeCashService(this).ExecutionTradeCash(tradeCashReq);
}
else
{
var subTrade = allTd.FirstOrDefault(y => y.id == x.TradeId);
UnwindTrade(subTrade, null, true);
}
});
//存黑箱主交易ClientCashInCashOut需要赋值0
//TradeCash在下面FinishGroupTradeCash里会根据子交易重新统计赋值
parentTradeCash.Amount = 0;
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, parentTradeCash, parentTradeCash.ValueDate);
DbContext.SaveChanges();
FinishGroupTradeCash(req.trade_cash.id);//只有复核,无审批,直接将group_action变为已完成
}
trans.Commit();
}
}
/// <summary>
///
/// </summary>
public TradeUnwindResultModel ApplyUnwindSwapTrade(TradeCashReq req)
{
var td = DbContext.trade.Find(req.TradeId);
//平仓时如果盈亏为正,则以换汇买价结算,如果盈亏为负,则以换汇卖价结算(客户方向,和TradeCashReq方向相反)
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, req.ValueDate.Value
, seekPreday: true, currencyRateType: req.Amount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
req.QuoteUnwindFee = req.UnwindFee;
var getQuoteInitialAmount = req.trade_cash_swap.GetInitialAmount;
var payQuoteInitialAmount = req.trade_cash_swap.PayInitialAmount;
var getQuoteExtraAmount = req.trade_cash_swap.GetExtraAmount;
var payQuoteExtraAmount = req.trade_cash_swap.PayExtraAmount;
var getQuoteCostFee = req.trade_cash_swap.GetCostFee;
var payQuoteCostFee = req.trade_cash_swap.PayCostFee;
req.Amount *= currencyRate;
req.UnwindFee *= currencyRate;
req.InitialAmount *= currencyRate;
req.ExtraAmount *= currencyRate;
req.trade_cash_swap.GetAmount *= currencyRate;
req.trade_cash_swap.GetInitialAmount *= currencyRate;
req.trade_cash_swap.GetExtraAmount *= currencyRate;
req.trade_cash_swap.GetCostFee *= currencyRate;
req.trade_cash_swap.PayAmount *= currencyRate;
req.trade_cash_swap.PayInitialAmount *= currencyRate;
req.trade_cash_swap.PayExtraAmount *= currencyRate;
req.trade_cash_swap.PayCostFee *= currencyRate;
req.UnwindPercentRate /= 100;
if (td.StockEqvNotional / td.OriginalStockEqvNotional - req.UnwindPercentRate <= 1e-5)
{
req.UnwindType = "全部平仓";
req.UnwindPercentRate = td.OriginalStockEqvNotional > 0 ? td.StockEqvNotional / td.OriginalStockEqvNotional.Value : 0;
}
req.UnwindNotional = (td.OriginalNotional * req.UnwindPercentRate) ?? 0;
req.Notional = td.Notional;//前端传回来的数量小数位不足,所以这里要重新赋值,保证不会有精度损失;
req.TradeAmount = td.TradeAmount;
if (req.UnwindPercentRate <= 0)
{
throw new Exception("平仓比例不合理");
}
var result = new TradeUnwindResultModel(td);
//增加现金交割交易记录
req.ValidState = ConsGlobal.InValid;
var tc = CloseTrade_TradeCashSave(td, req, false, false, req.UnwindType != "部分平仓");
var tradeCash = DbContext.trade_cash.Where(y => y.TradeId == td.id && y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= tc.ValueDate).OrderByDescending(y => y.id).FirstOrDefault();
var tradeCashSwap = tradeCash == null ? null : DbContext.trade_cash_swap.FirstOrDefault(x => x.TradeCashId == tradeCash.id);
tc.StartDate = tradeCash?.ValueDate ?? td.StartDate.Value;
tc.ExerciseWay = TradeCashExerciseWayEnum.提前终止行权;
tc.CurrencyRate = currencyRate;
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
tc.FinalPrice = trade_swap.IsGetFloatingProfit ? req.trade_cash_swap.GetFinalPrice : req.trade_cash_swap.PayFinalPrice;
var hasTradeProcess = HasTradeProcess();
CloseReCheck_SetTrade(td.id, false, hasTradeProcess);
var trade_cash_swap = req.trade_cash_swap;
trade_cash_swap.StartDate = tc.StartDate;
trade_cash_swap.GetStartPrice = tradeCashSwap?.GetFinalPrice ?? trade_swap.GetSpotPrice;
trade_cash_swap.PayStartPrice = tradeCashSwap?.PayFinalPrice ?? trade_swap.PaySpotPrice;
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
var tcdGetInitialAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetInitialAmount,
QuoteAmount = getQuoteInitialAmount,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetInitialAmount);
var tcdGetExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetExtraAmount,
QuoteAmount = getQuoteExtraAmount,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetExtraAmount);
var tcdGetCostFee = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetCostFee,
QuoteAmount = getQuoteCostFee,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetCostFee);
var tcdPayInitialAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayInitialAmount,
QuoteAmount = -payQuoteInitialAmount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayInitialAmount);
var tcdPayExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayExtraAmount,
QuoteAmount = -payQuoteExtraAmount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayExtraAmount);
var tcdPayCostFee = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayCostFee,
QuoteAmount = -payQuoteCostFee,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayCostFee);
DbContext.SaveChanges();
SaveTradeOperationHistory(td, "提交平仓");
return result;
}
/// <summary>
///
/// </summary>
public TradeUnwindResultModel ApproveUnwindSwapTrade(trade td)
{
var result = new TradeUnwindResultModel(td);
//增加现金交割交易记录
var tc = CloseTrade_TradeCashSave(td, null, true, false);
var groupAction = DbContext.trade_cash_group_action.FirstOrDefault(x => x.TradeId == td.id && x.Status != "已完成");
if (groupAction != null)
{
groupAction.Status = "已完成";
tc.ParentTradeCashId = groupAction.ParentTradeCashId;
tc.ParentTradeId = groupAction.ParentTradeId;
}
tc.ValidState = "Valid";
tc.ExerciseWay = TradeCashExerciseWayEnum.提前终止行权;
//加入平仓份额和平仓日期
if (tc.UnwindType == "全部平仓")
{
td.TradeStatus = ConsTrade.已平仓;
tc.IsLastAction = true;
}
else
{
td.TradeStatus = ConsTrade.确认成交;
td.HasPartialUnWind = 1;
tc.IsLastAction = false;
}
td.UnWindDate = tc.ValueDate;
td.StockEqvNotional -= (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0);
td.Notional -= (td.OriginalNotional ?? 0) * (tc.UnwindPercentRate ?? 0);
//给TradeAmount赋对应的值
var CountRatio = UnderlyingDataProvider.GetCountRatio(td.UnderlyingCode);
td.TradeAmount = td.Notional / CountRatio;
td.UnWindNotional = tc.UnwindNotional;
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
if (td.ParentTradeId > 0)
{
var parentTrade = DbContext.trade.Find(td.ParentTradeId);
if (parentTrade != null)
{
parentTrade.StockEqvNotional -= (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0);
if (parentTrade.StockEqvNotional <= 0)
{
parentTrade.TradeStatus = "已平仓";
}
var tradeSwapDetail = DbContext.trade_swap_detail.FirstOrDefault(x => x.TradeId == parentTrade.id && x.ChildTradeId == td.id);
if (tradeSwapDetail != null)
{
tradeSwapDetail.Notional = td.Notional;
}
}
}
DbContext.SaveChanges();
//删除E/Bod数据
var delTcIds = tc.Action == ClientCashInCashOut.系统操作_互换 ? GetRemovedTcIdsForSwapSettlement(td.id, tc) : null;
RemoveEodTradeAndFutureInfo(saveChanges: true, tradeId: td.id, removeStartDate: tc.ValueDate, tradeCashIds: delTcIds);
return result;
}
/// <summary>
/// 互换交易平仓
/// </summary>
/// <param name="req"></param>
/// <param name="reqFromFrontUser">请求是否来自前端用户</param>
/// <returns></returns>
public TradeUnwindResultModel UnwindSwapTrade(TradeCashReq req)
{
var trade = DbContext.trade.Find(req.TradeId);
//平仓时如果盈亏为正,则以换汇买价结算,如果盈亏为负,则以换汇卖价结算(客户方向,和TradeCashReq方向相反)
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(trade.QuoteCurrency, trade.SettlementCurrency, req.ValueDate.Value
, seekPreday: true, currencyRateType: req.Amount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
req.QuoteUnwindFee = req.UnwindFee;
var getQuoteInitialAmount = req.trade_cash_swap.GetInitialAmount;
var payQuoteInitialAmount = req.trade_cash_swap.PayInitialAmount;
var getQuoteExtraAmount = req.trade_cash_swap.GetExtraAmount;
var payQuoteExtraAmount = req.trade_cash_swap.PayExtraAmount;
var getQuoteCostFee = req.trade_cash_swap.GetCostFee;
var payQuoteCostFee = req.trade_cash_swap.PayCostFee;
req.Amount *= currencyRate;
req.UnwindFee *= currencyRate;
req.InitialAmount *= currencyRate;
req.ExtraAmount *= currencyRate;
req.trade_cash_swap.GetAmount *= currencyRate;
req.trade_cash_swap.GetInitialAmount *= currencyRate;
req.trade_cash_swap.GetExtraAmount *= currencyRate;
req.trade_cash_swap.GetCostFee *= currencyRate;
req.trade_cash_swap.PayAmount *= currencyRate;
req.trade_cash_swap.PayInitialAmount *= currencyRate;
req.trade_cash_swap.PayExtraAmount *= currencyRate;
req.trade_cash_swap.PayCostFee *= currencyRate;
req.UnwindPercentRate /= 100;
var td = DbContext.trade.Find(req.TradeId);
if (td.StockEqvNotional / td.OriginalStockEqvNotional - req.UnwindPercentRate <= 1e-5)
{
req.UnwindType = "全部平仓";
req.UnwindPercentRate = td.OriginalStockEqvNotional > 0 ? td.StockEqvNotional / td.OriginalStockEqvNotional.Value : 0;
}
req.UnwindNotional = (td.OriginalNotional * req.UnwindPercentRate) ?? 0;
req.Notional = td.Notional;//前端传回来的数量小数位不足,所以这里要重新赋值,保证不会有精度损失;
req.TradeAmount = td.TradeAmount;
if (req.UnwindPercentRate <= 0)
{
throw new Exception("平仓比例不合理");
}
var result = new TradeUnwindResultModel(td);
//增加现金交割交易记录
var tc = CloseTrade_TradeCashSave(td, req, false, false, req.UnwindType != "部分平仓");
var groupAction = DbContext.trade_cash_group_action.FirstOrDefault(x => x.TradeId == td.id && x.Status != "已完成");
if (groupAction != null)
{
groupAction.Status = "已完成";
tc.ParentTradeCashId = groupAction.ParentTradeCashId;
tc.ParentTradeId = groupAction.ParentTradeId;
}
var tradeCash = DbContext.trade_cash.Where(y => y.TradeId == td.id && y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= tc.ValueDate).OrderByDescending(y => y.id).FirstOrDefault();
var tradeCashSwap = tradeCash == null ? null : DbContext.trade_cash_swap.FirstOrDefault(x => x.TradeCashId == tradeCash.id);
tc.StartDate = tradeCash?.ValueDate ?? td.StartDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = TradeCashExerciseWayEnum.提前终止行权;
tc.CurrencyRate = currencyRate;
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
tc.FinalPrice = trade_swap.IsGetFloatingProfit ? req.trade_cash_swap.GetFinalPrice : req.trade_cash_swap.PayFinalPrice;
//加入平仓份额和平仓日期
if (req.UnwindType == "全部平仓")
{
td.TradeStatus = "已平仓";
}
else
{
td.HasPartialUnWind = 1;
}
td.UnWindDate = tc.ValueDate;
td.StockEqvNotional -= (td.OriginalStockEqvNotional ?? 0) * req.UnwindPercentRate;
td.Notional -= (td.OriginalNotional ?? 0) * req.UnwindPercentRate;
td.UnWindNotional = tc.UnwindNotional;
//给TradeAmount赋对应的值
var CountRatio = UnderlyingDataProvider.GetCountRatio(td.UnderlyingCode);
td.TradeAmount = td.Notional / CountRatio;
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
td.OptId = (int)tc.OptId;
td.OptName = tc.OptName;
td.OptDate = DateTime.Now;
var trade_cash_swap = req.trade_cash_swap;
trade_cash_swap.StartDate = tc.StartDate;
trade_cash_swap.GetStartPrice = tradeCashSwap?.GetFinalPrice ?? trade_swap.GetSpotPrice;
trade_cash_swap.PayStartPrice = tradeCashSwap?.PayFinalPrice ?? trade_swap.PaySpotPrice;
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
var tcdGetInitialAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetInitialAmount,
QuoteAmount = getQuoteInitialAmount,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetInitialAmount);
var tcdGetExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetExtraAmount,
QuoteAmount = getQuoteExtraAmount,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetExtraAmount);
var tcdGetCostFee = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetCostFee,
QuoteAmount = getQuoteCostFee,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetCostFee);
var tcdPayInitialAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayInitialAmount,
QuoteAmount = -payQuoteInitialAmount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayInitialAmount);
var tcdPayExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayExtraAmount,
QuoteAmount = -payQuoteExtraAmount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayExtraAmount);
var tcdPayCostFee = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayCostFee,
QuoteAmount = -payQuoteCostFee,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayCostFee);
if (td.ParentTradeId > 0)
{
var parentTrade = DbContext.trade.Find(td.ParentTradeId);
if (parentTrade != null)
{
parentTrade.StockEqvNotional -= (td.OriginalStockEqvNotional ?? 0) * req.UnwindPercentRate;
if (parentTrade.StockEqvNotional <= 0)
{
parentTrade.TradeStatus = "已平仓";
}
var tradeSwapDetail = DbContext.trade_swap_detail.FirstOrDefault(x => x.TradeId == parentTrade.id && x.ChildTradeId == td.id);
if (tradeSwapDetail != null)
{
tradeSwapDetail.Notional = td.Notional;
}
}
}
#region 补充期末价格,对其部分重新赋值
trade_swap.GetFinalPrice = trade_cash_swap.GetFinalPrice;
trade_swap.PayFinalPrice = trade_cash_swap.PayFinalPrice;
#endregion
DbContext.SaveChanges();
SaveTradeOperationHistory(td, "提交平仓");
//删除E/Bod数据
RemoveEodTradeAndFutureInfo(true, td.id, tc.ValueDate);
return result;
}
/// <summary>
/// 提交互换收益结算申请
/// </summary>
public TradeUnwindResultModel ApplySwapTradeSettlement(TradeCashReq req)
{
var trade = DbContext.trade.Find(req.TradeId);
//平仓时如果盈亏为正,则以换汇买价结算,如果盈亏为负,则以换汇卖价结算(客户方向,和TradeCashReq方向相反)
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(trade.QuoteCurrency, trade.SettlementCurrency, req.ValueDate.Value
, currencyRateType: req.Amount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
req.QuoteUnwindFee = req.UnwindFee;
var getQuoteInitialAmount = req.trade_cash_swap.GetInitialAmount;
var payQuoteInitialAmount = req.trade_cash_swap.PayInitialAmount;
var getQuoteExtraAmount = req.trade_cash_swap.GetExtraAmount;
var payQuoteExtraAmount = req.trade_cash_swap.PayExtraAmount;
var getQuoteCostFee = req.trade_cash_swap.GetCostFee;
var payQuoteCostFee = req.trade_cash_swap.PayCostFee;
req.UnwindFee *= currencyRate;
req.Amount *= currencyRate;
req.InitialAmount *= currencyRate;
req.ExtraAmount *= currencyRate;
req.trade_cash_swap.GetAmount *= currencyRate;
req.trade_cash_swap.GetInitialAmount *= currencyRate;
req.trade_cash_swap.GetExtraAmount *= currencyRate;
req.trade_cash_swap.GetCostFee *= currencyRate;
req.trade_cash_swap.PayAmount *= currencyRate;
req.trade_cash_swap.PayInitialAmount *= currencyRate;
req.trade_cash_swap.PayExtraAmount *= currencyRate;
req.trade_cash_swap.PayCostFee *= currencyRate;
req.UnwindPercentRate /= 100;
var td = DbContext.trade.Find(req.TradeId);
req.Notional = td.Notional;//前端传回来的数量小数位不足,所以这里要重新赋值,保证不会有精度损失;
req.TradeAmount = td.TradeAmount;
var result = new TradeUnwindResultModel(td);
//增加现金交割交易记录
req.ValidState = ConsGlobal.InValid;
var tc = CloseTrade_TradeCashSave(td, req, false, false);
var tradeCash = DbContext.trade_cash.Where(y => y.TradeId == td.id && y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= tc.ValueDate).OrderByDescending(y => y.id).FirstOrDefault();
var tradeCashSwap = tradeCash == null ? null : DbContext.trade_cash_swap.FirstOrDefault(x => x.TradeCashId == tradeCash.id);
tc.StartDate = tradeCash?.ValueDate ?? td.StartDate.Value;
tc.Action = ClientCashInCashOut.系统操作_互换;
tc.UnwindType = null;
tc.CurrencyRate = currencyRate;
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
tc.FinalPrice = trade_swap.IsGetFloatingProfit ? req.trade_cash_swap.GetFinalPrice : req.trade_cash_swap.PayFinalPrice;
if (td.ExerciseDate > req.ValueDate)
{
tc.UnwindNotional = 0;
tc.UnwindTradeAmount = 0;
tc.UnwindPercentRate = 0;
tc.ExerciseWay = TradeCashExerciseWayEnum.提前终止行权;
tc.IsLastAction = false;
}
else
{
tc.ExerciseWay = TradeCashExerciseWayEnum.到期行权;
tc.IsLastAction = true;
if (td.ExerciseDate == req.ValueDate)
{
tc.ValueDate = td.SettlementDate ?? td.ExerciseDate.Value;
tc.HappenedDate = td.ExerciseDate;
tc.HappenedDate = QdpCalendarHelper.GetNonHoliday(tc.HappenedDate.Value);
}
}
var hasTradeProcess = HasTradeProcess();
CloseReCheck_SetTrade(td.id, true, hasTradeProcess);
var lastGetFinalPrice = tradeCashSwap?.GetFinalPrice;
var lastPayFinalPrice = tradeCashSwap?.PayFinalPrice;
var trade_cash_swap = req.trade_cash_swap;
trade_cash_swap.StartDate = tc.StartDate;
trade_cash_swap.GetStartPrice = lastGetFinalPrice ?? trade_swap.GetSpotPrice;
trade_cash_swap.PayStartPrice = lastPayFinalPrice ?? trade_swap.PaySpotPrice;
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
var tcdGetInitialAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetInitialAmount,
QuoteAmount = getQuoteInitialAmount,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetInitialAmount);
var tcdGetExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetExtraAmount,
QuoteAmount = getQuoteExtraAmount,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetExtraAmount);
var tcdGetCostFee = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetCostFee,
QuoteAmount = getQuoteCostFee,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetCostFee);
var tcdPayInitialAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayInitialAmount,
QuoteAmount = -payQuoteInitialAmount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayInitialAmount);
var tcdPayExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayExtraAmount,
QuoteAmount = -payQuoteExtraAmount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayExtraAmount);
var tcdPayCostFee = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayCostFee,
QuoteAmount = -payQuoteCostFee,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayCostFee);
DbContext.SaveChanges();
SaveTradeOperationHistory(td, "提交互换");
return result;
}
/// <summary>
/// 审批通过互换交易申请
/// </summary>
public TradeUnwindResultModel ApproveSwapTrade(trade td)
{
var result = new TradeUnwindResultModel(td);
//增加现金交割交易记录
var tc = CloseTrade_TradeCashSave(td, null, true, false);
var groupAction = DbContext.trade_cash_group_action.FirstOrDefault(x => x.TradeId == td.id && x.Status != "已完成");
if (groupAction != null)
{
groupAction.Status = "已完成";
tc.ParentTradeCashId = groupAction.ParentTradeCashId;
tc.ParentTradeId = groupAction.ParentTradeId;
}
tc.ValidState = "Valid";
//加入平仓份额和平仓日期
td.UnWindDate = tc.ValueDate;
if (td.ExerciseDate > tc.ValueDate)
{
td.TradeStatus = ConsTrade.确认成交;
tc.IsLastAction = false;
}
else
{
td.TradeStatus = ConsTrade.已到期;
td.Notional = 0;
td.StockEqvNotional = 0;
td.TradeAmount = 0;
tc.IsLastAction = true;
}
var tradeCashSwap = DbContext.trade_cash_swap.FirstOrDefault(x => x.TradeCashId == tc.id);
if (tradeCashSwap != null)
{
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
trade_swap.GetFinalPrice = tradeCashSwap.GetFinalPrice;
trade_swap.PayFinalPrice = tradeCashSwap.PayFinalPrice;
tc.FinalPrice = trade_swap.IsGetFloatingProfit ? tradeCashSwap.GetFinalPrice : tradeCashSwap.PayFinalPrice;
}
//增加出入金记录
var ee = new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
DbContext.SaveChanges();
//删除E/Bod数据
var delTcIds = tc.Action == ClientCashInCashOut.系统操作_互换 ? GetRemovedTcIdsForSwapSettlement(td.id, tc) : null;
RemoveEodTradeAndFutureInfo(saveChanges: true, tradeId: td.id, removeStartDate: tc.ValueDate, tradeCashIds: delTcIds);
return result;
}
/// <summary>
/// 获取互换收益结算执行后需要删除的后续trade cash ids
/// </summary>
private IEnumerable<int> GetRemovedTcIdsForSwapSettlement(int tradeId, trade_cash currentTc)
{
var query = from tc in DbContext.trade_cash
where tc.TradeId == tradeId
&& tc.Action == ClientCashInCashOut.系统操作_互换
&& tc.ValueDate > currentTc.ValueDate && tc.id != currentTc.id
&& (tc.HappenedDate == null || tc.HappenedDate > currentTc.ValueDate)
&& tc.ValidState != ConsGlobal.InValid && !tc.IsDeleted
select tc.id;
var ids = query.ToArray();
return ids.Any() ? ids : new[] { 0 };
}
public TradeUnwindResultModel SwapTrade(TradeCashReq req)
{
var trade = DbContext.trade.Find(req.TradeId);
//平仓时如果盈亏为正,则以换汇买价结算,如果盈亏为负,则以换汇卖价结算(客户方向,和TradeCashReq方向相反)
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(trade.QuoteCurrency, trade.SettlementCurrency, req.ValueDate.Value
, currencyRateType: req.Amount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
req.QuoteUnwindFee = req.UnwindFee;
var getQuoteInitialAmount = req.trade_cash_swap.GetInitialAmount;
var payQuoteInitialAmount = req.trade_cash_swap.PayInitialAmount;
var getQuoteExtraAmount = req.trade_cash_swap.GetExtraAmount;
var payQuoteExtraAmount = req.trade_cash_swap.PayExtraAmount;
var getQuoteCostFee = req.trade_cash_swap.GetCostFee;
var payQuoteCostFee = req.trade_cash_swap.PayCostFee;
req.UnwindFee *= currencyRate;
req.Amount *= currencyRate;
req.InitialAmount *= currencyRate;
req.ExtraAmount *= currencyRate;
req.trade_cash_swap.GetAmount *= currencyRate;
req.trade_cash_swap.GetInitialAmount *= currencyRate;
req.trade_cash_swap.GetExtraAmount *= currencyRate;
req.trade_cash_swap.PayAmount *= currencyRate;
req.trade_cash_swap.PayInitialAmount *= currencyRate;
req.trade_cash_swap.PayExtraAmount *= currencyRate;
req.UnwindPercentRate /= 100;
var td = DbContext.trade.Find(req.TradeId);
req.Notional = td.Notional;//前端传回来的数量小数位不足,所以这里要重新赋值,保证不会有精度损失;
req.TradeAmount = td.TradeAmount;
var result = new TradeUnwindResultModel(td);
//增加现金交割交易记录
var tc = CloseTrade_TradeCashSave(td, req, false, false);
var groupAction = DbContext.trade_cash_group_action.FirstOrDefault(x => x.TradeId == td.id && x.Status != "已完成");
if (groupAction != null)
{
groupAction.Status = "已完成";
tc.ParentTradeCashId = groupAction.ParentTradeCashId;
tc.ParentTradeId = groupAction.ParentTradeId;
}
var tradeCash = DbContext.trade_cash.Where(y => y.TradeId == td.id && y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= tc.ValueDate).OrderByDescending(y => y.id).FirstOrDefault();
var tradeCashSwap = tradeCash == null ? null : DbContext.trade_cash_swap.FirstOrDefault(x => x.TradeCashId == tradeCash.id);
tc.StartDate = tradeCash?.ValueDate ?? td.StartDate.Value;
tc.ValidState = "Valid";
tc.Action = ClientCashInCashOut.系统操作_互换;
tc.CurrencyRate = currencyRate;
tc.UnwindType = null;
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
tc.FinalPrice = trade_swap.IsGetFloatingProfit ? req.trade_cash_swap.GetFinalPrice : req.trade_cash_swap.PayFinalPrice;
if (td.ExerciseDate > req.ValueDate)
{
tc.UnwindNotional = 0;
tc.UnwindTradeAmount = 0;
tc.UnwindPercentRate = 0;
tc.ExerciseWay = TradeCashExerciseWayEnum.提前终止行权;
tc.IsLastAction = false;
}
else
{
tc.ExerciseWay = TradeCashExerciseWayEnum.到期行权;
//执行到期时,发生日期记为到期日
tc.HappenedDate = tc.ValueDate;
if (tc.ValueDate == td.ExerciseDate)
{
//非延期交易,如果有结算日期,资金记在结算日
tc.ValueDate = td.SettlementDate ?? tc.ValueDate;
}
tc.UnwindNotional = td.Notional;
tc.UnwindTradeAmount = td.TradeAmount;
tc.UnwindPercentRate = td.StockEqvNotional / td.OriginalStockEqvNotional;
td.Notional = 0;
td.StockEqvNotional = 0;
td.TradeAmount = 0;
td.TradeStatus = "已到期";
tc.IsLastAction = true;
if (td.ParentTradeId > 0)
{
var parentTrade = DbContext.trade.Find(td.ParentTradeId);
if (parentTrade != null)
{
parentTrade.StockEqvNotional -= (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0);
if (parentTrade.StockEqvNotional <= 0)
{
parentTrade.TradeStatus = "已平仓";
}
}
}
}
//加入平仓份额和平仓日期
td.UnWindDate = tc.ValueDate;
var lastGetFinalPrice = tradeCashSwap?.GetFinalPrice;
var lastPayFinalPrice = tradeCashSwap?.PayFinalPrice;
trade_swap.GetFinalPrice = req.trade_cash_swap.GetFinalPrice;
trade_swap.PayFinalPrice = req.trade_cash_swap.PayFinalPrice;
//增加出入金记录
var ee = new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var trade_cash_swap = req.trade_cash_swap;
trade_cash_swap.StartDate = tc.StartDate;
trade_cash_swap.GetStartPrice = lastGetFinalPrice ?? trade_swap.GetSpotPrice;
trade_cash_swap.PayStartPrice = lastPayFinalPrice ?? trade_swap.PaySpotPrice;
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
var getAmount = trade_cash_swap.GetAmount ?? 0;
var getExtraAmount = trade_cash_swap.GetExtraAmount ?? 0;
var tcdGetInitialAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetInitialAmount,
QuoteAmount = getQuoteInitialAmount,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetInitialAmount);
var tcdGetExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetExtraAmount,
QuoteAmount = getQuoteExtraAmount,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetExtraAmount);
var tcdGetCostFee = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = trade_cash_swap.GetCostFee,
QuoteAmount = getQuoteCostFee,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdGetCostFee);
var tcdPayInitialAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayInitialAmount,
QuoteAmount = -payQuoteInitialAmount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayInitialAmount);
var tcdPayExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayExtraAmount,
QuoteAmount = -payQuoteExtraAmount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayExtraAmount);
var tcdPayCostFee = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -trade_cash_swap.PayCostFee,
QuoteAmount = -payQuoteCostFee,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdPayCostFee);
DbContext.SaveChanges();
SaveTradeOperationHistory(td, "收益互换");
//删除E/Bod数据
var delTcIds = GetRemovedTcIdsForSwapSettlement(td.id, tc);
RemoveEodTradeAndFutureInfo(saveChanges: true, tradeId: td.id, removeStartDate: tc.ValueDate, tradeCashIds: delTcIds);
return result;
}
/// <summary>
/// 黑箱交易主交易tradecash保存子交易了结费用加和的值
/// clientcashincashout保存一条0的记录
/// 主要为了解决我们是按照子交易进行结算,但是客户结算报告,又想以主交易来展示主交易资金
/// </summary>
/// <param name="req"></param>
public void SaveGroupTradeCash(SaveGroupTradeCashReq req)
{
if (DbContext.trade_cash.Any(x => x.TradeId == req.trade_cash.TradeId && x.Status == null && x.ValidState != "InValid" && x.Action != "系统操作-期权费" && !x.IsDeleted))
{
throw new Exception("上一次分组了结还未完成,完成后才可以继续后需了结操作");
}
//如果选择的是主交易,则代表所有活着的子交易都参与结算
bool parentTrade = false;
if (req.tradeIds.Count == 1 && req.tradeIds.First() == req.trade_cash.TradeId)
{
parentTrade = true;
req.tradeIds = DbContext.trade.Where(x => x.ValidState != "InValid" && x.ParentTradeId == req.trade_cash.TradeId && x.TradeStatus == "确认成交").Select(x => x.id).ToList();
if (!req.tradeIds.Any())
{
throw new Exception("该分组交易没有可以了结操作的子交易,添加失败");
}
}
var action = req.trade_cash.Action;
var trade_cash = req.trade_cash;
var trade = DbContext.trade.Find(trade_cash.TradeId);
trade_cash.OptId = UserId;
trade_cash.OptName = UserName;
trade_cash.OptDate = DateTime.Now;
trade_cash.ValidState = ConsGlobal.InValid;
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(trade.UnderlyingCode);
if (trade.IsUsePremiumRate == true)
{
if (trade_cash.IsUnwindStockEqvNotional == true)
{
trade_cash.UnwindPercentRate = trade_cash.UnwindStockEqvNotional / trade.OriginalStockEqvNotional;
}
else
{
trade_cash.UnwindPercentRate = trade_cash.UnwindPercentRate / 100;
}
trade_cash.UnwindNotional = trade.OriginalNotional * trade_cash.UnwindPercentRate;
trade_cash.UnwindTradeAmount = trade_cash.UnwindNotional / underlying.CountRatio;
}
else
{
trade_cash.UnwindNotional = trade_cash.UnwindTradeAmount * underlying.CountRatio;
trade_cash.UnwindPercentRate = trade.OriginalNotional != 0 ? trade_cash.UnwindNotional / trade.OriginalNotional : 0;
}
bool isFromExercise = true;
if (trade_cash.Action == "全部平仓")
{
trade_cash.Action = ClientCashInCashOut.系统操作_平仓费;
trade_cash.IsLastAction = true;
trade_cash.ExerciseWay = "提前终止行权";
trade_cash.UnwindType = "全部平仓";
trade.TradeStatus = "已平仓";
isFromExercise = false;
}
else if (trade_cash.Action == "部分平仓")
{
trade_cash.Action = ClientCashInCashOut.系统操作_平仓费;
trade_cash.IsLastAction = false;
trade_cash.ExerciseWay = "提前终止行权";
trade_cash.UnwindType = "部分平仓";
isFromExercise = false;
if (trade_cash.UnwindNotional > trade.Notional)
{
throw new Exception("部分平仓,平仓数量需要小于剩余数量");
}
}
else if (trade_cash.Action == "部分提前行权")
{
trade_cash.Action = ClientCashInCashOut.系统操作_平仓费;
trade_cash.IsLastAction = false;
trade_cash.ExerciseWay = "提前终止行权";
trade_cash.UnwindType = "部分行权";
if (trade_cash.UnwindNotional >= trade.Notional)
{
throw new Exception("部分行权,行权数量需要小于剩余数量");
}
}
else if (trade_cash.Action == "全部提前行权")
{
trade_cash.Action = ClientCashInCashOut.系统操作_行权费;
trade_cash.IsLastAction = true;
trade_cash.ExerciseWay = "提前终止行权";
trade_cash.UnwindType = "全部行权";
trade.TradeStatus = "已执行";
}
else if (trade_cash.Action == "到期行权")
{
trade_cash.Action = ClientCashInCashOut.系统操作_行权费;
trade_cash.IsLastAction = true;
trade_cash.ExerciseWay = "到期行权";
trade_cash.UnwindType = "到期行权";
trade.TradeStatus = "已执行";
}
else if (trade_cash.Action == "到期")
{
trade_cash.Action = ClientCashInCashOut.系统操作_行权费;
trade_cash.IsLastAction = true;
trade_cash.ExerciseWay = "到期行权";
trade_cash.UnwindType = "到期";
trade.TradeStatus = "已到期";
}
using (var trans = BeginTransaction())
{
if (valuedateBLL.SystemDate.UnwindAmountAngle == 0 && trade.BuySell == "卖出")
{
trade_cash.Amount *= -1;
}
DbContext.trade_cash.Add(trade_cash);
DbContext.SaveChanges();
var hasProcess = DbContext.approvalprocess.Where(t => t.processType == "TradeProcess").Any();
var childTradeId = 0;
req.tradeIds.ForEach(x =>
{
if (x != req.trade_cash.TradeId && x != 0)
{
var groupAction = new trade_cash_group_action()
{
TradeId = x,
ParentTradeId = trade_cash.TradeId,
ParentTradeCashId = trade_cash.id,
Status = "待完成",
OptId = UserId,
OptName = UserName,
OptDate = DateTime.Now
};
if ((valuedateBLL.SystemDate.CloseReCheck == 1 || (valuedateBLL.SystemDate.CloseReApprove == 1 && hasProcess)) && !parentTrade)
{
UpdateTradeApproval(x);
}
childTradeId = x;
DbContext.trade_cash_group_action.Add(groupAction);
}
});
trade.IsApproval = parentTrade && !req.from_group_options_close_start_v1;
if (req.childTradeCashs != null && req.childTradeCashs.Count > 0)
{
SaveGroupChildTradeCashs(req, underlying.CountRatio, hasProcess, trade_cash.id, trade.TradeStatus, trans);
}
if ((valuedateBLL.SystemDate.CloseReCheck == 1 || (valuedateBLL.SystemDate.CloseReApprove == 1 && hasProcess)) && parentTrade)//主交易进审批流
{
new TradeCloseService(this).CloseReCheck_SetTrade(trade.id, isFromExercise, true);
}
else
{
#region---存入ClientCashInCashOut---
var cl = ClientDataQueryService.GetClient(trade.ClientId, true);
var ee = new ClientCashInCashOut
{
Direction = "应收",
Number = UniqueTimeId.GetStr(),
ClientId = cl.id,
ClientNumber = cl.Number,
ClientName = cl.Name,
HappenDate = trade_cash.ValueDate,
State = ClientCashInCashOut.已确认,
OptId = trade_cash.OptId,
OptName = trade_cash.OptName,
OptDate = trade_cash.OptDate,
CreatorId = trade_cash.OptId,
CreatorName = trade_cash.OptName,
CreateDate = trade_cash.OptDate,
TradeId = trade_cash.TradeId,
TradeCashId = trade_cash.id,
Action = trade_cash.Action,
TradeNumber = trade.TradeNumber,
IsGroup = trade.IsGroup
};
DbContext.ClientCashInCashOut.Add(ee);
#endregion
trade.TradeAmount -= (trade_cash.UnwindTradeAmount ?? 0);
trade.Notional -= (trade_cash.UnwindNotional ?? 0);
trade.StockEqvNotional -= (trade.OriginalStockEqvNotional * trade_cash.UnwindPercentRate ?? 0);
trade.UnWindNotional = trade_cash.UnwindNotional;
trade.UnWindDate = trade_cash.ValueDate;
trade.FinalPrice = req.trade_cash.FinalPrice;
trade_cash.ValidState = ConsGlobal.Valid;
if (parentTrade) //无复核无审批,group_action直接完成
{
FinishGroupTradeCash(trade_cash.id);
}
}
AddTradeOperationHistoryAndSetParentTradeInfo(false, trade, action);
//删除E/Bod数据
RemoveEodTradeAndFutureInfo(false, trade.id, req.trade_cash.ValueDate);
DbContext.SaveChanges();
trans.Commit();
}
}
/// <summary>
/// 修改交易分组了结 标识
/// </summary>
/// <param name="tradeId"></param>
private void UpdateTradeApproval(int tradeId)
{
var trade = DbContext.trade.Find(tradeId);
trade.IsApproval = true;
}
public void SaveGroupChildTradeCashs(SaveGroupTradeCashReq req, int countRatio, bool hasProcess, int parentTradeCashId, string tradeStatus, IDbContextTransaction trans)
{
req.childTradeCashs.ForEach(x =>
{
trade td = DbContext.trade.Where(l => l.TraderId == x.id).FirstOrDefault();
var unwindPrice = x.UnwindTradeAmount == 0 ? 0 : x.Amount / x.UnwindTradeAmount;
var tradeCashReq = new TradeCashReq()
{
ValueDate = req.trade_cash.ValueDate,
TradeId = x.TradeId,
TradeAmount = x.TradeAmount,
Notional = x.Notional,
UnwindFee = x.Amount,
Amount = x.Amount,
UnwindPrice = unwindPrice,
UnwindPricePercentRate = TradeHelper.GetPremiumRateByTradeSinglePrice(unwindPrice, td?.SpotPrice),
UnwindTradeAmount = x.UnwindTradeAmount,
UnwindNotional = (x.UnwindTradeAmount ?? 0) * countRatio,
UnwindPercentRate = x.UnwindPercentRate ?? 0,
UnwindStockEqvNotional = x.UnwindStockEqvNotional,
CallPut = x.OptionType,
ExceciseType = "现金",
FinalPrice = req.trade_cash.FinalPrice,
UnwindType = req.trade_cash.UnwindType,
ParentTradeCashId = parentTradeCashId,
TradeStatus = tradeStatus
};
if (valuedateBLL.SystemDate.CloseReCheck == 1 || (valuedateBLL.SystemDate.CloseReApprove == 1 && hasProcess))
{
if (req.trade_cash.UnwindType.Contains("到期"))
{
tradeCashReq.IsExpire = true;
tradeCashReq.ValidState = ConsGlobal.InValid;
new TradeExerciseService(this).ApplyExerciseRecheck(tradeCashReq);
}
else
{
new TradeCloseService(this).CloseReCheck(tradeCashReq, false);
}
}
else
{
if (req.trade_cash.UnwindType.Contains("到期"))
{
new TradeCashService(this).ExecutionTradeCash(tradeCashReq);
}
else
{
UnwindTrade(tradeCashReq, trans);
}
}
});
}
public void FinishGroupTradeCash(int TcId)
{
var tradeCash = DbContext.trade_cash.Find(TcId);
if (tradeCash != null)
{
tradeCash.Status = "已执行";
var childrenTradeCash = DbContext.trade_cash.Where(x => x.ParentTradeCashId == TcId).ToList();
tradeCash.Amount = childrenTradeCash.Sum(x => x.Amount);
tradeCash.UnwindPrice = tradeCash.UnwindNotional != 0 ? tradeCash.Amount / tradeCash.UnwindNotional : 0;
var trade = DbContext.trade.Find(tradeCash.TradeId);
tradeCash.UnwindPricePercentRate = TradeHelper.GetPremiumRateByTradeSinglePrice(tradeCash.UnwindPrice, trade.SpotPrice);
var groupActions = DbContext.trade_cash_group_action.Where(x => x.ParentTradeCashId == TcId).ToList();
groupActions.ForEach(x => x.Status = "已完成");
DbContext.SaveChanges();
}
else
{
throw new Exception("未找到该笔了结记录");
}
}
public void CloseReCheck_SetTrade(int tradeId, bool isSwap, bool hasTradeProcess)
{
var td = DbContext.trade.Find(tradeId);
td.OptId = UserId;
td.OptName = UserName;
td.OptDate = OptDate;
if (td.TradeStatus!=ConsTrade.确认成交)
{
throw new Exception("当前交易状态不是确认成交");
}
if (isSwap)
{
td.TradeStatus = ConsTrade.互换待复核;
}
else
{
td.TradeStatus = ConsTrade.平仓待复核;
}
td.CheckStatus = Convert.ToInt32(TradeCheckEnum.StatusOfOld);
//检查是否有交易审批流程
if ((valuedateBLL.SystemDate.CloseReApprove == 1 || isSwap) && hasTradeProcess)
{
//如果有审批组
InitTradeProcessOrder(td, UserId);
}
AddTradeOperationHistoryAndSetParentTradeInfo(false, td, isSwap ? "互换审核提交" : "平仓审核提交");
}
}
/// <summary>
/// 交易平仓操作结果
/// </summary>
public class TradeUnwindResultModel
{
public trade Trade;
public trade_cash TradeCash;
/// <summary>
/// 是否复核审批
/// </summary>
public bool ApprovalProcess;
//----------------------------
//以下是平仓处理结果
/// <summary>
/// 是否有配对交易
/// </summary>
public bool HasPairTrade;
/// <summary>
/// 是否配对交易平仓成功
/// </summary>
public bool PairTradeUnwindSuccess;
/// <summary>
/// 配对交易平仓出错消息
/// </summary>
public Exception PairTradeUnwindException;
public TradeUnwindResultModel(trade trade)
{
Trade = trade;
}
}
}