using YLErp.Abstract.DataProviders;
namespace YLErp.Modules.DataProviderModule
{
///
/// 日终参考价数据提供(这个类只有特殊情况下用到)
///
public class EodReferencePriceProvider : IPriceProvider
{
bool _initialized;
Dictionary _priceDic;
///
/// 构造函数
///
/// 结算价取值日
public EodReferencePriceProvider(DateTime valueDate)
{
ValueDate = valueDate.Date;
}
///
/// 结算价取值日
///
public DateTime ValueDate { get; }
///
/// 初始化数据字典
/// (提前初始化可在大批量标的取结算价时提高一定性能)
///
public EodReferencePriceProvider Initialize(string[] underlyingCodes = null)
{
//多线程时只初始化一次
if (!_initialized)
{
lock (this)
{
if (!_initialized)
{
InnerInitialize(underlyingCodes);
}
_initialized = true;
}
}
return this;
}
private void InnerInitialize(string[] underlyingCodes)
{
using (var db = DbContextFactory.GetYLDbContext())
{
var predicate1 = PredicateBuilder.Create(t => t.ValueDate == ValueDate);
var predicate2 = PredicateBuilder.Create(t => t.ValueDate == ValueDate);
if (underlyingCodes != null && underlyingCodes.Any(n => !string.IsNullOrEmpty(n)))
{
predicate1 = predicate1.And(n => underlyingCodes.Contains(n.UnderlyingCode));
predicate2 = predicate2.And(n => underlyingCodes.Contains(n.UnderlyingCode));
}
var eodFutureQuery = db.eod_commodity_future_price.Where(predicate1).Select(n => new { n.UnderlyingCode, n.ReferencePrice });
var eodStockQuery = db.eod_stock_price.Where(predicate2).Select(n => new { n.UnderlyingCode, n.ReferencePrice });
//数据加载到字典中
var set = new HashSet(StringComparer.OrdinalIgnoreCase);
_priceDic = eodFutureQuery.Concat(eodStockQuery).ToArray()
.Where(n => n.UnderlyingCode != null && set.Add(n.UnderlyingCode))
.ToDictionary(n => n.UnderlyingCode, m => m.ReferencePrice, StringComparer.OrdinalIgnoreCase);
}
}
public double GetPrice(string instrumentCode)
{
return InnerTryGetPrice(instrumentCode, out var price) ? price : 0d;
}
public bool TryGetPrice(string instrumentCode, out double price)
{
return InnerTryGetPrice(instrumentCode, out price);
}
private bool InnerTryGetPrice(string instrumentCode, out double price)
{
price = 0;
if (string.IsNullOrWhiteSpace(instrumentCode))
{
return false;
}
lock (this)
{
if (_priceDic == null)
{
_priceDic = new Dictionary(StringComparer.OrdinalIgnoreCase);
}
else if (_priceDic.TryGetValue(instrumentCode, out var nPrice))
{
price = nPrice ?? 0;
return nPrice.HasValue;
}
else if (_initialized)
{
return false;
}
}
var exists = EodPriceQueryService.TryGetReferencePrice(ValueDate, instrumentCode, out price);
lock (this)
{
_priceDic[instrumentCode] = exists ? (double?)price : null;
}
return exists;
}
}
}