从山证v2.3.0拷贝
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
using System.Linq.Expressions;
|
||||
using YLErp.Model.Enum;
|
||||
|
||||
namespace YLErp.Modules.EodModule.SettlementModule
|
||||
{
|
||||
public class EodQueryPredicateBuilder
|
||||
{
|
||||
readonly DateTime _startDate;
|
||||
readonly EodSettlementRequest _request;
|
||||
|
||||
Expression<Func<trade, bool>> _otcTradePredicate;
|
||||
Expression<Func<ExchangeTrade, bool>> _exchangeTradePredicate;
|
||||
Expression<Func<clientcashincashout_product, bool>> _clientProductPredicate;
|
||||
|
||||
public EodQueryPredicateBuilder(EodSettlementRequest request)
|
||||
{
|
||||
_request = request ?? throw new ArgumentNullException(nameof(request));
|
||||
|
||||
if (_request.SettleDate.Year < 2000)
|
||||
{
|
||||
throw new ArgumentException("无效request");
|
||||
}
|
||||
|
||||
_startDate = request.SettleDate.AddYears(-5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建结算用的衍生品交易筛选条件
|
||||
/// </summary>
|
||||
/// <param name="isGuoJunNeedBesideSwapTrade">国君是否需要互换交易--国君互换持仓计算暂时自己导入 true 需要</param>
|
||||
/// <returns></returns>
|
||||
public Expression<Func<trade, bool>> GetOtcTradePredicate(bool isGuoJunNeedBesideSwapTrade = false)
|
||||
{
|
||||
if (_otcTradePredicate != null && !PS.Config.IsGuoJun)
|
||||
{
|
||||
return _otcTradePredicate;
|
||||
}
|
||||
|
||||
if (!_request.IsSettleOtcTrades)
|
||||
{
|
||||
return _otcTradePredicate = PredicateBuilder.False<trade>();
|
||||
}
|
||||
|
||||
//如果前一天是假日,要显示包含假日的交易
|
||||
var preday = BLL.valuedateBLL.GetNonHolidayDefore(_request.SettleDate.AddDays(-1));
|
||||
|
||||
var predicate = PredicateBuilder.Create<trade>(t =>
|
||||
t.TradeDate > _startDate && t.TradeDate <= _request.SettleDate
|
||||
&& t.ValidState != ConsGlobal.InValid && t.ClientId > 0
|
||||
&& t.TradeType != "结构化交易" && t.TradeType != "收益互换"
|
||||
&& (t.ExerciseDate > preday || t.UnWindDate > preday || _request.SuspensionUnderlyingIds.Contains(t.UnderlyingId) || _request.DelayUnderlyIds.Contains(t.UnderlyingId) || t.SettlementFlag == 1)
|
||||
&& (!ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus) || t.UnWindDate > preday));
|
||||
|
||||
if (PS.Config.IsGuoJun && !isGuoJunNeedBesideSwapTrade)
|
||||
{
|
||||
predicate = PredicateBuilder.Create<trade>(t =>
|
||||
t.TradeDate > _startDate && t.TradeDate <= _request.SettleDate
|
||||
&& t.ValidState != ConsGlobal.InValid && t.ClientId > 0
|
||||
&& t.TradeType != "结构化交易" && t.TradeType != "收益互换"
|
||||
&& (t.ExerciseDate > preday || t.UnWindDate > preday || _request.SuspensionUnderlyingIds.Contains(t.UnderlyingId) || _request.DelayUnderlyIds.Contains(t.UnderlyingId) || t.SettlementFlag == 1)
|
||||
&& (!ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus) || t.UnWindDate > preday));
|
||||
}
|
||||
|
||||
if (_request.ClientIds != null && _request.ClientIds.Any())
|
||||
{
|
||||
predicate = predicate.And(t => _request.ClientIds.Contains(t.ClientId));
|
||||
}
|
||||
|
||||
return _otcTradePredicate = predicate;
|
||||
}
|
||||
public Expression<Func<trade, bool>> GetOtcSwapTradePredicate()
|
||||
{
|
||||
//如果前一天是假日,要显示包含假日的交易
|
||||
var preday = BLL.valuedateBLL.GetNonHolidayDefore(_request.SettleDate.AddDays(-1));
|
||||
|
||||
var predicate = PredicateBuilder.Create<trade>(t =>
|
||||
t.TradeDate > _startDate && t.TradeDate <= _request.SettleDate
|
||||
&& t.ValidState != ConsGlobal.InValid
|
||||
&& t.TradeType == "收益互换"
|
||||
&& (t.ExerciseDate > preday || t.UnWindDate > preday || t.SettlementFlag == 1)
|
||||
&& (!ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus) || t.UnWindDate > preday));
|
||||
|
||||
if (_request.ClientIds != null && _request.ClientIds.Any())
|
||||
{
|
||||
predicate = predicate.And(t => _request.ClientIds.Contains(t.ClientId));
|
||||
}
|
||||
|
||||
return _otcTradePredicate = predicate;
|
||||
}
|
||||
/// <summary>
|
||||
/// 构建结算用的场内交易筛选条件
|
||||
/// </summary>
|
||||
public Expression<Func<ExchangeTrade, bool>> GetExchangeTradePredicate()
|
||||
{
|
||||
if (_exchangeTradePredicate != null)
|
||||
{
|
||||
return _exchangeTradePredicate;
|
||||
}
|
||||
|
||||
if (!_request.IsSettleExchangeTrades)
|
||||
{
|
||||
return _exchangeTradePredicate = PredicateBuilder.False<ExchangeTrade>();
|
||||
}
|
||||
|
||||
var predicate = PredicateBuilder.Create<ExchangeTrade>(t => t.TradeDate == _request.SettleDate && t.IsValid);
|
||||
|
||||
return _exchangeTradePredicate = predicate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户抵押品查询
|
||||
/// </summary>
|
||||
public Expression<Func<clientcashincashout_product, bool>> GetClientProductPredicate()
|
||||
{
|
||||
if (_clientProductPredicate != null)
|
||||
{
|
||||
return _clientProductPredicate;
|
||||
}
|
||||
|
||||
if (!_request.IsSettleOtcTrades)
|
||||
{
|
||||
return _clientProductPredicate = PredicateBuilder.False<clientcashincashout_product>();
|
||||
}
|
||||
|
||||
var settleDateEnd = _request.SettleDate.AddDays(1);
|
||||
var predicate = PredicateBuilder.Create<clientcashincashout_product>(t => t.HappenDate < settleDateEnd
|
||||
&& (t.Status == Clientcashincashout_productStatusEnum.抵押.ToString() && t.OptStatus == ClientCashInCashOut.已确认
|
||||
|| t.Status == Clientcashincashout_productStatusEnum.赎回.ToString() && (t.OptStatus != ClientCashInCashOut.已确认 || t.BackDate >= settleDateEnd)));
|
||||
|
||||
if (_request.ClientIds != null && _request.ClientIds.Any())
|
||||
{
|
||||
predicate = predicate.And(t => t.ClientId != 0 && _request.ClientIds.Contains(t.ClientId));
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
using System.Linq.Expressions;
|
||||
using YLErp.BLL;
|
||||
using YLErp.Modules.DataProviderModule;
|
||||
using YLErp.Modules.TradeModule;
|
||||
using YLErp.Modules.TradeModule.ForwardModule;
|
||||
|
||||
namespace YLErp.Modules.EodModule.SettlementModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于结算的数据查询服务
|
||||
/// </summary>
|
||||
public class EodSettleDataQueryService : YLBaseService
|
||||
{
|
||||
public EodSettleDataQueryService(OptUserInfo optUser) : base(optUser)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EodSettleDataQueryService(YLBaseService baseService) : base(baseService)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取要结算的交易数据
|
||||
/// </summary>
|
||||
/// <param name="settleDate">结算日期</param>
|
||||
/// <param name="tradeDataPredicate">交易数据查询过滤条件</param>
|
||||
/// <param name="tradecashProvider">交易资金提供接口</param>
|
||||
/// <param name="preSettleDate">上个结算日(多交易日历场景下的假日到期交易处理时使用)</param>
|
||||
public List<trade> GetOtcTrades(DateTime settleDate, Expression<Func<trade, bool>> tradeDataPredicate
|
||||
, out TradeCashDataProvider tradecashProvider, DateTime preSettleDate = default)
|
||||
{
|
||||
if (tradeDataPredicate is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tradeDataPredicate));
|
||||
}
|
||||
|
||||
var tradeList = new List<trade>(1000);
|
||||
|
||||
//------------------------------------------------------
|
||||
// eod trades
|
||||
//------------------------------------------------------
|
||||
|
||||
var etQuery = from et in DbContext.eod_trade
|
||||
join t in DbContext.trade.Where(tradeDataPredicate) on et.TradeId equals t.id
|
||||
where et.ValueDate == settleDate
|
||||
select new
|
||||
{
|
||||
t.id,
|
||||
et.TradeId,
|
||||
et.TradeJson,
|
||||
t.BuySell,
|
||||
t.AssetId,
|
||||
t.ExerciseDate,
|
||||
t.DividendRate,
|
||||
t.TradeType
|
||||
};
|
||||
|
||||
var etList = etQuery.ToArray();
|
||||
List<TradeMeta> structProductTradeMetaList = null;
|
||||
if (etList != null && etList.Length > 0)
|
||||
{
|
||||
var structProductTradeIds = etList.Where(p => "结构化产品".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
|
||||
if (structProductTradeIds != null && structProductTradeIds.Count > 0)
|
||||
{
|
||||
structProductTradeMetaList = DbContext.TradeMeta.AsNoTracking().Where(d => structProductTradeIds.Contains(d.TradeId)).ToList();
|
||||
}
|
||||
}
|
||||
if (structProductTradeMetaList == null)
|
||||
{
|
||||
structProductTradeMetaList = new List<TradeMeta>();
|
||||
}
|
||||
|
||||
|
||||
foreach (var item in etList)
|
||||
{
|
||||
try
|
||||
{
|
||||
var t = TradeHelper2.Deserialize(item.TradeJson);
|
||||
t.id = item.TradeId;
|
||||
t.BuySell = item.BuySell;
|
||||
t.AssetId = item.AssetId;
|
||||
if (t.ExerciseDate != item.ExerciseDate && !DbContext.ExtensionTime.Any(x => x.TradeId == t.id && x.IsValid && x.OldMaturityDate == t.ExerciseDate && x.NewMaturityDate == item.ExerciseDate && x.OptDate >= settleDate))
|
||||
{
|
||||
t.ExerciseDate = item.ExerciseDate;
|
||||
}
|
||||
t.MetaDic["from_eod_trade"] = "true";
|
||||
tradeList.Add(t);
|
||||
//先简单处理一下避免某些情况下删除eodtrade表数据
|
||||
//比如手动在数据库改了观察频率回到历史收盘(手动改是因为回到历史收盘太慢了而且涉及到除权除息的各种问题)
|
||||
if (t.TradeType == "雪球期权")
|
||||
{
|
||||
var snowball = DbContext.trade_snowball.Where(n => n.TradeId == item.id).Select(n => new
|
||||
{
|
||||
n.KOObservationDates,
|
||||
n.ObservationDates,
|
||||
n.KOObservationSettleDates
|
||||
}).FirstOrDefault();
|
||||
|
||||
if (snowball != null && t.trade_snowball != null)
|
||||
{
|
||||
t.trade_snowball.ObservationDates = snowball.ObservationDates;
|
||||
t.trade_snowball.KOObservationDates = snowball.KOObservationDates;
|
||||
t.trade_snowball.KOObservationSettleDates = snowball.KOObservationSettleDates;
|
||||
}
|
||||
}
|
||||
else if (t.TradeType == "凤凰期权")
|
||||
{
|
||||
var autocall = DbContext.trade_autocall.Where(n => n.TradeId == item.id).Select(n => new
|
||||
{
|
||||
n.ObservationDates,
|
||||
n.KOObservationDates
|
||||
}).FirstOrDefault();
|
||||
if (autocall != null && t.trade_autocall != null)
|
||||
{
|
||||
t.trade_autocall.ObservationDates = autocall.ObservationDates;
|
||||
t.trade_autocall.KOObservationDates = autocall.KOObservationDates;
|
||||
}
|
||||
}
|
||||
else if (t.TradeType == "累计期权")
|
||||
{
|
||||
t.MetaDic.Remove("from_eod_trade");
|
||||
new OptionTradeActionRestoreService(this).RestoreTradeDataToSpecialDay(t, settleDate);
|
||||
}
|
||||
else if (t.TradeType == "远期")
|
||||
{
|
||||
var forwardTrade = DbContext.trade_forward.Where(n => n.TradeId == item.id).Select(n => new
|
||||
{
|
||||
n.ForwardValue,
|
||||
n.OpenCommission
|
||||
}).FirstOrDefault();
|
||||
}
|
||||
else if (t.TradeType == "结构化产品")
|
||||
{
|
||||
var tradeMetas = structProductTradeMetaList.Where(d => d.TradeId == t.id).ToDictionary(g => g.MetaKey, g => g.MetaValue);
|
||||
if (tradeMetas != null && tradeMetas.Count > 0)
|
||||
{
|
||||
foreach (var d in tradeMetas)
|
||||
{
|
||||
if (!t.MetaDic.ContainsKey(d.Key))
|
||||
{
|
||||
t.MetaDic.Add(d.Key, d.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t.TradeType == "亚式期权")
|
||||
{
|
||||
if (t.trade_asian_option.PayoffType == "EnhancedArithmeticAverage" && t.trade_asian_option.EnhancedPrice == 0 && t.TradeDate < new DateTime(2023, 2, 19) && t.Strike.HasValue)
|
||||
{
|
||||
t.trade_asian_option.EnhancedPrice = t.Strike.Value;
|
||||
}
|
||||
}
|
||||
|
||||
//解决收盘时从hisdata取了null并且存入了eodtrade的情况下数据问题
|
||||
if (t.DividendRate == null)
|
||||
{
|
||||
t.DividendRate = item.DividendRate;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFactory.GetLogger("eod_trade.TradeJson解析").Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// 多交易日历场景下的假日到期交易处理
|
||||
//------------------------------------------------------
|
||||
if (PS.Config.ErpElement.SupportMultiCalendar)
|
||||
{
|
||||
var pretQuery = from et in DbContext.eod_trade
|
||||
join t in DbContext.trade on et.TradeId equals t.id
|
||||
where et.ValueDate == preSettleDate
|
||||
&& !DbContext.trade.Where(tradeDataPredicate).Any(n => n.id == et.TradeId)
|
||||
select new
|
||||
{
|
||||
et.TradeId,
|
||||
et.TradeJson,
|
||||
t.BuySell,
|
||||
t.UnderlyingCode
|
||||
};
|
||||
|
||||
var pretList = pretQuery.ToArray();
|
||||
|
||||
if (pretList.Any())
|
||||
{
|
||||
var exHolidaySet = DataCacheProvider.GetMarketDataSource().AsQueryable()
|
||||
.Where(n => !string.IsNullOrEmpty(n.ExchangeNo) && QdpModule.QdpCalendarHelper.IsHoliday(preSettleDate, n.CalendarName.TrimToNull() ?? ConsGlobal.DefaultCalendar))
|
||||
.Select(n => n.ExchangeNo.ToUpperInvariant()).ToHashSet();
|
||||
|
||||
foreach (var item in pretList)
|
||||
{
|
||||
if (!tradeList.Any(x => x.id == item.TradeId))
|
||||
{
|
||||
var un = DataCacheProvider.GetUnderlyingDataSource().GetData(item.UnderlyingCode);
|
||||
|
||||
if (!string.IsNullOrEmpty(un.MarketCode) && exHolidaySet.Contains(un.MarketCode))
|
||||
{
|
||||
try
|
||||
{
|
||||
var t = TradeHelper2.Deserialize(item.TradeJson);
|
||||
t.id = item.TradeId;
|
||||
t.BuySell = item.BuySell;
|
||||
t.MetaDic["from_eod_trade"] = "true";
|
||||
tradeList.Add(t);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFactory.GetLogger("eod_trade.TradeJson解析").Error(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// 没有出现在eodtrae表中的交易数据
|
||||
//------------------------------------------------------
|
||||
|
||||
var eodTradeIds = tradeList.Select(n => n.id);
|
||||
|
||||
tradeDataPredicate = tradeDataPredicate.And(t => !eodTradeIds.Contains(t.id));
|
||||
|
||||
var trades = DbContext.trade.AsNoTracking().Where(tradeDataPredicate).ToArray();
|
||||
|
||||
//------------------------------------------------------
|
||||
// 交易资金接口
|
||||
//------------------------------------------------------
|
||||
|
||||
var tradeIds = trades.Select(x => x.id).ToList();
|
||||
|
||||
tradecashProvider = new TradeCashDataProvider().Initialize(eodTradeIds.Concat(tradeIds).ToArray());
|
||||
var tradecashPreProvider = new TradeCashPreDataProvider().Initialize(eodTradeIds.Concat(tradeIds).ToArray());
|
||||
|
||||
//------------------------------------------------------
|
||||
// 交易数据结果集
|
||||
//------------------------------------------------------
|
||||
|
||||
if (!trades.Any())
|
||||
{
|
||||
return tradeList;
|
||||
}
|
||||
|
||||
tradeList.AddRange(trades);
|
||||
structProductTradeMetaList = null;
|
||||
if (trades != null && trades.Length > 0)
|
||||
{
|
||||
var structProductTradeIds = trades.Where(p => "结构化产品".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
|
||||
if (structProductTradeIds != null && structProductTradeIds.Count > 0)
|
||||
{
|
||||
structProductTradeMetaList = DbContext.TradeMeta.AsNoTracking().Where(d => structProductTradeIds.Contains(d.TradeId)).ToList();
|
||||
}
|
||||
}
|
||||
if (structProductTradeMetaList == null)
|
||||
{
|
||||
structProductTradeMetaList = new List<TradeMeta>();
|
||||
}
|
||||
foreach (var t in trades)
|
||||
{
|
||||
if (t.TradeType == "累计期权")
|
||||
{
|
||||
new OptionTradeActionRestoreService(this).RestoreTradeDataToSpecialDay(t, settleDate);
|
||||
}
|
||||
if (t.TradeType == "结构化产品")
|
||||
{
|
||||
var tradeMetas = structProductTradeMetaList.Where(d => d.TradeId == t.id).ToDictionary(g => g.MetaKey, g => g.MetaValue);
|
||||
if (tradeMetas != null && tradeMetas.Count > 0)
|
||||
{
|
||||
foreach (var d in tradeMetas)
|
||||
{
|
||||
if (!t.MetaDic.ContainsKey(d.Key))
|
||||
{
|
||||
t.MetaDic.Add(d.Key, d.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ProcessTrade(settleDate, tradecashProvider, tradecashPreProvider, t);
|
||||
}
|
||||
|
||||
return tradeList;
|
||||
}
|
||||
|
||||
|
||||
public static void ProcessTrade(DateTime settleDate, TradeCashDataProvider tradecashProvider, TradeCashPreDataProvider tradecashPreProvider, trade t)
|
||||
{
|
||||
//存在收盘之后的了结记录,代表收盘日那天,交易为确认成交状态
|
||||
var tradeCashs = tradecashProvider.GetTradeCashes(t.id).Where(x => x.ValidState != "InValid" && !x.IsDeleted && x.Action != "系统操作-期权费" && (x.HappenedDate > settleDate || x.ValueDate > settleDate && x.HappenedDate == null));
|
||||
t.TradeStatus = tradeCashs.Any() ? ConsTrade.确认成交 : t.TradeStatus;
|
||||
|
||||
//收历史盘时,找到收盘日之前最近一次的了结日期
|
||||
var lastSecondTradeCash = tradecashProvider.GetTradeCashes(t.id).Where(x => x.ValidState != "InValid" && !x.IsDeleted && x.Action != "系统操作-期权费" && (x.HappenedDate <= settleDate || x.ValueDate <= settleDate && x.HappenedDate == null)).OrderByDescending(y => y.id).FirstOrDefault();
|
||||
t.UnWindDate = lastSecondTradeCash?.HappenedDate ?? lastSecondTradeCash?.ValueDate;
|
||||
|
||||
if (ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus))
|
||||
{
|
||||
t.Notional = 0;
|
||||
t.TradeAmount = 0;
|
||||
t.StockEqvNotional = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var tc = tradeCashs.Where(x => x.Notional != 0).FirstOrDefault();
|
||||
if (tc != null)
|
||||
{
|
||||
t.Notional = tc.Notional;
|
||||
}
|
||||
else
|
||||
{
|
||||
//取第一个ValueDate大于settleDate的TradeCash数据(TradeCashPreDataProvider类中ValueDate已做正序处理)
|
||||
var tcPrePredicate = new Func<trade_cash_pre, bool>(x => x.Action != "系统操作-期权费" && x.Notional != 0
|
||||
&& x.ValueDate > settleDate && (x.HappenedDate > settleDate || x.HappenedDate == null));
|
||||
var tcPre = tradecashPreProvider.GetTradeCashPres(t.id).FirstOrDefault(tcPrePredicate);
|
||||
if (tcPre != null)
|
||||
{
|
||||
t.Notional = tcPre.Notional;
|
||||
}
|
||||
}
|
||||
|
||||
if (t.TradeType == ConsGlobal.TradeType.CashFlow)
|
||||
{
|
||||
t.TradeAmount = 0;
|
||||
t.StockEqvNotional = t.Notional;
|
||||
}
|
||||
else
|
||||
{
|
||||
var CountRatio = (DataCacheProvider.GetUnderlyingDataSource().GetData(t.UnderlyingId)?.CountRatio) ?? 1;
|
||||
t.TradeAmount = t.Notional / CountRatio;
|
||||
t.StockEqvNotional = t.OriginalNotional == 0 ? 0 : (t.Notional / t.OriginalNotional * t.OriginalStockEqvNotional) ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
tradeBLL.SetFieldsByTradeType(t, settleDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace YLErp.Modules.EodModule.SettlementModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 结算服务基类
|
||||
/// </summary>
|
||||
public abstract class EodSettleServiceBase : YLBaseService
|
||||
{
|
||||
protected readonly EodSettlementContextBase _context;
|
||||
|
||||
public EodSettleServiceBase(EodSettlementContextBase context)
|
||||
: base(context.UserInfo)
|
||||
{
|
||||
_context = context ?? throw new ArgumentNullException(nameof(context));
|
||||
|
||||
ResetDbContext();
|
||||
}
|
||||
|
||||
public DateTime SettleDate => _context.SettleDate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
using YLErp.Abstract.DataProviders;
|
||||
using YLErp.Modules.DataProviderModule;
|
||||
|
||||
namespace YLErp.Modules.EodModule.SettlementModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 这是一个多线程运行环境下的收盘上下文类
|
||||
/// </summary>
|
||||
public abstract class EodSettlementContextBase
|
||||
{
|
||||
EodPriceProvider _eodPriceProvider;
|
||||
EodPriceProvider _preEodPriceProvider;
|
||||
ExchangeStatus _exchangeStatus;
|
||||
|
||||
protected EodSettlementContextBase(EodSettlementRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
Request = request ?? throw new ArgumentNullException(nameof(request));
|
||||
|
||||
CancellationToken = cancellationToken;
|
||||
|
||||
if (request.SettleDate.Year < 2000)
|
||||
{
|
||||
throw new ArgumentException("request参数错误:SettleDate");
|
||||
}
|
||||
|
||||
if (!request.IsSettleOtcTrades && !request.IsSettleExchangeTrades)
|
||||
{
|
||||
throw new ArgumentException("request参数错误");
|
||||
}
|
||||
|
||||
StartDate = request.SettleDate.AddYears(-3);
|
||||
|
||||
PreSettleDate = BLL.valuedateBLL.GetNonHolidayDefore(SettleDate.AddDays(-1));
|
||||
|
||||
SystemValue = BLL.valuedateBLL.SystemDate;
|
||||
|
||||
PredicateBuilder = new EodQueryPredicateBuilder(request);
|
||||
}
|
||||
|
||||
public ExchangeStatus ExchangeStatus => _exchangeStatus ?? (_exchangeStatus = new ExchangeStatus(SettleDate, PreSettleDate));
|
||||
|
||||
/// <summary>
|
||||
/// 任务终止令牌
|
||||
/// </summary>
|
||||
public CancellationToken CancellationToken { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 结算请求参数
|
||||
/// </summary>
|
||||
public EodSettlementRequest Request { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求用户信息
|
||||
/// </summary>
|
||||
public OptUserInfo UserInfo => Request.UserInfo;
|
||||
|
||||
/// <summary>
|
||||
/// 结算日
|
||||
/// </summary>
|
||||
public DateTime SettleDate => Request.SettleDate;
|
||||
|
||||
/// <summary>
|
||||
/// 需要收盘得客户
|
||||
/// </summary>
|
||||
public IEnumerable<int> ClienIds => Request.ClientIds;
|
||||
/// <summary>
|
||||
/// 结算日
|
||||
/// </summary>
|
||||
public string SettleDateStr => Request.SettleDate.ToString(ConsGlobal.DateFormat);
|
||||
|
||||
/// <summary>
|
||||
/// 获取上个结算日(结算第一步就需要检查这个日期是否等于日历数据中的前一工作日)
|
||||
/// </summary>
|
||||
public DateTime PreSettleDate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取上个结算日(结算第一步就需要检查这个日期是否等于日历数据中的前一工作日)
|
||||
/// </summary>
|
||||
public string PreSettleDateStr => PreSettleDate.ToString(ConsGlobal.DateFormat);
|
||||
|
||||
/// <summary>
|
||||
/// 交易起始关注日
|
||||
/// </summary>
|
||||
public DateTime StartDate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 系统参数
|
||||
/// </summary>
|
||||
public valuedate SystemValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 查询条件构造器
|
||||
/// </summary>
|
||||
public EodQueryPredicateBuilder PredicateBuilder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否当前交易日
|
||||
/// </summary>
|
||||
public bool IsCurrentDay => SettleDate == SystemValue.ValueDate;
|
||||
|
||||
/// <summary>
|
||||
/// 获取日终价格提供对象
|
||||
/// </summary>
|
||||
public EodPriceProvider GetEodPriceProvider()
|
||||
{
|
||||
if (_eodPriceProvider == null)
|
||||
{
|
||||
_eodPriceProvider = new EodPriceProvider(SettleDate, isDiviendPrice: false);
|
||||
if (!Request.IsPartialSettlement)
|
||||
{
|
||||
_eodPriceProvider.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
return _eodPriceProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收盘日上一交易日日终价格提供
|
||||
/// </summary>
|
||||
public EodPriceProvider GetPreEodPriceProvider()
|
||||
{
|
||||
if (_preEodPriceProvider == null)
|
||||
{
|
||||
_preEodPriceProvider = new EodPriceProvider(PreSettleDate);
|
||||
_preEodPriceProvider.SetPreValueDate(PreSettleDate);
|
||||
if (!Request.IsPartialSettlement)
|
||||
{
|
||||
_preEodPriceProvider.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
return _preEodPriceProvider;
|
||||
}
|
||||
|
||||
#region----运行信息处理----
|
||||
|
||||
/// <summary>
|
||||
/// 记录日志
|
||||
/// </summary>
|
||||
public void LogInfo(string message)
|
||||
{
|
||||
LogFactory.GetLogger("日终结算").Info(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录日志
|
||||
/// </summary>
|
||||
public void LogError(string message, Exception ex = null)
|
||||
{
|
||||
LogFactory.GetLogger("日终结算").Error(message, ex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激发错误异常
|
||||
/// </summary>
|
||||
public void RaiseError(string action, string error, Exception ex = null)
|
||||
{
|
||||
if (error == null)
|
||||
{
|
||||
error = "发生错误";
|
||||
}
|
||||
|
||||
throw new EodSettleException($"[{action}]{error}", ex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查结算任务是否被取消
|
||||
/// </summary>
|
||||
public void CheckCanceled()
|
||||
{
|
||||
CancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return SettleDateStr;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日终结算错误
|
||||
/// </summary>
|
||||
public class EodSettleException : Exception
|
||||
{
|
||||
public EodSettleException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 交易所状态
|
||||
/// </summary>
|
||||
public class ExchangeStatus
|
||||
{
|
||||
readonly DateTime _preDate;
|
||||
readonly Dictionary<string, (bool isholidy, DateTime exPreDate)> _dic;
|
||||
|
||||
public ExchangeStatus(DateTime valueDate, DateTime preDate)
|
||||
{
|
||||
_preDate = preDate;
|
||||
_dic = new Dictionary<string, (bool, DateTime)>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var m in DataCacheProvider.GetMarketDataSource().AsQueryable())
|
||||
{
|
||||
if (!string.IsNullOrEmpty(m.ExchangeNo))
|
||||
{
|
||||
var calendar = m.CalendarName.TrimToNull() ?? ConsGlobal.DefaultCalendar;
|
||||
var isholidy = QdpModule.QdpCalendarHelper.IsHoliday(valueDate, calendar);
|
||||
var exPreDate = QdpModule.QdpCalendarHelper.GetNonHolidayDefore(_preDate, calendar);
|
||||
|
||||
_dic[m.ExchangeNo] = (isholidy, exPreDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 交易所是否节假日
|
||||
/// </summary>
|
||||
public bool IsHoliday(string exchangeNo)
|
||||
{
|
||||
return !string.IsNullOrEmpty(exchangeNo) && _dic.TryGetValue(exchangeNo, out var state) && state.isholidy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 交易所的上一个交易日
|
||||
/// </summary>
|
||||
public DateTime GetPreDate(string exchangeNo)
|
||||
{
|
||||
return !string.IsNullOrEmpty(exchangeNo) && _dic.TryGetValue(exchangeNo, out var state) ? state.exPreDate : _preDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
namespace YLErp.Modules.EodModule.SettlementModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 日终结算请求
|
||||
/// </summary>
|
||||
public class EodSettlementRequest
|
||||
{
|
||||
bool _readonly;
|
||||
|
||||
private DateTime _settleDate;
|
||||
protected string _volType;
|
||||
protected bool _useClosePrice;
|
||||
|
||||
private IEnumerable<int> _clientId;
|
||||
|
||||
private bool _isSettleOtcTrades = true;
|
||||
private bool _isSettleExchangeTrades = true;
|
||||
|
||||
public EodSettlementRequest(OptUserInfo userInfo)
|
||||
{
|
||||
UserInfo = userInfo ?? throw new ArgumentNullException(nameof(userInfo));
|
||||
SuspensionUnderlyingIds = EodDataHelper.GetSuspensionUnderlyingIds();
|
||||
}
|
||||
|
||||
#region----属性只读----
|
||||
|
||||
public bool Readonly => _readonly;
|
||||
|
||||
private void CheckReadonly()
|
||||
{
|
||||
if (_readonly)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public EodSettlementRequest AsReadonly()
|
||||
{
|
||||
_readonly = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public OptUserInfo UserInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 结算日期
|
||||
/// </summary>
|
||||
public DateTime SettleDate
|
||||
{
|
||||
get => _settleDate;
|
||||
set
|
||||
{
|
||||
CheckReadonly();
|
||||
_settleDate = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 结算用的波动率类型
|
||||
/// </summary>
|
||||
public string VolType
|
||||
{
|
||||
get => _volType;
|
||||
set
|
||||
{
|
||||
CheckReadonly();
|
||||
_volType = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用收盘价结算
|
||||
/// </summary>
|
||||
public bool UseClosePrice
|
||||
{
|
||||
get => _useClosePrice;
|
||||
set
|
||||
{
|
||||
CheckReadonly();
|
||||
_useClosePrice = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否结算衍生品交易(默认true)
|
||||
/// </summary>
|
||||
public bool IsSettleOtcTrades
|
||||
{
|
||||
get => _isSettleOtcTrades;
|
||||
set
|
||||
{
|
||||
CheckReadonly();
|
||||
_isSettleOtcTrades = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 只结算所给客户ID的交易
|
||||
/// 注意:只用于衍生品交易结算时
|
||||
/// </summary>
|
||||
public IEnumerable<int> ClientIds
|
||||
{
|
||||
get => _clientId;
|
||||
set
|
||||
{
|
||||
CheckReadonly();
|
||||
_clientId = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否结算场内交易(默认true)
|
||||
/// </summary>
|
||||
public bool IsSettleExchangeTrades
|
||||
{
|
||||
get => _isSettleExchangeTrades;
|
||||
set
|
||||
{
|
||||
CheckReadonly();
|
||||
_isSettleExchangeTrades = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停牌标的ID集合
|
||||
/// </summary>
|
||||
public IEnumerable<int> SuspensionUnderlyingIds { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 涨跌停标的集合
|
||||
/// </summary>
|
||||
public IEnumerable<int> DelayUnderlyIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否部分结算
|
||||
/// </summary>
|
||||
public bool IsPartialSettlement
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ClientIds!=null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return !(IsSettleOtcTrades && IsSettleExchangeTrades);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否延期交易
|
||||
/// </summary>
|
||||
public bool IsDelayTrade { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 克隆对象(克隆后非只读)
|
||||
/// </summary>
|
||||
public EodSettlementRequest Clone(bool asReadonly = false)
|
||||
{
|
||||
var clone = (EodSettlementRequest)MemberwiseClone();
|
||||
clone._readonly = asReadonly;
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回收盘价或结算价
|
||||
/// </summary>
|
||||
public string GetPriceType()
|
||||
{
|
||||
return UseClosePrice ? ConsGlobal.SettlePriceMode.收盘价 : ConsGlobal.SettlePriceMode.结算价;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var priceType = UseClosePrice ? "收盘价" : "结算价";
|
||||
|
||||
return $"{SettleDate:yyyy-MM-dd},{VolType},{priceType}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
using YLErp.DBModels.Consts;
|
||||
using YLErp.Modules.VolatilityModule;
|
||||
using YLErp.QdpModule;
|
||||
|
||||
namespace YLErp.Modules.EodModule.SettlementModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 结算波动率接口(暂未考虑多标的处理)
|
||||
/// </summary>
|
||||
public interface IEodVolProvider
|
||||
{
|
||||
double? GetVol(OtcTradeBase td, double spotPrice);
|
||||
}
|
||||
|
||||
#region----持仓波动率----
|
||||
|
||||
/// <summary>
|
||||
/// TradeVol模式持仓波动率提供
|
||||
/// </summary>
|
||||
class EodPositionVolProvider_Trade : TradeVolitalityProvider, IEodVolProvider
|
||||
{
|
||||
Dictionary<int, double> _overridVolDic;
|
||||
|
||||
public EodPositionVolProvider_Trade(DateTime valueDate) : base(valueDate)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public double? GetVol(OtcTradeBase td, double spotPrice)
|
||||
{
|
||||
if (td is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(td));
|
||||
}
|
||||
|
||||
if (td.id < 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_overridVolDic == null)
|
||||
{
|
||||
using (var db = DbContextFactory.GetYLDbContext())
|
||||
{
|
||||
_overridVolDic = db.eod_trade_vol_override.Where(x => x.valuedate == _valueDate)
|
||||
.Select(n => new { n.tradeid, n.vol }).ToDictionary(n => n.tradeid, m => m.vol);
|
||||
}
|
||||
}
|
||||
|
||||
if (_overridVolDic.TryGetValue(td.id, out var vol))
|
||||
{
|
||||
return vol;
|
||||
}
|
||||
|
||||
if (TryGetVol(td.id, td.ExerciseDate.Value, out vol))
|
||||
{
|
||||
return vol;
|
||||
}
|
||||
|
||||
return VolatilityHelper.GetTradeVol(_valueDate, td.TradeDate.Value, td.ExerciseDate.Value,
|
||||
td.TradeOpenVolatility ?? 0, td.TradeCloseVolatility ?? 0, td.NumOfSmoothingDays ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region----曲面波动率----
|
||||
|
||||
/// <summary>
|
||||
/// 曲面波动率模式持仓波动率提供
|
||||
/// </summary>
|
||||
class EodUnderlyingVolProvider : UnderlyingVolitalityProvider
|
||||
{
|
||||
protected EodUnderlyingVolProvider(DateTime valueDate, IEnumerable<string> volTypes) : base(valueDate, volTypes)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected double? InnerGetVol(OtcTradeBase td, string volType, double spotPrice)
|
||||
{
|
||||
if (td is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(td));
|
||||
}
|
||||
|
||||
var userGroup = string.Empty;
|
||||
|
||||
if (ConsUserGroup.HasGroup)
|
||||
{
|
||||
userGroup = DataCacheProvider.GetAssetUnitDataSource().GetData(td.AssetId)?.UserGroup;
|
||||
|
||||
if (string.IsNullOrEmpty(userGroup))
|
||||
{
|
||||
throw new Exception($"[结算交易'{td.TradeNumber}'][取{volType}波动率]未能获取用户组!");
|
||||
}
|
||||
}
|
||||
|
||||
var unVol = GetVol(volType, userGroup, td.UnderlyingCode);
|
||||
|
||||
if (unVol == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var constVol = VolatilityHelper.GetInterpolatedVol(
|
||||
volConstructionType: PS.Config.ErpElement.SkewMapVolConstruction ? VolConstructionType.SkewMap : VolConstructionType.Normal,
|
||||
volSurface: unVol,
|
||||
valueDate: _valueDate,
|
||||
underlyingCode: td.UnderlyingCode,
|
||||
exerciseDate: td.ExerciseDate.Value,
|
||||
strike: td.Strike ?? 0,
|
||||
isBuy: td.BuySell == "买入",
|
||||
isCall: td.CallPut == "Call",
|
||||
spotPrice: spotPrice,
|
||||
isMoneynessOption: td.IsMoneynessOption == "是",
|
||||
isEodCalc: true);
|
||||
|
||||
return constVol;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单个曲面波动率类型
|
||||
/// </summary>
|
||||
class EodUnderlyingSingleVolProvider : EodUnderlyingVolProvider, IEodVolProvider
|
||||
{
|
||||
readonly string _volType;
|
||||
|
||||
public EodUnderlyingSingleVolProvider(DateTime valueDate, string volType)
|
||||
: base(valueDate, new[] { volType })
|
||||
{
|
||||
_volType = volType ?? throw new ArgumentNullException(nameof(volType));
|
||||
}
|
||||
|
||||
public double? GetVol(OtcTradeBase td, double spotPrice)
|
||||
{
|
||||
return InnerGetVol(td, _volType, spotPrice);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 曲面波动率模式持仓波动率提供
|
||||
/// </summary>
|
||||
class EodPositionVolProvider_Underlying : EodUnderlyingVolProvider, IEodVolProvider
|
||||
{
|
||||
readonly string _volType;
|
||||
|
||||
Dictionary<int, double> _overridVolDic;
|
||||
|
||||
public EodPositionVolProvider_Underlying(DateTime valueDate, string volType)
|
||||
: base(valueDate, new[] { volType })
|
||||
{
|
||||
_volType = volType ?? throw new ArgumentNullException(nameof(volType));
|
||||
}
|
||||
|
||||
public double? GetVol(OtcTradeBase td, double spotPrice)
|
||||
{
|
||||
if (_overridVolDic == null)
|
||||
{
|
||||
using (var db = DbContextFactory.GetYLDbContext())
|
||||
{
|
||||
_overridVolDic = db.eod_trade_vol_override.Where(x => x.valuedate == _valueDate)
|
||||
.Select(n => new { n.tradeid, n.vol }).ToDictionary(n => n.tradeid, m => m.vol);
|
||||
}
|
||||
}
|
||||
|
||||
if (_overridVolDic.TryGetValue(td.id, out var vol))
|
||||
{
|
||||
return vol;
|
||||
}
|
||||
|
||||
return InnerGetVol(td, _volType, spotPrice);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region----对冲波动率----
|
||||
|
||||
/// <summary>
|
||||
/// 对冲波动率提供
|
||||
/// </summary>
|
||||
class EodHedgeVolProvider : TradeHedgeVolProvider, IEodVolProvider
|
||||
{
|
||||
public EodHedgeVolProvider(DateTime valueDate) : base(valueDate)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public double? GetVol(OtcTradeBase td, double spotPrice)
|
||||
{
|
||||
if (td is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(td));
|
||||
}
|
||||
|
||||
if (TryGetVol(td.id, out var vol))
|
||||
{
|
||||
return vol;
|
||||
}
|
||||
|
||||
return td.TradeSavedVol ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开仓波动率提供(开仓波动率只在TradeVol模式下结算)
|
||||
/// </summary>
|
||||
class EodOpenVolProvider : TradeHedgeVolProvider, IEodVolProvider
|
||||
{
|
||||
public EodOpenVolProvider(DateTime valueDate) : base(valueDate)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public double? GetVol(OtcTradeBase td, double spotPrice)
|
||||
{
|
||||
return td?.TradeOpenVolatility;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region----扩展波动率----
|
||||
|
||||
/// <summary>
|
||||
/// 扩展波动率(光证)提供
|
||||
/// </summary>
|
||||
class EodExtendVolProvider_GZ : VarietyVolProvider, IEodVolProvider
|
||||
{
|
||||
public EodExtendVolProvider_GZ(DateTime valueDate) : base(valueDate)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public double? GetVol(OtcTradeBase td, double spotPrice)
|
||||
{
|
||||
if (td is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(td));
|
||||
}
|
||||
|
||||
if (TryGetVol(td.UnderlyingCode, out var vol))
|
||||
{
|
||||
return vol;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 扩展波动率(BidAskVol)提供
|
||||
/// </summary>
|
||||
class EodExtendVolProvider_BidAskVol : EodUnderlyingVolProvider, IEodVolProvider
|
||||
{
|
||||
public EodExtendVolProvider_BidAskVol(DateTime valueDate)
|
||||
: base(valueDate, new[] { "报价Ask", "报价Bid" })
|
||||
{
|
||||
}
|
||||
|
||||
public double? GetVol(OtcTradeBase td, double spotPrice)
|
||||
{
|
||||
if (td is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(td));
|
||||
}
|
||||
|
||||
return InnerGetVol(td, td.BuySell == "买入" ? "报价Ask" : "报价Bid", spotPrice);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 波动率提供者工厂
|
||||
/// </summary>
|
||||
public class EodVolProviderFactory
|
||||
{
|
||||
public static IEodVolProvider GetEodVolProvider(DateTime valueDate, string volType)
|
||||
{
|
||||
switch (volType)
|
||||
{
|
||||
case "持仓":
|
||||
if (PS.Config.IsTradeVol)
|
||||
{
|
||||
return new EodPositionVolProvider_Trade(valueDate);
|
||||
}
|
||||
volType = BLL.valuedateBLL.SystemDate.EodSettleVolMode.TrimToNull() ?? "财务";
|
||||
return new EodPositionVolProvider_Underlying(valueDate, volType);
|
||||
case "开仓":
|
||||
return new EodOpenVolProvider(valueDate);
|
||||
case "对冲":
|
||||
return new EodHedgeVolProvider(valueDate);
|
||||
case "BidAskVol":
|
||||
return new EodExtendVolProvider_BidAskVol(valueDate);
|
||||
case "光证":
|
||||
return new EodExtendVolProvider_GZ(valueDate);
|
||||
default:
|
||||
return new EodUnderlyingSingleVolProvider(valueDate, volType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace YLErp.Modules.EodModule.SettlementModule
|
||||
{
|
||||
public interface IAsyncTaskManager
|
||||
{
|
||||
void SetTaskStep(string step);
|
||||
|
||||
void WaitTasks(params Task[] tasks);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user