181 lines
6.8 KiB
C#
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; }
|
|
|
|
}
|
|
}
|