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

183 lines
5.8 KiB
C#

using System.Collections.Concurrent;
using YLErp.Abstract;
using YLErp.DBModels.Consts;
namespace YLErp.Modules.DataProviderModule
{
/// <summary>
/// 交易历史数据提供
/// </summary>
public class TradeHisDataProvider : ITradeHisDataProvider
{
readonly DateTime _valueDate;
//key:tradeId
readonly ConcurrentDictionary<int, InnerTradeHisData> _dic;
public TradeHisDataProvider(DateTime valueDate)
{
_valueDate = valueDate;
_dic = new ConcurrentDictionary<int, InnerTradeHisData>();
}
/// <summary>
/// 加载最近三个月的数据做初始化
/// </summary>
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;
}
}
/// <summary>
/// 获取无风险利率
/// </summary>
public double? GetNoRiskRate(int tradeId)
{
return GetValue(tradeId, ValueFlag.NoRiskRate);
}
/// <summary>
/// 获取分红率
/// </summary>
public double? GetDividendRate(int tradeId)
{
return GetValue(tradeId, ValueFlag.DividendRate);
}
class InnerTradeHisData
{
/// <summary>
/// 无风险利率
/// </summary>
public double? NoRiskRate;
/// <summary>
/// 分红率
/// </summary>
public double? DividendRate;
public ValueFlag Flag;
}
enum ValueFlag
{
None = 0,
NoRiskRate = 1 << 0,
DividendRate = 1 << 1
}
}
}