156 lines
5.8 KiB
C#
156 lines
5.8 KiB
C#
using YLErp.BLL;
|
|
using YLErp.Model;
|
|
using YLErp.Model.Enum;
|
|
using YLErp.Modules.TradeDalModule;
|
|
|
|
namespace YLErp.Modules.TradeModule.DealModule
|
|
{
|
|
/// <summary>
|
|
/// 交易平仓操作
|
|
/// </summary>
|
|
public class TradeCloseService : TradeCashService
|
|
{
|
|
public TradeCloseService(YLBaseService baseService) : base(baseService)
|
|
{
|
|
}
|
|
|
|
public TradeCloseService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// 平仓待复核提交
|
|
/// </summary>
|
|
public TradeCashResult CloseReCheck(TradeCashReq req, bool isFromExercise = false)
|
|
{
|
|
var tradeDalService = new TradeDalService(OptUser);
|
|
|
|
//这个对象只提供收盘前数据,用于创建TradeCash记录
|
|
var td = tradeDalService.GetTradeOrEodTrade(new[] { req.TradeId }, req.ValueDate ?? SystemValueDate).FirstOrDefault();
|
|
|
|
if (td == null)
|
|
{
|
|
if (isFromExercise)
|
|
{
|
|
throw new ServiceException("行权失败,该交易不存在,不能提交行权审核");
|
|
}
|
|
else
|
|
{
|
|
throw new ServiceException("平仓失败,该交易不存在,不能提交平仓审核");
|
|
}
|
|
}
|
|
|
|
if (td.TradeType == "结构化交易")
|
|
{
|
|
throw new ServiceException("操作失败,结构化交易主交易不支持此操作");
|
|
}
|
|
|
|
if (td.TradeStatus != ConsTrade.确认成交 && td.TradeStatus != ConsTrade.提前终止拒绝)
|
|
{
|
|
if (isFromExercise)
|
|
{
|
|
throw new ServiceException("行权失败,该交易处于待" + td.TradeStatus + "状态,不能提交行权审核!");
|
|
}
|
|
else
|
|
{
|
|
throw new ServiceException("平仓失败,该交易处于待" + td.TradeStatus + "状态,不能提交平仓审核!");
|
|
}
|
|
}
|
|
|
|
if (PS.Config.TradeElement.ExecuteAfterGeneratedConfirmDoc && td.TradeType != "远期" && td.TradeType != "自定义交易" && td.TradeType != "现金流交易"
|
|
&& !DbContext.trade_contract_r.Any(n => n.TradeId == td.id && n.Type == "交易确认书" && n.IsValid))
|
|
{
|
|
throw new ServiceException("请先去生成交易确认书");
|
|
}
|
|
|
|
bool isPartialClose = false;
|
|
if (req != null)
|
|
{
|
|
unwindPreHandle(req, td, isFromExercise, out isPartialClose);
|
|
}
|
|
|
|
//保存tradecash
|
|
//增加现金交割交易记录
|
|
req.ValidState = ConsGlobal.InValid;
|
|
|
|
var tc = CloseTrade_TradeCashSave(td, req, false, !isFromExercise, !isPartialClose);
|
|
|
|
var hasTradeProcess = HasTradeProcess();
|
|
|
|
CloseReCheck_SetTrade(td.id, isFromExercise, hasTradeProcess);
|
|
|
|
//配对 平仓待复合提交
|
|
if (req.IsUnwindPairTrade && !string.IsNullOrEmpty(td.PairTrade))
|
|
{
|
|
int pairTradeId = Convert.ToInt32(td.PairTrade);
|
|
//这个对象只提供收盘前数据,用于创建TradeCash记录
|
|
var pairTrade = tradeDalService.GetTradeOrEodTrade(new[] { pairTradeId }, req.ValueDate.Value).FirstOrDefault();
|
|
|
|
//配对交易平仓总份额取各自剩余的总份额
|
|
req.Notional = pairTrade.Notional;
|
|
//UnwindNotional >= Notional代表全部品仓,配对交易的平仓份额为自己剩余的总份额
|
|
//UnwindNotional < td.Notional部分平仓,配对的两笔交易部分平仓份额相等,即req.UnwindNotional不变
|
|
if (req.UnwindNotional >= Math.Floor(pairTrade.Notional * Math.Pow(10, 8)) / Math.Pow(10, 8))
|
|
{
|
|
req.UnwindNotional = pairTrade.Notional;
|
|
}
|
|
if (isFromExercise)
|
|
{
|
|
req.UnwindFee = -req.UnwindFee;
|
|
}
|
|
CloseTrade_TradeCashSave(pairTrade, req, !isFromExercise, !isPartialClose);
|
|
|
|
CloseReCheck_SetTrade(pairTrade.id, isFromExercise, hasTradeProcess);
|
|
}
|
|
|
|
DbContext.SaveChanges();
|
|
|
|
return new TradeCashResult(td, tc);
|
|
}
|
|
|
|
//平仓待复核提交
|
|
public void CloseReCheck_SetTrade(int tradeId, bool isFromExercise, bool hasTradeProcess)
|
|
{
|
|
var td = DbContext.trade.Find(tradeId);
|
|
td.OptId = UserId;
|
|
td.OptName = UserName;
|
|
td.OptDate = OptDate;
|
|
if (isFromExercise)
|
|
{
|
|
td.TradeStatus = ConsTrade.行权待复核;
|
|
}
|
|
else
|
|
{
|
|
td.TradeStatus = ConsTrade.平仓待复核;
|
|
}
|
|
|
|
td.CheckStatus = Convert.ToInt32(TradeCheckEnum.StatusOfOld);
|
|
|
|
//检查是否有交易审批流程(需求②:平仓/行权按交易状态查对应流程,而非只查开仓流程)
|
|
if (valuedateBLL.SystemDate.CloseReApprove == 1 && TradeProcessCountByCategory(td) > 0)
|
|
{
|
|
// 如果有审批组
|
|
InitTradeProcessOrder(td, UserId);
|
|
}
|
|
|
|
AddTradeOperationHistoryAndSetParentTradeInfo(false, td, isFromExercise ? "部分行权审核提交" : "平仓审核提交");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class TradeCashResult
|
|
{
|
|
public TradeCashResult(trade td, trade_cash tc)
|
|
{
|
|
Trade = td ?? throw new ArgumentNullException(nameof(td));
|
|
TradeCash = tc ?? throw new ArgumentNullException(nameof(tc));
|
|
}
|
|
|
|
public trade Trade { get; }
|
|
|
|
public trade_cash TradeCash { get; }
|
|
}
|
|
}
|