258 lines
9.1 KiB
C#
258 lines
9.1 KiB
C#
using System.Linq.Expressions;
|
|
using YLErp.Abstract;
|
|
using YLErp.Abstract.DataProviders;
|
|
using YLErp.Commons;
|
|
using YLErp.DBModels;
|
|
using YLErp.Modules.CalculationModule;
|
|
using YLErp.Modules.CalculationModule.Abstract;
|
|
using YLErp.Modules.DataProviderModule;
|
|
using YLErp.Modules.EodModule;
|
|
using YLErp.Modules.TradeRiskCalcModule.Abstract;
|
|
|
|
namespace YLErp.Modules.TradeRiskCalcModule
|
|
{
|
|
class TradeRiskCalcTestContextBase
|
|
{
|
|
public DateTime ValueDate { get; }
|
|
|
|
public bool IsEodSettle { get; }
|
|
|
|
public bool UseClosePrice { get; }
|
|
|
|
public TraceWrap Trace { get; }
|
|
|
|
protected TradeRiskCalcTestContextBase(TradeRiskCalcTestRequest request)
|
|
{
|
|
if (request is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(request));
|
|
}
|
|
|
|
ValueDate = request.ValueDate;
|
|
IsEodSettle = request.IsEodSettle;
|
|
UseClosePrice = request.UseClosePrice;
|
|
Trace = new TraceWrap("实时风险调试");
|
|
}
|
|
}
|
|
|
|
class TradeRiskCalcTestContext : TradeRiskCalcTestContextBase, ITradeRiskCalcContext
|
|
{
|
|
readonly TradeRiskCalcTestRequest2 _request2;
|
|
|
|
public TradeRiskCalcTestContext(TradeRiskCalcTestRequest request, TradeRiskCalcTestRequest2 request2) : base(request)
|
|
{
|
|
_request2 = request2 ?? throw new ArgumentNullException(nameof(request));
|
|
|
|
VolType = request.VolType;
|
|
|
|
Trace.WriteLine("当前交易日:" + ValueDate);
|
|
|
|
PreValueDate = QdpModule.QdpCalendarHelper.GetNonHolidayDefore(request.ValueDate.AddDays(-1));
|
|
|
|
PreSettleDate = BLL.Eod.EodOperationBase.GetLastSettlementDate(ValueDate, true);
|
|
|
|
Trace.WriteLine("上一交易日:" + PreSettleDate);
|
|
|
|
OptionCalcDataProvider = new OptionCalcDataProvider(this);
|
|
|
|
YdEodPriceProvider = new EodPriceProvider(PreSettleDate);
|
|
|
|
YdTradeHisDataProvider = new TradeHisDataProvider(PreSettleDate);
|
|
|
|
YdEodPositionDataProvider = new YdEodPositionDataProvider().Initialize(_request2, PreSettleDate, OptionCalcDataProvider.UnderlyingDataProvider);
|
|
}
|
|
|
|
public string VolType { get; }
|
|
|
|
public DateTime PreValueDate { get; }
|
|
|
|
public DateTime PreSettleDate { get; }
|
|
|
|
public IOptionCalcDataProvider OptionCalcDataProvider { get; }
|
|
|
|
public IEodPriceProvider YdEodPriceProvider { get; }
|
|
|
|
public ITradeHisDataProvider YdTradeHisDataProvider { get; }
|
|
|
|
public bool HasError { get; private set; }
|
|
|
|
public void AddError(string error)
|
|
{
|
|
HasError = true;
|
|
|
|
Trace.WriteLine("[ERROR]发生错误:" + error);
|
|
}
|
|
|
|
IPriceProvider _ExchangeOptionPriceProvider;
|
|
|
|
public IHedgePnlCalcContext CreateHedgePnlCalcContext(IOtcTradeValueCalcContext optionValueCaclContext)
|
|
{
|
|
if (_ExchangeOptionPriceProvider == null)
|
|
{
|
|
if (IsEodSettle)
|
|
{
|
|
_ExchangeOptionPriceProvider = new EodExchangeOptionPriceProvider(ValueDate, UseClosePrice);
|
|
}
|
|
else
|
|
{
|
|
_ExchangeOptionPriceProvider = new ExchangeOptionPriceProvider();
|
|
}
|
|
}
|
|
return new HedgePnlCalcContext(optionValueCaclContext, new ExchangeTradeCommissionCalc(), _ExchangeOptionPriceProvider);
|
|
}
|
|
|
|
OptionCalcDataProvider _OptionCalcDataProvider;
|
|
|
|
public IOtcTradeValueCalcContext CreateOptionValueCalcContext(double sysRiskFreeRate)
|
|
{
|
|
if (_OptionCalcDataProvider == null)
|
|
{
|
|
_OptionCalcDataProvider = new OptionCalcDataProvider(this);
|
|
}
|
|
|
|
return new OptionValueCalcContext(VolType, IsEodSettle, ValueDate, sysRiskFreeRate, _OptionCalcDataProvider)
|
|
{
|
|
Trace = Trace,
|
|
CalcScenario = Enums.CalcScenarioEnum.RealtimeRisk
|
|
};
|
|
}
|
|
|
|
public IEnumerable<string> GetErrors()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public IEnumerable<trade_cash> GetTrade_Cashes(IEnumerable<int> tradeIds)
|
|
{
|
|
using (var db = DbContextFactory.GetYLDbContext())
|
|
{
|
|
//在使用时会判断ValidState(猜测是为新增待确认的交易)
|
|
return db.trade_cash.Where(t => tradeIds.Contains(t.TradeId) && !t.IsDeleted).ToList();
|
|
}
|
|
}
|
|
|
|
public ITradeRiskEodPositionDataProvider YdEodPositionDataProvider { get; }
|
|
}
|
|
|
|
class YdEodPositionDataProvider : ITradeRiskEodPositionDataProvider
|
|
{
|
|
readonly Dictionary<int, EodTradePositionAndRisk> _positionVolOtcTradeDic;
|
|
readonly Dictionary<int, EodTradePositionAndRisk> _hedgeVolOtcTradeDic;
|
|
|
|
readonly List<EodTradePosition> _exchangeTradeList;
|
|
|
|
public YdEodPositionDataProvider()
|
|
{
|
|
_positionVolOtcTradeDic = new Dictionary<int, EodTradePositionAndRisk>();
|
|
_hedgeVolOtcTradeDic = new Dictionary<int, EodTradePositionAndRisk>();
|
|
_exchangeTradeList = new List<EodTradePosition>();
|
|
}
|
|
|
|
private Expression<Func<T, bool>> CreatePredicate<T>(TradeRiskCalcTestRequest2 _request2) where T : EodTradePosition
|
|
{
|
|
var predicate = PredicateBuilder.True<T>();
|
|
|
|
if (_request2.TradeId > 0)
|
|
{
|
|
predicate = predicate.And(n => n.TradeId == _request2.TradeId);
|
|
}
|
|
else
|
|
{
|
|
if (_request2.ClientId > 0)
|
|
{
|
|
predicate = predicate.And(n => n.ClientId == _request2.ClientId);
|
|
}
|
|
|
|
if (_request2.UnderlyingCodes != null && _request2.UnderlyingCodes.Any())
|
|
{
|
|
predicate = predicate.And(n => _request2.UnderlyingCodes.Contains(n.UnderlyingCode, StringComparer.OrdinalIgnoreCase));
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(_request2.TradeType))
|
|
{
|
|
predicate = predicate.And(n => _request2.TradeType.Equals(n.TradeType, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
if (_request2.AssetBookId > 0)
|
|
{
|
|
predicate = predicate.And(n => n.BookId == _request2.AssetBookId);
|
|
}
|
|
}
|
|
|
|
return predicate;
|
|
}
|
|
|
|
public YdEodPositionDataProvider Initialize(TradeRiskCalcTestRequest2 request, DateTime positionDate, IUnderlyingDataProvider underlyingDataProvider)
|
|
{
|
|
if (underlyingDataProvider is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(underlyingDataProvider));
|
|
}
|
|
|
|
var where = CreatePredicate<eod_trade_position>(request);
|
|
|
|
_exchangeTradeList.Capacity = 500;
|
|
|
|
var service = new EodSettlementService(OptUserInfo.SystemUser);
|
|
var eodPositions = service.GetEodTradePosition<eod_trade_position, eod_trade_risk>(positionDate, where);
|
|
|
|
foreach (var item in eodPositions)
|
|
{
|
|
if (item.Position.TradeId > 0)
|
|
{
|
|
_positionVolOtcTradeDic[item.Position.TradeId] = item;
|
|
}
|
|
else if (item.Position.TradeType == "商品期货")
|
|
{
|
|
var un = underlyingDataProvider.GetUnderlying(item.Position.UnderlyingCode);
|
|
if (un == null || un.MaturityDate.HasValue && DateTime.Compare(un.MaturityDate.Value, positionDate) > 0)
|
|
{
|
|
_exchangeTradeList.Add(item.Position);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_exchangeTradeList.Add(item.Position);
|
|
}
|
|
}
|
|
|
|
_exchangeTradeList.TrimExcess();
|
|
|
|
var where2 = CreatePredicate<eod_trade_position_hedgevol>(request).And(x => x.TradeId > 0);
|
|
|
|
//对冲波动率计算出来的日终持仓
|
|
var eodPositions2 = service.GetEodTradePosition<eod_trade_position_hedgevol, eod_trade_risk_hedgevol>(positionDate, where2);
|
|
|
|
foreach (var item in eodPositions2)
|
|
{
|
|
if (item.Position.TradeId > 0)
|
|
{
|
|
_hedgeVolOtcTradeDic[item.Position.TradeId] = item;
|
|
}
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据交易ID和波动率类型获取场外交易
|
|
/// </summary>
|
|
/// <param name="tradeId"></param>
|
|
/// <param name="volType">对冲|持仓</param>
|
|
/// <returns></returns>
|
|
public EodTradePositionAndRisk GetOtcTradePositionData(int tradeId, string volType)
|
|
{
|
|
if (volType == "对冲")
|
|
{
|
|
return _hedgeVolOtcTradeDic.TryGetValue(tradeId, out var item) ? item : null;
|
|
}
|
|
else
|
|
{
|
|
return _positionVolOtcTradeDic.TryGetValue(tradeId, out var item) ? item : null;
|
|
}
|
|
}
|
|
|
|
public IEnumerable<EodTradePosition> GetExchangeTradePositionList(string volType) => _exchangeTradeList;
|
|
}
|
|
}
|