Files
zszq-trs/YLErpDAL/Modules/EodModule/SettlementModule/EodSwapSettleService.cs
T
2024-05-09 14:06:26 +08:00

299 lines
16 KiB
C#

using YLErp.BLL;
using YLErp.DBModels.Converts;
using YLErp.Model;
using YLErp.Modules.CalculationModule;
using YLErp.Modules.TradeModule;
using YLErp.Modules.TradeModule.DealModule;
using YLErp.Modules.UnderlyingModule;
using YLErp.QdpModule;
namespace YLErp.Modules.EodModule.SettlementModule
{
/// <summary>
/// 日终互换自动结息
/// </summary>
internal class EodSwapSettleService : TradeCashService
{
public EodSwapSettleService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// 定期结算互换
/// </summary>
public void BalanceSwapTrade(DateTime settleDate, IEnumerable<int> clientIds = null)
{
var dateStr = settleDate.ToString("yyyy-MM-dd");
var observateTrades = new List<trade>();
#region 第一步 获取当前观察日交易
var tradePredicate = PredicateBuilder.Create<trade>(n => n.ValidState != ConsGlobal.InValid
&& n.TradeType == "收益互换"
&& n.IsGroup != 2
&& n.StartDate <= settleDate
&& n.ExerciseDate >= settleDate
&& n.TradeStatus == ConsTrade.确认成交);
if (clientIds != null && clientIds.Any())
{
tradePredicate = tradePredicate.And(l => clientIds.Contains(l.ClientId));
}
var tradeQueryList = DbContext.trade.Where(tradePredicate).ToList();
var tradeIds = tradeQueryList.Select(s => s.id).ToList();
var tradeSwapList = DbContext.trade_swap.Where(t => tradeIds.Contains(t.TradeId)
&& ((t.GetSwapTimeAndRate != null && t.GetSwapTimeAndRate.Contains(dateStr))
|| (t.PaySwapTimeAndRate != null && t.PaySwapTimeAndRate.Contains(dateStr)))
).ToList();
foreach (var trade in tradeQueryList)
{
var tradeSwap = tradeSwapList.FirstOrDefault(x => x.TradeId == trade.id);
var tradeExerciseDate = trade.ExerciseDate.Value.ToString("yyyy-MM-dd");
if (tradeExerciseDate != dateStr && tradeSwap != null && ((tradeSwap.GetSwapTimeAndRate != null && tradeSwap.GetSwapTimeAndRate.Contains(dateStr))
|| (tradeSwap.PaySwapTimeAndRate != null && tradeSwap.PaySwapTimeAndRate.Contains(dateStr))))
{
var getCalc = CalcDate(tradeSwap.GetSwapTimeAndRate, dateStr);
var payCalc = CalcDate(tradeSwap.PaySwapTimeAndRate, dateStr);
if (getCalc || payCalc)
{
trade.trade_swap = tradeSwap;
observateTrades.Add(trade);
}
}
}
#endregion
if (!observateTrades.Any())
{
return;
}
#region 第二步 计算观察日收益
var tradeObservateIds = observateTrades.Select(s => s.id).ToList();
var tradeCashPredicate = PredicateBuilder.Create<trade_cash>(n => tradeObservateIds.Contains(n.TradeId) && !n.IsDeleted && n.Action == ClientCashInCashOut.系统操作_互换);
var tradeCashList = DbContext.trade_cash.Where(tradeCashPredicate).ToList();
var tradeCashIds = tradeCashList.Select(x => x.id);
var cashSwaps = DbContext.trade_cash_swap.Where(x => tradeObservateIds.Contains(x.TradeId) && tradeCashIds.Contains(x.TradeCashId)).ToArray();
foreach (var trade in observateTrades)
{
//历史收盘时,如果已进行过互换则排除
if (tradeCashList.Any(x => x.TradeId == trade.id && x.ValidState != ConsGlobal.InValid && x.ValueDate >= settleDate))
{
continue;
}
tradeBLL.SetFieldsByTradeType(trade);
var tradeCashNotInvalid = tradeCashList.Where(x => x.TradeId == trade.id && x.ValidState != ConsGlobal.InValid).OrderByDescending(y => y.id).FirstOrDefault();
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(trade.UnderlyingCode);
var commodity = ConsGlobal.InstrumentType.CalcTypeIsFutures(um.UnderlyingInstrumentType);
trade.trade_cash = InitTradeCash(trade, um);
trade.trade_cash.ValueDate = settleDate;
trade.trade_cash.UnwindMethod = commodity ? 1 : 0;
InitTradeAndTradeCash(trade, trade.trade_cash, um, tradeCashNotInvalid);
var oldMaturityDate = new ExtensionTimeService(UserInfo).QueryExtensionTimeList(trade.id).OrderByDescending(x => x.OldMaturityDate)?.FirstOrDefault()?.OldMaturityDate;
trade.trade_swap.GetSwapRate = GetSwapRateByDate(trade.trade_swap.GetSwapTimeAndRate, trade.trade_cash.ValueDate, 1, trade.trade_swap.IsGetFloatingProfit, oldMaturityDate);
trade.trade_swap.PaySwapRate = GetSwapRateByDate(trade.trade_swap.PaySwapTimeAndRate, trade.trade_cash.ValueDate, 1, trade.trade_swap.IsPayFloatingProfit, oldMaturityDate);
trade.trade_cash.trade_cash_swap = new trade_cash_swap()
{
GetFinalPrice = trade.trade_swap.GetSpotPrice,
PayFinalPrice = trade.trade_swap.PaySpotPrice,
GetCostFee = 0,
PayCostFee = 0,
GetExtraAmount = 0,
PayExtraAmount = 0,
PayAmount = 0,
PayInitialAmount = 0,
GetSwapRate = 0,
PaySwapRate = 0,
IsAuto = true,
GetInitialAmount = 0,
GetAmount = 0
};
//取最后一次手动收益;
var lastManualCashSwap = cashSwaps.OrderByDescending(o => o.StartDate).FirstOrDefault(x => !x.IsAuto && x.TradeId == trade.id);
var lastManualCash = lastManualCashSwap != null ? tradeCashList.FirstOrDefault(x => x.id == lastManualCashSwap.TradeCashId) : null;
if (!trade.trade_swap.IsGetFloatingProfit)//收取 利息
{
DateTime endDate;
var preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(trade, trade.trade_swap, trade.trade_cash.ValueDate, tradeCashNotInvalid, lastManualCash, trade.trade_swap.IsGetFloatingProfit, out endDate);
trade.trade_cash.trade_cash_swap.GetExtraAmount = PayoffSwapCalcService.GetExtraAmountBySwapRate(trade.ClientId, trade.TradeDate, trade.trade_swap.GetSwapTimeAndRate, preSwapDate, endDate, trade.trade_swap.AnnualDays ?? 0, (trade.OriginalStockEqvNotional ?? 0) * (trade.trade_cash.UnwindPercentRate ?? 0));
trade.trade_cash.trade_cash_swap.GetInitialAmount = PayoffSwapCalcService.GetInitialAmountSwapGet(trade, trade.trade_swap, trade.trade_swap.GetSpotPrice ?? 0
, trade.trade_swap.GetSpotPrice ?? 0, (trade.OriginalStockEqvNotional ?? 0) * (trade.trade_cash.UnwindPercentRate ?? 0), trade.trade_cash.ValueDate, tradeCashNotInvalid?.ValueDate);
}
if (!trade.trade_swap.IsPayFloatingProfit)//支付 利息
{
DateTime endDate;
var preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(trade, trade.trade_swap, trade.trade_cash.ValueDate, tradeCashNotInvalid, lastManualCash, trade.trade_swap.IsPayFloatingProfit, out endDate);
trade.trade_cash.trade_cash_swap.PayInitialAmount = PayoffSwapCalcService.GetInitialAmountSwapPay(trade, trade.trade_swap, trade.trade_swap.PaySpotPrice ?? 0
, trade.trade_swap.PaySpotPrice ?? 0, (trade.OriginalStockEqvNotional ?? 0) * (trade.trade_cash.UnwindPercentRate ?? 0), trade.trade_cash.ValueDate, tradeCashNotInvalid?.ValueDate);
trade.trade_cash.trade_cash_swap.PayExtraAmount = PayoffSwapCalcService.GetExtraAmountBySwapRate(trade.ClientId, trade.TradeDate, trade.trade_swap.PaySwapTimeAndRate, preSwapDate, trade.trade_cash.ValueDate, trade.trade_swap.AnnualDays ?? 0, (trade.OriginalStockEqvNotional ?? 0) * (trade.trade_cash.UnwindPercentRate ?? 0));
}
trade.trade_cash.trade_cash_swap.PaySwapRate = trade.trade_swap.PaySwapRate;
trade.trade_cash.trade_cash_swap.GetSwapRate = trade.trade_swap.GetSwapRate;
trade.trade_cash.trade_cash_swap.GetAmount = trade.trade_cash.trade_cash_swap.GetInitialAmount + trade.trade_cash.trade_cash_swap.GetExtraAmount + trade.trade_cash.trade_cash_swap.GetCostFee;
trade.trade_cash.trade_cash_swap.PayAmount = trade.trade_cash.trade_cash_swap.PayInitialAmount + trade.trade_cash.trade_cash_swap.PayExtraAmount + trade.trade_cash.trade_cash_swap.PayCostFee;
trade.trade_cash.Amount = (trade.trade_cash.trade_cash_swap.GetAmount ?? 0) - (trade.trade_cash.trade_cash_swap.PayAmount ?? 0);
trade.trade_cash.Notional = trade.trade_cash.TradeAmount.Value * (um.CountRatio == 0 ? 1 : um.CountRatio);
#region 第三步 单个封装对象保存
var req = new TradeCashReq
{
TradeId = trade.id,
ValueDate = trade.trade_cash.ValueDate,
Amount = trade.trade_cash.Amount,
UnwindFee = trade.trade_cash.Amount,
InitialAmount = trade.trade_cash.InitialAmount,
ExtraAmount = trade.trade_cash.ExtraAmount ?? 0,
UnwindMethod = trade.trade_cash.UnwindMethod ?? 0,
UnwindStockEqvNotional = trade.trade_cash.UnwindStockEqvNotional,
UnwindPrice = trade.trade_cash.UnwindPrice,
FinalPrice = trade.trade_cash.FinalPrice,
SpotPrice = trade.trade_cash.SpotPrice,
UnwindVol = trade.trade_cash.UnwindVol,
HappenedDate = trade.trade_cash.HappenedDate,
BarrierPrice = trade.trade_cash.BarrierPrice,
VolType = trade.trade_cash.VolType,
UnwindType = trade.trade_cash.UnwindType,
UnwindPercentRate = (trade.trade_cash.UnwindPercentRate * 100) ?? 0,
UnwindPricePercentRate = trade.trade_cash.UnwindPercentRate ?? 0,
TradePremium = trade.trade_cash.TradePremium,
AdvanceMoney = trade.trade_cash.AdvanceMoney,
trade_cash_swap = trade.trade_cash.trade_cash_swap
};
var result = new TradeUnwindService(this).SwapTrade(req);
#endregion
}
#endregion
}
/// <summary>
/// 初始化收益互换值
/// </summary>
private trade_cash InitTradeCash(trade td, underlying_manager um)
{
var r = new trade_cash
{
TradeId = td.id,
FinalPrice = um.UnderlyingType == "组合标的" ? new SyntheticUnderlyingPriceService(UserInfo).GetPrice(td.UnderlyingCode) : (um.Price ?? 0),
ExceciseType = "现金",
CallPut = td.CallPut,
Strike = td.IsMoneynessOptionData ? (td.Strike * td.SpotPrice) : td.Strike,
Notional = td.Notional,
UnwindType = "全部平仓",
UnwindNotional = td.Notional,
UnwindPercentRate = td.StockEqvNotional / td.OriginalStockEqvNotional,
Amount = 0
};
r.TradeAmount = r.Notional / um.CountRatio;
r.UnwindTradeAmount = r.UnwindNotional / um.CountRatio;
return r;
}
/// <summary>
/// 初始化收益互换值
/// </summary>
private void InitTradeAndTradeCash(trade td, trade_cash r, underlying_manager um, trade_cash notInvalid)
{
r.StockEqvNotional = td.StockEqvNotional;
r.OriginalStockEqvNotional = td.OriginalStockEqvNotional ?? 0;
r.IsUsePremiumRate = td.IsUsePremiumRate;
r.IsTradePricePayType = td.IsTradePricePayType;
if (td.IsUsePremiumRate != null && td.IsUsePremiumRate.Value)
{
//r.UnwindPercentRate *= 100;
}
else
{
r.UnwindPercentRate = 0;
}
r.TradeOriginalAmount = td.OriginalNotional / um.CountRatio;
r.OriginalNotional = td.OriginalNotional;
r.UnderlyingCode = td.UnderlyingCode;
r.UnderlyingId = um.id;
r.UnderlyingInstrumentType = td.UnderlyingInstrumentType;
r.TradeType = BuySellConvert.GetClientBuySell(td.BuySell);
r.BondType = td.TradeType;
r.ClientName = td.ClientName;
r.TraderName = td.TraderName;
r.UnwindStockEqvNotional = r.UnwindStockEqvNotional ?? 0;
r.StartDate = notInvalid?.ValueDate ?? td.StartDate.Value;
r.ExtraAmount = td.OriginalStockEqvNotional > 0 ? (td.trade_swap.IsTradePriceWhenOpen ? ((td.trade_swap.GetTradePrice ?? 0) - (td.trade_swap.PayTradePrice ?? 0)) : ((td.trade_swap.GetTradePrice ?? 0) - (td.trade_swap.PayTradePrice ?? 0)) * 2) * td.StockEqvNotional / td.OriginalStockEqvNotional : 0;
//td.trade_swap.GetSpotPrice = td.trade_swap.GetFinalPrice ?? td.trade_swap.GetSpotPrice ?? 0;
//td.trade_swap.PaySpotPrice = td.trade_swap.PayFinalPrice ?? td.trade_swap.PaySpotPrice ?? 0;
}
/// <summary>
/// 校验某观察日是否结算
/// </summary>
private bool CalcDate(string swapTime, string dataStr)
{
if (string.IsNullOrEmpty(swapTime))
{
return false;
}
var calc = false;
var filedArr = swapTime.Split(';');
var dateListArr = filedArr[0];
if (filedArr.Length > 2)
{
var calcListArr = filedArr[2];//是否结算
var calcList = calcListArr.Split(',');
var dateList = dateListArr.Split(',');
for (var i = 0; i < dateList.Length; i++)
{
if (dateList[i] == dataStr && i <= calcList.Length - 1 && calcList[i] == "true")
{
calc = true;
break;
}
}
}
return calc;
}
private double GetSwapRateByDate(string swapTimeAndRate, DateTime valueDate, int IsSwap, bool IsFloatingProfit = true, DateTime? oldMaturityDate = null)
{
double swapRate = 0;
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(swapTimeAndRate);
var dates = customizedResults.Item1;
if (dates == null)
{
return swapRate;
}
var getSwapRates = customizedResults.Item2;
var latestDate = dates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
//展期情况互换利率获取最后一个日期的互换利率
if (latestDate == null)
{
latestDate = dates.Max();
}
if (latestDate != null)
{
if (getSwapRates != null && getSwapRates.Any())
{
swapRate = getSwapRates[TradeObservationHelper.GetDateIndex(dates, latestDate)];
}
}
return swapRate;
}
}
}