Files
zszq-trs/YLErpDAL/Modules/TradeModule/ForwardModule/TradeForwardUnwindService.cs
T
2024-05-09 14:06:26 +08:00

181 lines
6.8 KiB
C#

using YLErp.BLL;
using YLErp.DBModels.Converts;
namespace YLErp.Modules.TradeModule.ForwardModule
{
/// <summary>
/// 远期交易平仓服务
/// </summary>
public class TradeForwardUnwindService : TradeServiceBase
{
public TradeForwardUnwindService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// from fowardTradeController.TradeUnwind
/// </summary>
public PrepareForwardUnwindResult PrepareUnwind(int tradeId, bool isUseApproval = false)
{
var result = new PrepareForwardUnwindResult();
var td = DbContext.trade.Find(tradeId);
var tc = new trade_cash();
if (td == null)
{
throw new ServiceException("找不到现金交割交易");
}
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
result.HasProcess = HasTradeProcess();
if (((valuedateBLL.SystemDate.CloseReCheck == 1) || (valuedateBLL.SystemDate.CloseReApprove == 1 && result.HasProcess)) && td.TradeStatus == ConsTrade.平仓待复核)
{
tc = DbContext.trade_cash.FirstOrDefault(t => t.TradeId == tradeId && t.Action == ClientCashInCashOut.系统操作_平仓费 && t.ValidState == ConsGlobal.InValid && !t.IsDeleted);
if (tc == null)
{
throw new ServiceException("该笔交易状态为平仓待复核,而trade_cash表没有相关记录,请检查该笔交易是否有效");
}
}
else
{
tc = SetTradeUnwind(td, um);
}
tc.InitialSpotPrice = td.SpotPrice ?? 0;
tc.UnderlyingCode = um.UnderlyingCode;
tc.UnderlyingId = um.id;
tc.TradeOriginalAmount = td.OriginalNotional / um.CountRatio;
tc.UnderlyingInstrumentType = td.UnderlyingInstrumentType;
tc.BondType = td.TradeType;
tc.TradeType = BuySellConvert.GetClientBuySell(td.BuySell);
tc.UnwindType = string.IsNullOrEmpty(tc.UnwindType) ? "全部平仓" : tc.UnwindType;
if (!isUseApproval)
{
tc.TradeAmount = td.TradeAmount;
tc.UnwindPrice = 0;
}
result.Trade = td;
result.TradeCash = tc;
result.OtcTradeForward = new TradeForwardService(OptUser).GetDetail(tradeId);
if (!string.IsNullOrEmpty(td.PairTrade))
{
var pid = Convert.ToInt32(td.PairTrade);
result.PairTrade = DbContext.trade.Find(pid);
}
result.Underlying = um;
result.Variety = new VarietyBasic
{
CountRatio = um.CountRatio,
TradeUnitValue = um.ContractSize,
VarietyCode = um.CommodityCode
};
//在当日收盘前部分了解,预付金成本累加获取
//远期交易最后一笔平仓时的预付金成本特殊情况处理: 触发条件:
//1.最后一笔平仓
//2.当前交易日和前一个交易日中间有假期
// 处理规则:
// 预付金成本 = 这笔平仓上一交易日预付金成本 + 这笔平仓假期日的预付金成本
var valueDate = valuedateBLL.ValueDate;
if (valueDate > td.ExerciseDate)
{
valueDate = td.ExerciseDate.Value;
}
var lastMarginRecord = DbContext.eod_forward_margin.Where(f => f.TradeId == tc.TradeId && f.ValueDate < valueDate).OrderByDescending(x => x.ValueDate).FirstOrDefault();
result.MaxUnwindDate = td.ExerciseDate.Value;
if (td.ExerciseDate.Value > valuedateBLL.ValueDate)
{
result.MaxUnwindDate = valuedateBLL.ValueDate;
}
if (!isUseApproval)
{
result.TradeCash.ValueDate = valuedateBLL.ValueDate <= td.ExerciseDate ? valuedateBLL.ValueDate : td.ExerciseDate.Value;
}
if (lastMarginRecord != null)
{
//这段代码注释掉,在前端平仓页面使用MaxUnwindDate限制最大平仓日期选择
//var lastSettleDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(-1));
//if (lastSettleDate != lastMarginRecord.ValueDate)
//{
// throw new ServiceException($"请确保上一交易日({lastSettleDate:yyyy-MM-dd})已结算收盘!请尝试从{lastMarginRecord.ValueDate}之后,开始收盘!");
//}
var totaldays = (valuedateBLL.ValueDate.Date - lastMarginRecord.ValueDate.Date).TotalDays;
result.HolidayMargin = lastMarginRecord.SettlePrice * lastMarginRecord.MarginRate * lastMarginRecord.AnnualRate * totaldays / 365;
result.LastMarginRecord = lastMarginRecord;
}
else
{
//交易日当天
result.HolidayMargin = 0;
result.LastMarginRecord = new eod_forward_margin();
}
return result;
}
private trade_cash SetTradeUnwind(trade td, underlying_manager um)
{
var r = new trade_cash
{
TradeId = td.id,
FinalPrice = um.Price ?? 0,
ExceciseType = "现金",
CallPut = td.CallPut,
Strike = td.Strike,
Notional = td.Notional,
InitialSpotPrice = td.SpotPrice ?? 0,
UnderlyingInstrumentType = td.UnderlyingInstrumentType,
StockEqvNotional = td.StockEqvNotional,
UnwindNotional = td.Notional,
Amount = 0,
ValueDate = valuedateBLL.ValueDate <= td.ExerciseDate ? valuedateBLL.ValueDate : td.ExerciseDate.Value,
TradeType = BuySellConvert.GetClientBuySell(td.BuySell)
};
r.TradeAmount = r.Notional / um.CountRatio;
r.UnwindTradeAmount = r.UnwindNotional / um.CountRatio;
return r;
}
}
public class PrepareForwardUnwindResult
{
public trade Trade { get; set; }
public trade_cash TradeCash { get; set; }
public OtcTradeForward OtcTradeForward { get; set; }
public trade PairTrade { get; set; }
public underlying_manager Underlying { get; set; }
public VarietyBasic Variety { get; set; }
public double HolidayMargin { get; set; }
public eod_forward_margin LastMarginRecord { get; set; }
public DateTime MaxUnwindDate { get; set; }
/// <summary>
/// 是否有审批步骤
/// </summary>
public bool HasProcess { get; set; }
}
}