从山证v2.3.0拷贝

This commit is contained in:
吴方海
2024-05-09 14:06:26 +08:00
parent 566ff33259
commit f9d8a256a6
4471 changed files with 1203456 additions and 9 deletions
@@ -0,0 +1,38 @@
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
/// <summary>
/// 簿记账户
/// </summary>
class AssetUnitDataSource : GenericeCachedDataSource<AssetUnit>
{
public override string TableName => nameof(AssetUnit);
//public override void UpdateData(IEnumerable<string> updateKeyIds)
//{
// System.Diagnostics.Debug.WriteLine("DEBUG");
// base.UpdateData(updateKeyIds);
//}
public static readonly AssetUnitDataSource Default;
static AssetUnitDataSource()
{
Default = new AssetUnitDataSource();
}
}
class AssetUnitDataGroupSource : GenericeCachedDataSource<AssetUnitGroup>
{
public override string TableName => nameof(AssetUnitGroup);
public static readonly AssetUnitDataGroupSource Default;
static AssetUnitDataGroupSource()
{
Default = new AssetUnitDataGroupSource();
}
}
}
}
@@ -0,0 +1,30 @@
using YLErp.Model;
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
class ClientBlackDataSource : GenericeCachedDataSource<client_black>
{
public ClientBlackDataSource()
{
}
public override string TableName => nameof(client_black);
protected override DbContext CreateDbContext()
{
return DbContextFactory.GetClientDbContext(null);
}
//---------------------------------------------
public static readonly ClientBlackDataSource Default;
static ClientBlackDataSource()
{
Default = new ClientBlackDataSource();
}
}
}
}
@@ -0,0 +1,25 @@
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
/// <summary>
/// 客户信息
/// </summary>
class ClientDataSource : GenericeCachedDataSource<Client>
{
public override string TableName => nameof(Client);
protected override DbContext CreateDbContext()
{
return DbContextFactory.GetClientDbContext(null);
}
public static readonly ClientDataSource Default;
static ClientDataSource()
{
Default = new ClientDataSource();
}
}
}
}
@@ -0,0 +1,25 @@
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
/// <summary>
/// 客户等级信息
/// </summary>
class ClientLevelDataSource : GenericeCachedDataSource<ClientLevel>
{
public override string TableName => nameof(ClientLevel);
protected override DbContext CreateDbContext()
{
return DbContextFactory.GetClientDbContext(null);
}
public static readonly ClientLevelDataSource Default;
static ClientLevelDataSource()
{
Default = new ClientLevelDataSource();
}
}
}
}
@@ -0,0 +1,27 @@
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
/// <summary>
/// 标的关联性
/// </summary>
class CorrelationDataSource : GenericeCachedDataSource<CorrelationTable>
{
public CorrelationDataSource()
{
Filter = a => a.State == valuedate.使;
}
public override string TableName => nameof(CorrelationTable);
//---------------------------------------------
public static readonly CorrelationDataSource Default;
static CorrelationDataSource()
{
Default = new CorrelationDataSource();
}
}
}
}
@@ -0,0 +1,20 @@
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
/// <summary>
/// 对冲账户
/// </summary>
class ExchangeAccountDataSource : GenericeCachedDataSource<ExchangeAccount>
{
public override string TableName => nameof(ExchangeAccount);
public static readonly ExchangeAccountDataSource Default;
static ExchangeAccountDataSource()
{
Default = new ExchangeAccountDataSource();
}
}
}
}
@@ -0,0 +1,83 @@
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
/// <summary>
/// 场内期权基础数据
/// </summary>
class ExchangeListOptionDataSource : GenericeCachedDataSource<ExchangeListOption>, Abstract.IDataSourceKey2<ExchangeListOption>
{
public override string TableName => nameof(ExchangeListOption);
readonly Dictionary<string, ExchangeListOption> _dicEx;
public ExchangeListOptionDataSource()
{
_dicEx = new Dictionary<string, ExchangeListOption>(StringComparer.OrdinalIgnoreCase);
AfterUpdate = data =>
{
if (!string.IsNullOrWhiteSpace(data?.ContractCode))
{
_dicEx[data.ContractCode] = data;
}
};
AfterRemove = data =>
{
if (!string.IsNullOrWhiteSpace(data?.ContractCode))
{
_dicEx.Remove(data.ContractCode);
}
};
//使用近1个月的数据作为缓存
var date = DateTime.Today.AddDays(-30);
Filter = PredicateBuilder.Create<ExchangeListOption>(n => n.MaturityDate > date);
}
public ExchangeListOption GetData(string keyId)
{
if (string.IsNullOrWhiteSpace(keyId))
{
return null;
}
lock (this)
{
if (_dicEx.TryGetValue(keyId, out ExchangeListOption data))
{
return data;
}
using (var db = DbContextFactory.GetYLDbContext())
{
var exopt = db.exchange_list_option.AsNoTracking().FirstOrDefault(n => n.ContractCode == keyId);
if (exopt != null)
{
_dic[exopt.id] = exopt;
_dicEx[exopt.ContractCode] = exopt;
}
return exopt?.Clone();
}
}
}
public override void ResetDataSource()
{
base.ResetDataSource();
_dicEx.Clear();
}
//---------------------------------------------
public static readonly ExchangeListOptionDataSource Default;
static ExchangeListOptionDataSource()
{
Default = new ExchangeListOptionDataSource();
}
}
}
}
@@ -0,0 +1,211 @@
using System.Linq.Expressions;
using YLErp.Abstract;
namespace YLErp.Modules.DataCacheModule
{
/// <summary>
/// 通用数据源抽象类
/// </summary>
abstract class GenericeCachedDataSource<TData> : IDataUpdater, IDataSource, IDataSource<TData>, IDataSourceEvent, IJsonSerializable
where TData : class, IDataTraceV2, IDataEntity
{
protected int _maxId = -1;
protected bool _clonable;
protected readonly Dictionary<int, TData> _dic;
protected DateTime _lastUptime;
public event EventHandler DataSourceUpdated;
protected GenericeCachedDataSource()
{
_dic = new Dictionary<int, TData>();
_clonable = typeof(TData).GetInterface(typeof(IClonable<TData>).Name) != null;
}
/// <summary>
/// 数据条数
/// </summary>
public int Count => _dic.Count;
public abstract string TableName { get; }
/// <summary>
/// 获取数据
/// </summary>
public IQueryable<TData> AsQueryable(Expression<Func<TData, bool>> predicate = null)
{
lock (this)
{
if (_dic.Count < 1)
{
return Enumerable.Empty<TData>().AsQueryable();
}
var query = _dic.Values.AsQueryable();
if (predicate != null)
{
query = query.Where(predicate);
}
if (_clonable)
{
return new DataCacheQueryable<TData>(query);
}
return query;
}
}
/// <summary>
/// 更新数据源
/// </summary>
public virtual void UpdateData(IEnumerable<string> updateKeyIds)
{
lock (_dic)
{
InnerUpdateData(updateKeyIds);
}
}
private void InnerUpdateData(IEnumerable<string> updateKeyIds)
{
using (var db = CreateDbContext())
{
var table = db.Set<TData>().AsNoTracking();
var minId = _maxId;
var maxId = table.Max(n => (int?)n.id) ?? 0;
//ID更新集合
var updateIds = DataConvert.ConvertToInt32Set(updateKeyIds);
if (maxId < minId)
{
minId = -1;
}
if (maxId == minId && !updateIds.Any(n => n > 0))
{
return;
}
_lastUptime = DateTime.Now;
//数据查询
var query = table.Where(n => (n.id > minId && n.id <= maxId) || updateIds.Contains(n.id));
if (Filter != null)
{
query = query.Where(Filter);
}
var datas = query.OrderBy(n => n.id).ToArray();
datas = PreProcessDatas(datas);
lock (this)
{
//更新字典数据
foreach (var data in datas)
{
updateIds.Remove(data.id);
_dic[data.id] = data;
AfterUpdate?.Invoke(data);
}
//取不到数据的直接从本地字典中删除
updateIds.Remove(0);
foreach (var id in updateIds)
{
if (AfterRemove != null && _dic.TryGetValue(id, out var data))
{
AfterRemove(data);
}
_dic.Remove(id);
}
}
_maxId = maxId;
DataSourceUpdated?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// 根据KeyID获取数据
/// </summary>
public virtual TData GetData(int keyId)
{
if (keyId < 1)
{
return null;
}
lock (this)
{
if (_dic.TryGetValue(keyId, out TData data))
{
return _clonable ? ((IClonable<TData>)data).Clone() : data;
}
using (var db = CreateDbContext())
{
var dbModel = db.Set<TData>().AsNoTracking().FirstOrDefault(n => n.id == keyId);
if (dbModel != null)
{
_dic[dbModel.id] = dbModel;
AfterUpdate?.Invoke(dbModel);
return _clonable ? ((IClonable<TData>)dbModel).Clone() : dbModel;
}
return dbModel;
}
}
}
/// <summary>
/// 重置数据源
/// </summary>
public virtual void ResetDataSource()
{
_maxId = -1;
_dic.Clear();
}
//--------用于扩展配置------------------
/// <summary>
/// 数据加载后预处理
/// </summary>
protected virtual TData[] PreProcessDatas(TData[] datas)
{
return datas;
}
/// <summary>
/// 查询过滤条件
/// </summary>
public Expression<Func<TData, bool>> Filter { get; set; }
/// <summary>
/// 更新以后事件处理
/// </summary>
public Action<TData> AfterUpdate { get; set; }
/// <summary>
/// 删除以后事件处理
/// </summary>
public Action<TData> AfterRemove { get; set; }
/// <summary>
/// 创建数据库上下文(默认使用YLContext)
/// </summary>
protected virtual DbContext CreateDbContext()
{
return DbContextFactory.GetYLDbContext();
}
public string ToJson()
{
return new { _maxId, _lastUptime, _dic }.ToJson();
}
}
}
@@ -0,0 +1,14 @@
namespace YLErp.Modules.DataCacheModule
{
class MarketDataSource : GenericeCachedDataSource<Market>
{
public override string TableName => nameof(Market);
public static readonly MarketDataSource Default;
static MarketDataSource()
{
Default = new MarketDataSource();
}
}
}
@@ -0,0 +1,26 @@
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
/// <summary>
/// 个股黑白名单
/// </summary>
class StockBlackWhiteDataSource : GenericeCachedDataSource<StockBlackWhite>
{
public StockBlackWhiteDataSource()
{
}
public override string TableName => nameof(StockBlackWhite);
//---------------------------------------------
public static readonly StockBlackWhiteDataSource Default;
static StockBlackWhiteDataSource()
{
Default = new StockBlackWhiteDataSource();
}
}
}
}
@@ -0,0 +1,25 @@
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
/// <summary>
/// 股票手续费设定
/// </summary>
class StockCommissionDataSource : GenericeCachedDataSource<StockCommissionConfig>
{
public StockCommissionDataSource()
{
Filter = n => n.Enabled == 1;
}
public override string TableName => nameof(StockCommissionConfig);
public static readonly StockCommissionDataSource Default;
static StockCommissionDataSource()
{
Default = new StockCommissionDataSource();
}
}
}
}
@@ -0,0 +1,471 @@
using System.Collections.Concurrent;
using YieldChain.Commons;
using YieldChain.Helpers;
using YLErp.Abstract.DataProviders;
using YLErp.BLL;
using YLErp.Models;
using YLErp.Modules.UnderlyingModule;
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
/// <summary>
/// 标的数据源
/// </summary>
class UnderlyingDataSource : GenericeCachedDataSource<underlying_manager>, IUnderlyingDataSource, IBasketPriceProvider
{
readonly ThrottleAction _updatePricethrottle;
readonly Dictionary<string, underlying_manager> _dicEx;
readonly ConcurrentDictionary<string, SyntheticUnderlying> _dicSynthetic;
private UnderlyingDataSource()
{
_updatePricethrottle = new ThrottleAction(ThrottleUpdatePricesAction, 3, 180);
_dicEx = new Dictionary<string, underlying_manager>(StringComparer.OrdinalIgnoreCase);
_dicSynthetic = new ConcurrentDictionary<string, SyntheticUnderlying>(StringComparer.OrdinalIgnoreCase);
AfterUpdate = AfterUpdateHandle;
AfterRemove = AfterRemoveHandle;
//使用近2年的标的数据作为缓存
int.TryParse(PS.Config.ErpElement.UnderlyingCacheCfg, out int years);
if (years < 0) years = -years;
var date = DateTime.Today.AddYears(years < 2 ? -2 : -years);
Filter = PredicateBuilder.Create<underlying_manager>(
n => (n.UnderlyingInstrumentType != ConsGlobal.InstrumentType.CommodityFutures
&& n.UnderlyingInstrumentType != ConsGlobal.InstrumentType.StockIF) || n.MaturityDate >= date);
}
public override string TableName => nameof(underlying_manager);
/// <summary>
/// 扩展数据更新
/// </summary>
private void AfterUpdateHandle(underlying_manager data)
{
if (string.IsNullOrWhiteSpace(data?.UnderlyingCode))
{
return;
}
_dicEx[data.UnderlyingCode] = data;
_dicSynthetic.TryRemove(data.UnderlyingCode, out _);
var variety = DataCacheProvider.GetVarietyDataSource().GetData(data.UnderlyingTypeId);
if (data.IsStock())
{
data.CountRatio = 1;
data.ContractSize = data.ContractSize > 0 ? data.ContractSize : 100;
data.QuoteUnit = data.TradeUnit = "股";
data.PinYinFirst = PingYinHelper.GetFirstPinYin(data.UnderlyingName)?.ToUpperInvariant();
data.CommodityCode = variety?.VarietyCode;
}
else if (data.IsBasket())
{
data.CountRatio = 1;
data.ContractSize = data.ContractSize > 0 ? data.ContractSize : 100;
data.QuoteUnit = data.TradeUnit = "股";
}
else if (data.IsSynthetic())
{
data.CountRatio = 1;
data.ContractSize = data.ContractSize > 0 ? data.ContractSize : 1;
}
else
{
if (variety != null)
{
if (data.ContractSize < 1)
{
data.ContractSize = DBModels.Helpers.VarietyHelper.GetTradeUnitValue(variety.VarietyCode, variety.TradeUnit) ?? 1;
}
if (string.IsNullOrEmpty(data.QuoteUnit))
{
data.QuoteUnit = DBModels.Helpers.VarietyHelper.GetQuoteUnitSingleOriginal(variety.QuoteUnit);
}
if (string.IsNullOrEmpty(data.TradeUnit))
{
data.TradeUnit = DBModels.Helpers.VarietyHelper.GetTradeUnitSingle(variety.TradeUnit);
}
data.CountRatio = DBModels.Helpers.VarietyHelper.GetCountRatio(variety.QuoteUnit);
data.CommodityCode = variety?.VarietyCode;
}
if (data.ContractSize < 1)
{
data.ContractSize = 1;
}
if (data.PriceTick < 1e-4)
{
data.PriceTick = DBModels.Helpers.VarietyHelper.ParseMinPriceChange(variety) ?? 0;
}
}
if (data.PriceTick < 1e-4)
{
data.PriceTick = 0.01;
}
}
/// <summary>
/// 扩展数据移除操作
/// </summary>
private void AfterRemoveHandle(underlying_manager data)
{
if (string.IsNullOrWhiteSpace(data?.UnderlyingCode))
{
return;
}
_dicEx.Remove(data.UnderlyingCode);
_dicSynthetic.TryRemove(data.UnderlyingCode, out _);
}
/// <summary>
/// 根据标的代码获取标的数据
/// </summary>
public underlying_manager GetData(string underlyingCode)
{
if (string.IsNullOrWhiteSpace(underlyingCode))
{
return null;
}
lock (this)
{
if (_dicEx.TryGetValue(underlyingCode, out var underlying))
{
var clone = underlying.Clone();
clone.Price = InnerGetPrice(clone);
return clone;
}
using (var db = DbContextFactory.GetYLDbContext())
{
var un = db.underlying_manager.AsNoTracking().FirstOrDefault(n => n.UnderlyingCode == underlyingCode);
if (un != null)
{
_dic[un.id] = un;
AfterUpdateHandle(un);
if (un.IsBasket() && InnerTryGetPrice(un, out var price))
{
un.Price = price;
}
}
return un?.Clone();
}
}
}
/// <summary>
/// 根据标的ID获取标的数据
/// </summary>
public override underlying_manager GetData(int keyId)
{
var un = base.GetData(keyId);
if (un != null)
{
un.Price = InnerGetPrice(un);
}
return un;
}
#region----IPriceProvider----
/// <summary>
/// 根据标的代码获取标的价格(包含组合标的)
/// </summary>
public double GetPrice(int underlyingId)
{
return InnerGetPrice(GetData(underlyingId));
}
/// <summary>
/// 根据标的代码获取标的价格(标的代码不区分大小写)(包含组合标的)
/// </summary>
public double GetPrice(string underlyingCode)
{
return InnerGetPrice(GetData(underlyingCode));
}
/// <summary>
/// 根据标的代码获取标的价格(包含组合标的)
/// </summary>
public bool TryGetPrice(int underlyingId, out double price)
{
return InnerTryGetPrice(GetData(underlyingId), out price);
}
/// <summary>
/// 根据标的代码获取标的价格,标的代码不区分大小写(包含组合标的)
/// </summary>
public bool TryGetPrice(string underlyingCode, out double price)
{
return InnerTryGetPrice(GetData(underlyingCode), out price);
}
public bool InitData(List<string> underlyingCodes)
{
lock (this)
{
var notInCaches = underlyingCodes.Where(p => !_dicEx.Keys.Contains(p)).ToList();
if (notInCaches != null && notInCaches.Count > 0)
{
List<underlying_manager> unList = null;
using (var db = DbContextFactory.GetYLDbContext())
{
unList = db.underlying_manager.AsNoTracking().Where(n => notInCaches.Contains(n.UnderlyingCode)).ToList();
}
if (unList != null && unList.Count > 0)
{
unList.ForEach(un =>
{
_dic[un.id] = un;
AfterUpdateHandle(un);
if (un.IsBasket() && InnerTryGetPrice(un, out var price))
{
un.Price = price;
}
});
}
}
}
return true;
}
private double InnerGetPrice(underlying_manager underlying)
{
return InnerTryGetPrice(underlying, out var price) ? price : 0;
}
private bool InnerTryGetPrice(underlying_manager un, out double price)
{
price = 0;
if (un == null)
{
return false;
}
if (un.IsBasket())
{
price = BasketUnderlyingHelper.GetBasketPrice(un, this, true).Price;
}
else
{
price = un.Price ?? 0;
}
return true;
}
/// <summary>
/// 更新标的价格
/// </summary>
public bool UpdatePrices(bool delay)
{
if (_updatePricethrottle.Execute())
{
if (delay)
{
_updatePricethrottle.DelayExecute(60);
}
return true;
}
return false;
}
private void ThrottleUpdatePricesAction()
{
using (var db = DbContextFactory.GetYLDbContext())
{
var query1 = from u in db.underlying_manager
where u.UnderlyingState != "Matured"
&& u.UnderlyingType != "组合标的"
select new PriceModel
{
InstrumentCode = u.UnderlyingCode,
Price = u.Price ?? 0,
PreClose = u.PrevClosePrice,
PriceTime = u.LastUpdateTime
};
var query2 = from su in db.synthetic_underlying
join u in db.underlying_manager on su.Name equals u.UnderlyingCode
join u1 in db.underlying_manager on su.UnderlyingCode1 equals u1.UnderlyingCode into u1t
from u1 in u1t.DefaultIfEmpty()
join u2 in db.underlying_manager on su.UnderlyingCode2 equals u2.UnderlyingCode into u2t
from u2 in u2t.DefaultIfEmpty()
join u3 in db.underlying_manager on su.UnderlyingCode3 equals u3.UnderlyingCode into u3t
from u3 in u3t.DefaultIfEmpty()
join u4 in db.underlying_manager on su.UnderlyingCode4 equals u4.UnderlyingCode into u4t
from u4 in u4t.DefaultIfEmpty()
where u.UnderlyingState == "Live" && u.LaunchState == "1"
select new PriceModel
{
InstrumentCode = u.UnderlyingCode,
Price = (u1.Price ?? 0) * (su.Coefficient1 ?? 0)
+ (u2.Price ?? 0) * (su.Coefficient2 ?? 0)
+ (u3.Price ?? 0) * (su.Coefficient3 ?? 0)
+ (u4.Price ?? 0) * (su.Coefficient4 ?? 0)
+ (su.Constant ?? 0),
PreClose = (u1.PrevClosePrice ?? 0) * (su.Coefficient1 ?? 0)
+ (u2.PrevClosePrice ?? 0) * (su.Coefficient2 ?? 0)
+ (u3.PrevClosePrice ?? 0) * (su.Coefficient3 ?? 0)
+ (u4.PrevClosePrice ?? 0) * (su.Coefficient4 ?? 0)
+ (su.Constant ?? 0),
PriceTime = u1.LastUpdateTime ?? u2.LastUpdateTime ?? u3.LastUpdateTime ?? u4.LastUpdateTime
};
var datas = query1.Concat(query2).ToArray();
foreach (var item in datas)
{
if (_dicEx.TryGetValue(item.InstrumentCode, out var underlying))
{
underlying.Price = item.Price;
underlying.PrevClosePrice = item.PreClose;
underlying.LastUpdateTime = item.PriceTime;
}
}
}
}
/// <summary>
/// 获取篮子的子标的价格
/// </summary>
public bool TryGetSubPrice(string underlyingCode, out double price, out double settlePrice)
{
//篮子标的的子标的只能是普通标的
var data = GetData(underlyingCode);
if (data != null)
{
price = settlePrice = data.Price ?? 0;
return true;
}
price = settlePrice = 0;
return false;
}
#endregion
/// <summary>
/// 获取组合标的信息
/// </summary>
public SyntheticUnderlying GetSyntheticUnderlying(string underlyingCode)
{
if (string.IsNullOrEmpty(underlyingCode))
{
return null;
}
if (_dicSynthetic.TryGetValue(underlyingCode, out var sy))
{
return sy;
}
var un = GetData(underlyingCode);
if (un?.CommodityCode != "组合标的")
{
return null;
}
using (var db = DbContextFactory.GetYLDbContext())
{
sy = db.synthetic_underlying.AsNoTracking().FirstOrDefault(n => n.Name == underlyingCode);
if (sy != null)
{
_dicSynthetic[sy.Name] = sy;
}
return sy?.Clone();
}
}
/// <summary>
/// 获取数量转份额的乘积因子(最小为1)
/// </summary>
public int GetCountRatio(string underlyingCode)
{
return GetData(underlyingCode)?.CountRatio ?? 1;
}
public override void ResetDataSource()
{
base.ResetDataSource();
_dicEx.Clear();
_dicSynthetic.Clear();
UpdateData(null);
}
//排序规则:优先使用未过期的期货,然后股票/现货,然后没有过期日的期货,然后过期的期货
protected override underlying_manager[] PreProcessDatas(underlying_manager[] datas)
{
var valueDate = valuedateBLL.ValueDate;
return datas.OrderBy(n =>
{
var prefix = "1";
if (n.IsFutures())
{
if (n.MaturityDate.HasValue)
{
prefix = (n.MaturityDate.Value > valueDate ? 0 : valueDate.Year - n.MaturityDate.Value.Year + 2).ToString();
}
else
{
prefix = "2";
}
}
return prefix + (n.IsCombined() ? "1" : "0") + n.UnderlyingCode;
}).ToArray();
}
/// <summary>
/// 更新标的资产启用状态
/// </summary>
public void UpdateLauchState()
{
using (var db = DbContextFactory.GetYLDbContext())
{
var datas = db.underlying_manager.Where(Filter).Select(n => new { n.id, n.LaunchState }).ToArray();
lock (_dic)
{
foreach (var item in datas)
{
if (_dic.TryGetValue(item.id, out var um))
{
um.LaunchState = item.LaunchState;
}
}
}
}
}
//---------------------------------------------
public static readonly UnderlyingDataSource Default;
static UnderlyingDataSource()
{
Default = new UnderlyingDataSource();
}
}
}
}
@@ -0,0 +1,186 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using YieldChain.Commons;
using YieldChain.Helpers;
using YLErp.Abstract;
using YLErp.Abstract.DataProviders;
using YLErp.BLL;
using YLErp.Models;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.UnderlyingModule;
using YLErp.QdpModule;
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
class UnderlyingDbDataSource : IUnderlyingDataSource, IBasketPriceProvider, IDataUpdater, IDataSource, IDataSource<underlying_manager>, IDataSourceEvent, IJsonSerializable
{
private readonly YLContext _context=new YLContext();
/// <summary>
/// 查询过滤条件
/// </summary>
public Expression<Func<underlying_manager, bool>> Filter { get; set; }
public int Count
{
get
{
return _context.underlying_manager.Count();
}
}
public string TableName => "underlying_manager";
public IQueryable<underlying_manager> AsQueryable(Expression<Func<underlying_manager, bool>> predicate = null)
{
if (predicate == null)
{
return _context.underlying_manager;
}
return _context.underlying_manager.Where(predicate);
}
public int GetCountRatio(string underlyingCode)
{
return GetData(underlyingCode)?.CountRatio ?? 1;
}
public underlying_manager GetData(string underlyingCode)
{
return _context.underlying_manager.FirstOrDefault(x => x.UnderlyingCode == underlyingCode);
}
public underlying_manager GetData(int keyId)
{
return _context.underlying_manager.FirstOrDefault(x => x.id == keyId);
}
public double GetPrice(int underlyingId)
{
return InnerGetPrice(GetData(underlyingId));
}
public double GetPrice(string underlyingCode)
{
return InnerGetPrice(GetData(underlyingCode));
}
public SyntheticUnderlying GetSyntheticUnderlying(string underlyingCode)
{
if (string.IsNullOrEmpty(underlyingCode))
{
return null;
}
var un = GetData(underlyingCode);
if (un?.CommodityCode != "组合标的")
{
return null;
}
var sy = _context.synthetic_underlying.AsNoTracking().FirstOrDefault(n => n.Name == underlyingCode);
return sy?.Clone();
}
public bool InitData(List<string> underlyingCodes)
{
return true;
}
public void ResetDataSource()
{
}
public bool TryGetPrice(int underlyingId, out double price)
{
return InnerTryGetPrice(GetData(underlyingId), out price);
}
public bool TryGetPrice(string underlyingCode, out double price)
{
return InnerTryGetPrice(GetData(underlyingCode), out price);
}
public bool TryGetSubPrice(string underlyingCode, out double price, out double settlePrice)
{
//篮子标的的子标的只能是普通标的
var data = GetData(underlyingCode);
if (data != null)
{
price = settlePrice = data.Price ?? 0;
return true;
}
price = settlePrice = 0;
return false;
}
public void UpdateLauchState()
{
}
public bool UpdatePrices(bool delay)
{
return true;
}
private double InnerGetPrice(underlying_manager underlying)
{
return InnerTryGetPrice(underlying, out var price) ? price : 0;
}
private bool InnerTryGetPrice(underlying_manager un, out double price)
{
price = 0;
if (un == null)
{
return false;
}
if (un.IsBasket())
{
price = BasketUnderlyingHelper.GetBasketPrice(un, this, true).Price;
}
else if (un.IsBond())
{
var valueDate = valuedateBLL.ValueDate;
valueDate=QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(-1));
var bondPrice = EodPriceQueryService.GetBondPrice(valueDate,un.UnderlyingCode);
price = bondPrice!=null? bondPrice.ClosePrice:un.Price??0;
}
else
{
price = un.Price ?? 0;
}
return true;
}
public void UpdateData(IEnumerable<string> updateKeyIds)
{
}
public string ToJson()
{
return "";
}
public static readonly UnderlyingDbDataSource Default;
public event EventHandler DataSourceUpdated;
static UnderlyingDbDataSource()
{
Default = new UnderlyingDbDataSource();
}
}
}
}
@@ -0,0 +1,62 @@
namespace YLErp.Modules.DataCacheModule
{
public static partial class DataCacheManager
{
class VarietyDataSource : GenericeCachedDataSource<Variety>, Abstract.IDataSourceKey2<Variety>
{
public override string TableName => nameof(Variety);
readonly Dictionary<string, Variety> _dicEx;
private VarietyDataSource()
{
_dicEx = new Dictionary<string, Variety>(StringComparer.OrdinalIgnoreCase);
}
public Variety GetData(string varietyCode)
{
if (string.IsNullOrWhiteSpace(varietyCode))
{
return null;
}
lock (this)
{
if (_dicEx.TryGetValue(varietyCode, out var variety))
{
var clone = variety.Clone();
return clone;
}
using (var db = DbContextFactory.GetYLDbContext())
{
var va = db.variety.AsNoTracking().FirstOrDefault(n => n.VarietyCode == varietyCode);
if (va != null)
{
_dic[va.id] = va;
AfterUpdateHandle(va);
}
return va?.Clone();
}
}
}
private void AfterUpdateHandle(Variety data)
{
if (string.IsNullOrWhiteSpace(data.VarietyCode))
{
return;
}
_dicEx[data.VarietyCode] = data;
}
public static readonly VarietyDataSource Default;
static VarietyDataSource()
{
Default = new VarietyDataSource();
}
}
}
}