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

291 lines
12 KiB
C#

using System.Text;
using YLErp.BLL;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.MarginModule;
using YLErp.QdpModule;
namespace YLErp.Modules.TradeModule.DealModule
{
public class TradeDelaySettlementService : TradeServiceBase
{
public TradeDelaySettlementService(YLBaseService baseService) : base(baseService)
{
}
public TradeDelaySettlementService(OptUserInfo userInfo) : base(userInfo)
{
}
private const string key = "ExerciseTradeUnderly";
public ExerciseTradeUnderly GetCacheExerciseTradeUnderly()
{
var _reture = DataCacheProvider.GetCache("ExerciseTradeUnderly");
ExerciseTradeUnderly exerciseTradeUnderly = (ExerciseTradeUnderly)_reture;
if (_reture == null)
{
exerciseTradeUnderly = CheckExerciseTradeUnderly();
}
return exerciseTradeUnderly;
}
/// <summary>
/// 检察当日到期交易的标的状态
/// </summary>
/// <param name="valueDate"></param>
public ExerciseTradeUnderly CheckExerciseTradeUnderly()
{
ExerciseTradeUnderly exerciseTradeUnderly = new ExerciseTradeUnderly();
List<DelaySettlement> delays = GetDelaySettlements();
exerciseTradeUnderly.underlystr = "";
exerciseTradeUnderly.datetime = DateTime.Now.ToString("yyyy/MM/dd/ HH:mm:ss");
if (delays.Any())
{
StringBuilder underlyStr = new StringBuilder();
foreach (var item in delays)
{
underlyStr.Append(item.UnderlyCode).Append("(").Append(item.UnderlyState).Append(")").Append(",");
}
exerciseTradeUnderly.underlystr = underlyStr.ToString().Substring(0, underlyStr.Length - 1);
}
DataCacheProvider.SetCache(key, exerciseTradeUnderly, DateTime.Today.AddDays(1));
return exerciseTradeUnderly;
}
/// <summary>
/// 获取异常标的列表
/// </summary>
/// <returns></returns>
public List<DelaySettlement> GetDelaySettlements(DateTime? date = null)
{
var valueDate = date ?? valuedateBLL.ValueDate;
var lastDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(-1));
List<DelaySettlement> delays = new List<DelaySettlement>();
//结构化交易主交易除外(没有主交易概念),组合交易主交易子交易都得考虑延期处理
var query = DbContext.trade.Where(x => (x.TradeType != "结构化交易" || x.IsGroup == 1) && x.ValidState != ConsGlobal.InValid && (x.ExerciseDate >= valueDate || x.SettlementFlag == 1) && ConsTrade.PositionTradeStatusList.Contains(x.TradeStatus));
var arrUnderlyingCode = query.Select(n => n.UnderlyingCode).Distinct().ToArray();
MarginParamProvider marginParam = new MarginParamProvider(OptUser, valueDate);
marginParam.Initialize(arrUnderlyingCode.ToHashSet(), MarginParamTypeEnum.UpDownLimit);
if (arrUnderlyingCode.Any())
{
var eodPriceProvider = new EodPriceProvider(valueDate);
var eodPriceProvidlast = new EodPriceProvider(lastDate);
foreach (var item in arrUnderlyingCode)
{
if (eodPriceProvider.TryGetEodPrice(item, out var eodPrice))
{
DelaySettlement delay = new DelaySettlement();
if (eodPrice.UnderlyingStatus == "停牌")
{
delay.UnderlyState = "停牌";
}
else if (eodPriceProvidlast.TryGetPrice(item, SettlementTypeEnum.SettlePrice, out double price))
{
if (marginParam.TryGetUpdownLimit(item, out var limit, out var isFixed))
{
if (!isFixed)
{
limit *= price;
}
}
else
{
limit = price * 0.05;
}
//注意:price价格可能为负值
limit = Math.Abs(limit);
//涨跌停暂时不使用精确等于处理
if (price + limit <= eodPrice.ClosePrice)
{
delay.UnderlyState = "涨停";
}
else if (price - limit >= eodPrice.ClosePrice)
{
delay.UnderlyState = "跌停";
}
}
else if (eodPrice.HighPrice == eodPrice.LowPrice && eodPrice.HighPrice != null)
{
delay.UnderlyState = "涨跌停";
}
if (!string.IsNullOrWhiteSpace(delay.UnderlyState))
{
delay.UnderlyCode = item;
delays.Add(delay);
}
}
}
}
return delays;
}
/// <summary>
/// 获取需要延期交易的交易编号
/// </summary>
/// <returns></returns>
public string GetDelayTradeNumber(List<int> updownUnderly)
{
var date = valuedateBLL.ValueDate;
var lastDate = QdpCalendarHelper.GetNonHolidayDefore(date.AddDays(-1));
var predicate = PredicateBuilder.Create<trade>(t => t.ExerciseDate >= lastDate
&& t.ExerciseDate <= date
&& t.TradeStatus == ConsTrade.确认成交
&& t.ClientId > 0
&& updownUnderly.Contains(t.UnderlyingId) && t.SettlementFlag == 0 //检查费停牌状态下所有 持仓交易的是否已执行到期
&& t.ValidState != ConsGlobal.InValid);
var tradeNumber = DbContext.trade.Where(predicate).Select(x => x.TradeNumber).ToHashSet();
return "<br />需要延期结算的交易:<br />" + string.Join(",<br/>", tradeNumber);
}
/// <summary>
/// 获取需要延期交易的异常标的id
/// </summary>
/// <returns></returns>
public IEnumerable<int> GetDelayUnderlyIds(DateTime? date = null)
{
var valueDate = date ?? valuedateBLL.ValueDate;
var lastDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(-1));
//结构化交易主交易除外(没有主交易概念),组合交易主交易子交易都得考虑延期处理
var query = DbContext.trade.Where(x => (x.TradeType != "结构化交易" || x.IsGroup == 1) && x.ValidState != ConsGlobal.InValid && x.ExerciseDate == valueDate && ConsTrade.PositionTradeStatusList.Contains(x.TradeStatus) && x.TradeType == "收益互换" && x.SettlementFlag != 1);
var arrUnderlyingCode = query.Select(n => n.UnderlyingCode).Distinct().ToArray();
MarginParamProvider marginParam = new MarginParamProvider(OptUser, valueDate);
marginParam.Initialize(arrUnderlyingCode.ToHashSet(), MarginParamTypeEnum.UpDownLimit);
List<int> ret = new List<int>();
if (arrUnderlyingCode.Any())
{
var eodPriceProvider = new EodPriceProvider(valueDate);
var eodPriceProvidlast = new EodPriceProvider(lastDate);
foreach (var item in arrUnderlyingCode)
{
if (eodPriceProvider.TryGetEodPrice(item, out var eodPrice))
{
if (eodPrice.UnderlyingStatus == "停牌")
{
ret.Add(eodPrice.UnderlyingId);
}
else if (eodPriceProvidlast.TryGetPrice(item, SettlementTypeEnum.SettlePrice, out double price))
{
if (marginParam.TryGetUpdownLimit(item, out var limit, out var isFixed))
{
if (!isFixed)
{
limit *= price;
}
}
else
{
limit = price * 0.05;
}
//注意:price价格可能为负值
limit = Math.Abs(limit);
//涨跌停暂时不使用精确等于处理
if (price + limit <= eodPrice.ClosePrice || price - limit >= eodPrice.ClosePrice)
{
ret.Add(eodPrice.UnderlyingId);
}
}
else if (eodPrice.HighPrice == eodPrice.LowPrice && eodPrice.HighPrice != null)
{
ret.Add(eodPrice.UnderlyingId);
}
}
}
}
return ret;
}
public void ExecuteDelaySettlements(string tradeids, int settlementvalue, out string msg)
{
msg = "";
List<int> ids = new List<int>();
var _ids = tradeids.Split(',').ToList();
foreach (var item in _ids)
{
ids.Add(Convert.ToInt32(item));
}
var Alltrades = DbContext.trade.Where(x => ids.Contains(x.id));
if (Alltrades.Any(x => x.TradeStatus != ConsTrade.确认成交))
{
throw new ServiceException("交易:" + string.Join(".", Alltrades.Where(x => x.TradeStatus != ConsTrade.确认成交).Select(x => x.TradeNumber).ToList()) + ",当前交易状态不符合延期结算要求,无法进行延期结算");
}
var notChange = Alltrades.Where(x => x.SettlementFlag == settlementvalue).Count();
if (Alltrades.Any(x => x.SettlementFlag != settlementvalue))
{
var optType = settlementvalue == 1 ? "手动延期结算" : "延期结算放弃";
var trades = Alltrades.Where(x => x.SettlementFlag != settlementvalue).ToList();
using (var trans = BeginTransaction())
{
foreach (var item in trades)
{
UpdateDelayStatus(item, optType, settlementvalue);
}
DbContext.SaveChanges();
trans.Commit();
}
}
else
{
throw new ServiceException("不存在需要修改延期结算状态的交易");
}
if (notChange > 0)
{
msg = "成功修改" + (Alltrades.Count() - notChange) + "条,不需要修改延期结算状态" + notChange + "条";
}
else
{
msg = "修改延期结算状态成功";
}
}
/// <summary>
/// 修改交易延期状态
/// </summary>
/// <param name="trade"></param>
public void UpdateDelayStatus(trade td, string optType, int SettlementFlag = 1)
{
td.SettlementFlag = SettlementFlag;
td.SettlementFlagDate = DateTime.Now;
td.SettlementFlagOptId = UserId;
td.OptId = UserId;
td.OptName = UserName;
td.OptDate = DateTime.Now;
AddTradeOperationHistoryAndSetParentTradeInfo(true, td, optType);
}
}
public class ExerciseTradeUnderly
{
public string datetime { get; set; }
public string underlystr { get; set; }
}
public class DelaySettlement
{
public string UnderlyCode { get; set; }
public string UnderlyState { get; set; }
}
}