using System.Collections.Concurrent; using YLErp.Abstract; using YLErp.DBModels.Consts; namespace YLErp.Modules.DataProviderModule { /// /// 交易历史数据提供 /// public class TradeHisDataProvider : ITradeHisDataProvider { readonly DateTime _valueDate; //key:tradeId readonly ConcurrentDictionary _dic; public TradeHisDataProvider(DateTime valueDate) { _valueDate = valueDate; _dic = new ConcurrentDictionary(); } /// /// 加载最近三个月的数据做初始化 /// public TradeHisDataProvider Initialize() { if (_dic.Count > 0) { return this; } lock (this) { if (_dic.Count > 0) { return this; } //只取3个月以内的 var startDate = _valueDate.AddMonths(-3); using (var db = DbContextFactory.GetYLDbContext()) { var query1 = from a in db.TradeHisData where a.ValueDate > startDate && a.ValueDate <= _valueDate group a by new { a.TradeId, a.ValueType } into g select new { g.Key.TradeId, g.Key.ValueType, ValueDate = g.Max(n => n.ValueDate) }; var query2 = from a in query1 join b in db.TradeHisData on a equals new { b.TradeId, b.ValueType, b.ValueDate } select new { b.TradeId, b.ValueType, b.Value }; var datas = query2.ToArray(); foreach (var data in datas) { if (!_dic.TryGetValue(data.TradeId, out var idata)) { _dic[data.TradeId] = idata = new InnerTradeHisData(); } if (ConsTradeField.NoRiskRate.Equals(data.ValueType, StringComparison.OrdinalIgnoreCase)) { idata.NoRiskRate = data.Value; idata.Flag |= ValueFlag.NoRiskRate; } else if (ConsTradeField.DividendRate.Equals(data.ValueType, StringComparison.OrdinalIgnoreCase)) { idata.DividendRate = data.Value; idata.Flag |= ValueFlag.DividendRate; } } } } return this; } private double? GetValue(int tradeId, ValueFlag valueFlag) { if (_dic.TryGetValue(tradeId, out var data)) { if ((data.Flag & valueFlag) == valueFlag) { switch (valueFlag) { case ValueFlag.NoRiskRate: return data.NoRiskRate; case ValueFlag.DividendRate: return data.DividendRate; default: throw new InvalidOperationException(); } } } else { _dic[tradeId] = data = new InnerTradeHisData(); } string valueType; switch (valueFlag) { case ValueFlag.NoRiskRate: valueType = ConsTradeField.NoRiskRate; break; case ValueFlag.DividendRate: valueType = ConsTradeField.DividendRate; break; default: throw new InvalidOperationException(); } using (var db = DbContextFactory.GetYLDbContext()) { var query = from n in db.TradeHisData where n.TradeId == tradeId && n.ValueDate <= _valueDate && n.ValueType == valueType orderby n.ValueDate descending select (double?)n.Value; var value = query.FirstOrDefault(); switch (valueFlag) { case ValueFlag.NoRiskRate: data.NoRiskRate = value; break; case ValueFlag.DividendRate: data.DividendRate = value; break; default: throw new InvalidOperationException(); } data.Flag |= valueFlag; return value; } } /// /// 获取无风险利率 /// public double? GetNoRiskRate(int tradeId) { return GetValue(tradeId, ValueFlag.NoRiskRate); } /// /// 获取分红率 /// public double? GetDividendRate(int tradeId) { return GetValue(tradeId, ValueFlag.DividendRate); } class InnerTradeHisData { /// /// 无风险利率 /// public double? NoRiskRate; /// /// 分红率 /// public double? DividendRate; public ValueFlag Flag; } enum ValueFlag { None = 0, NoRiskRate = 1 << 0, DividendRate = 1 << 1 } } }