221 lines
8.8 KiB
C#
221 lines
8.8 KiB
C#
using YLErp.DBModels.Consts;
|
|
using YLErp.DBModels.Enums;
|
|
using YLErp.DBModels.Helpers;
|
|
using YLErp.Helpers;
|
|
using YLErp.Modules.DataProviderModule;
|
|
using YLErp.Modules.TradeModule;
|
|
using YLErp.Modules.TradeModule.DealModule;
|
|
using YLErp.QdpModule;
|
|
|
|
namespace YLErp.Modules.EodModule.SettlementModule
|
|
{
|
|
/// <summary>
|
|
/// 日终结算除权除息
|
|
/// </summary>
|
|
public class EodDividenService : EodSettleServiceBase
|
|
{
|
|
public const string Step = "除权除息";
|
|
|
|
readonly DateTime _bodDate;
|
|
|
|
public EodDividenService(EodSettlementContextBase context) : base(context)
|
|
{
|
|
_bodDate = QdpCalendarHelper.GetNonHoliday(SettleDate.AddDays(1));
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// 备份次日初持仓数据
|
|
// 将settleDate未了结的交易,进行除权除息
|
|
// 将场内部分结果保存到bod_trade_position表和trade_position表
|
|
// 将场外部分结果保存到trade和bodTrade表
|
|
// 次日开仓场内持仓数据从bod_trade_position表开始
|
|
// 次日开仓场外交易数据从trade表开始
|
|
//------------------------------------------------------
|
|
|
|
/// <summary>
|
|
/// 场内交易除权除息处理
|
|
/// </summary>
|
|
public void Execute(IEnumerable<EodTradePosition> eodPositionList)
|
|
{
|
|
if (eodPositionList is null || !eodPositionList.Any())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var exchangePositionList = eodPositionList.Where(O => ConsTrade.TradeTypesForHedge.Contains(O.TradeType)|| ConsTrade.BondTypeList.Contains(O.TradeType)).ToList();
|
|
|
|
var bodTradePositions = new DividendService(OptUser).Execute(_context.SettleDate, exchangePositionList);
|
|
|
|
foreach (var item in bodTradePositions)
|
|
{
|
|
item.ValueDate = _bodDate;
|
|
}
|
|
|
|
using (var db = DbContextFactory.GetYLDbContext())
|
|
{
|
|
db.BodTradePosition.AddRange(bodTradePositions);
|
|
|
|
if (_context.IsCurrentDay)
|
|
{
|
|
var tpList = ConvertToTradePosition(bodTradePositions);
|
|
db.TradePosition.AddRange(tpList);
|
|
db.BulkDelete<TradePosition>("1=1");
|
|
}
|
|
|
|
BodTradePosition t;
|
|
db.BulkDelete<BodTradePosition>($"{nameof(t.ValueDate)}='{_bodDate:yyyy-MM-dd}'");
|
|
db.SaveChanges(_context.CancellationToken);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 场外交易除权除息处理
|
|
/// </summary>
|
|
public void Execute(IEnumerable<trade> trades)
|
|
{
|
|
if (trades is null || !trades.Any())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var bodTrades = new DividendService(OptUser).Execute(SettleDate, trades, out var useSaveTrades, out var useSaveUnderlyings);
|
|
|
|
foreach (var item in bodTrades)
|
|
{
|
|
item.ValueDate = _bodDate;
|
|
}
|
|
|
|
bod_trade t;
|
|
|
|
using (var db = DbContextFactory.GetYLDbContext())
|
|
{
|
|
db.bod_Trade.AddRange(bodTrades);
|
|
|
|
//更新underlying数据
|
|
if (useSaveUnderlyings.Any())
|
|
{
|
|
var service = new DbRecordChangesService<UnderlyingChanges>(UserInfo, db);
|
|
List<UnderlyingChanges> ucList = new List<UnderlyingChanges>();
|
|
var ids = useSaveUnderlyings.Select(O => O.id);
|
|
var dbUm = db.underlying_manager.Where(O => ids.Contains(O.id)).ToArray();
|
|
foreach (var item in useSaveUnderlyings)
|
|
{
|
|
var um = dbUm.FirstOrDefault(O => O.id == item.id);
|
|
if (um == null)
|
|
{
|
|
continue;
|
|
}
|
|
var uc = new UnderlyingChanges
|
|
{
|
|
ChangeType = ConsInfoChangeType.Dividend,
|
|
RecordId = um.id,
|
|
FieldName = nameof(underlying_manager.SubData),
|
|
FieldValue = um.SubData ?? "",
|
|
NewValue = item.SubData ?? "",
|
|
OptDate = SettleDate,
|
|
Update = DateTime.Now
|
|
};
|
|
ucList.Add(uc);
|
|
um.SubData = item.SubData;
|
|
}
|
|
service.Save(ucList, false);
|
|
}
|
|
|
|
//更新trade数据
|
|
if (useSaveTrades.Any())
|
|
{
|
|
var ids = useSaveTrades.Select(O => O.id).ToList();
|
|
var tradeList = db.trade.Where(O => ids.Contains(O.id)).ToList();
|
|
new TradeExtendService(UserInfo, db).SetTradeExtend(tradeList, tracking: true);
|
|
foreach (var item in useSaveTrades)
|
|
{
|
|
var td = tradeList.FirstOrDefault(O => O.id == item.id);
|
|
if (td == null || td.DividendDate >= item.DividendDate
|
|
|| td.OriginalNotional >= item.OriginalNotional
|
|
|| Math.Abs((td.OriginalNotional - item.OriginalNotional) ?? 0) < 1e-5)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//var changes = TradeChangeUtil.GetAllChanges(td, item);
|
|
//var changsStr = TradeChangeUtil.SerializeChanges(changes, out var auditFlag);
|
|
TradeHelper2.ReduceTradeExt(td);
|
|
TradeHelper2.ReduceTradeExt(item);
|
|
var changsStr = DataChangeHelper.GetDataChanges(td, item).ToJson();
|
|
|
|
db.TradeAuditLog.Add(new TradeAuditLog
|
|
{
|
|
TradeId = td.id,
|
|
Changes = changsStr,
|
|
DataType = "C01",
|
|
OptId = UserId,
|
|
OptName = UserName,
|
|
OptDate = OptDate,
|
|
OptType = "除权除息",
|
|
AuditFlag = TradeAuditFlag.operation //| auditFlag
|
|
});
|
|
|
|
var changeList = DividendService.GetDividendChanges(td, item);
|
|
new DbRecordChangesService<TradeChanges>(OptUser, db).Save(changeList, false);
|
|
|
|
DividendService.SetDividendTradeData(td, item);
|
|
}
|
|
}
|
|
|
|
if (_context.ClienIds!=null&& _context.ClienIds.Any())
|
|
{
|
|
string strClientWhere=string.Join(",", _context.ClienIds);
|
|
db.BulkDelete<bod_trade>($"{nameof(t.ValueDate)}='{_bodDate:yyyy-MM-dd}' and ClientId in ({strClientWhere})");
|
|
}
|
|
else
|
|
{
|
|
db.BulkDelete<bod_trade>($"{nameof(t.ValueDate)}='{_bodDate:yyyy-MM-dd}'");
|
|
}
|
|
db.SaveChanges(_context.CancellationToken);
|
|
}
|
|
}
|
|
|
|
private IEnumerable<TradePosition> ConvertToTradePosition(IEnumerable<BodTradePosition> positions)
|
|
{
|
|
var tpList = new List<TradePosition>();
|
|
|
|
foreach (var item in positions)
|
|
{
|
|
DateTime maturityDate;
|
|
|
|
if (item.TradeType == "股票")
|
|
{
|
|
maturityDate = DateTime.Today.AddYears(10);
|
|
}
|
|
else if (item.TradeType == "场内期权")
|
|
{
|
|
ExchangeOptionDataProvider.TryGetMaturityDate(item.ExchangeOptionCode, out var date);
|
|
maturityDate = date;
|
|
}
|
|
else if (!UnderlyingDataProvider.TryGetMaturityDate(item.UnderlyingCode, out maturityDate))
|
|
{
|
|
maturityDate = DateTime.Today.AddMonths(1);
|
|
}
|
|
|
|
tpList.Add(new TradePosition
|
|
{
|
|
BookId = item.BookId,
|
|
TradeType = item.TradeType,
|
|
TradeType1 = TradeHelper.GetTradeType1(item.TradeType),
|
|
UnderlyingId = item.UnderlyingId,
|
|
UnderlyingCode = item.UnderlyingCode,
|
|
PositionType = item.PositionType == "long" ? PositionTypeFlag.Long : PositionTypeFlag.Short,
|
|
Position = item.Amount,
|
|
PositionCost = item.Cost,
|
|
MaturityDate = maturityDate,
|
|
InstrumentCode = item.ExchangeOptionCode,
|
|
CreateTime = DateTime.Now,
|
|
UpdateTime = DateTime.Now
|
|
});
|
|
}
|
|
|
|
return tpList;
|
|
}
|
|
}
|
|
}
|