148 lines
5.7 KiB
C#
148 lines
5.7 KiB
C#
using YLErp.Abstract.DataProviders;
|
|
using YLErp.Modules.DataProviderModule;
|
|
|
|
namespace YLErp.Modules.TradeModule
|
|
{
|
|
/// <summary>
|
|
/// 气囊结构服务
|
|
/// </summary>
|
|
public class TradeAirbagService : TradeServiceBase
|
|
{
|
|
public TradeAirbagService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
}
|
|
|
|
public TradeAirbagService(YLBaseService baseService) : base(baseService)
|
|
{
|
|
}
|
|
|
|
public void SetKnockIn(DateTime valueDate, IEodPriceProviderV2 priceProvider, DateTime? startDate = null
|
|
, Action<OtcTrade, trade_airbag> afterKnowInOut = null, System.Collections.Generic.IEnumerable<int> clienIds = null)
|
|
{
|
|
if (priceProvider is null)
|
|
{
|
|
priceProvider = new EodPriceProvider(valueDate);
|
|
}
|
|
|
|
if (startDate == null)
|
|
{
|
|
startDate = valueDate.AddYears(-5);
|
|
}
|
|
|
|
var query = from trade in DbContext.trade
|
|
join airbag in DbContext.trade_airbag on trade.id equals airbag.TradeId
|
|
where trade.TradeDate > startDate.Value && trade.TradeDate <= valueDate
|
|
&& string.IsNullOrEmpty(airbag.KnockInOutStatus)
|
|
&& trade.TradeType == "气囊结构"
|
|
&& ConsTrade.确认成交 == trade.TradeStatus
|
|
&& trade.ValidState != ConsGlobal.InValid
|
|
&& trade.DividendDate < valueDate
|
|
select new
|
|
{
|
|
trade,
|
|
tradeAirbag = airbag
|
|
};
|
|
#region 增加客户筛选 tw
|
|
if (clienIds != null)
|
|
{
|
|
query = query.Where(l => clienIds.Contains(l.trade.ClientId));
|
|
}
|
|
#endregion
|
|
var trades = query.ToList();
|
|
|
|
if (trades == null || !trades.Any())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var tradeIds = trades.Select(x => x.trade.id).ToArray();
|
|
|
|
var manuallyTradeObservationPrices = DbContext.manually_trade_observation_price
|
|
.Where(x => tradeIds.Contains(x.TradeId) && x.ValueDate == valueDate).ToDictionary(n => n.TradeId);
|
|
|
|
foreach (var tr in trades)
|
|
{
|
|
if (tr.trade.ExerciseDate < valueDate)
|
|
{
|
|
continue;//已到期交易不再观察;
|
|
}
|
|
var tradeStatus = tr.trade.TradeStatus;
|
|
|
|
double? closePrice;
|
|
|
|
if (manuallyTradeObservationPrices.TryGetValue(tr.trade.id, out var manuallyTradeObservationPrice))
|
|
{
|
|
closePrice = manuallyTradeObservationPrice.Price;
|
|
}
|
|
else if (!priceProvider.TryGetEodPrice(tr.trade.UnderlyingCode, out var eodprice))
|
|
{
|
|
throw new Exception($"[{tr.trade.TradeType}:{tr.trade.TradeNumber}]标的:{tr.trade.UnderlyingCode} 未找到结算价");
|
|
}
|
|
else
|
|
{
|
|
closePrice = eodprice.ClosePrice;
|
|
}
|
|
|
|
var oldKnockInOutStatus = tr.tradeAirbag.KnockInOutStatus;
|
|
CheckAirbagKnockInStatus(tr.trade, tr.tradeAirbag, valueDate, closePrice);
|
|
|
|
if (oldKnockInOutStatus != tr.tradeAirbag.KnockInOutStatus)
|
|
{
|
|
var KnockInOutStatus = tr.tradeAirbag.KnockInOutStatus == ConsTrade.KnockState.KnockedIn ? "敲入" : "敲出";
|
|
AddTradeOperationHistoryAndSetParentTradeInfo(false, tr.trade, KnockInOutStatus, KnockInOutStatus);
|
|
}
|
|
|
|
if (tradeStatus != tr.trade.TradeStatus|| oldKnockInOutStatus != tr.tradeAirbag.KnockInOutStatus)
|
|
{
|
|
//删除E/Bod_Trade记录
|
|
RemoveEodTradeAndFutureInfo(false, tr.trade.id, valueDate);
|
|
}
|
|
|
|
if (afterKnowInOut != null && DbContext.Entry(tr.tradeAirbag).State == EntityState.Modified)
|
|
{
|
|
afterKnowInOut(tr.trade, tr.tradeAirbag);
|
|
}
|
|
}
|
|
|
|
//更新
|
|
DbContext.SaveChanges();
|
|
}
|
|
|
|
public void CheckAirbagKnockInStatus(OtcTradeBase td, trade_airbag tradeAirbag, DateTime valueDate, double? closePrice)
|
|
{
|
|
//气囊结构暂时都是每日连续观察,不用考虑观察周期问题
|
|
//气囊结构暂时都是向下敲入
|
|
if (closePrice <= (td.IsMoneynessOptionData ? tradeAirbag.Barrier * td.SpotPrice : tradeAirbag.Barrier))
|
|
{
|
|
tradeAirbag.KnockInOutStatus = ConsTrade.KnockState.KnockedIn;
|
|
tradeAirbag.KnockInOutDate = valueDate;
|
|
tradeAirbag.KnockInOutNotional = td.Notional;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置敲入敲出状态
|
|
/// </summary>
|
|
public trade_airbag SaveKnockInOutStatus(int tradeId, DateTime? KnockInOutDate, string KnockInOutStatus)
|
|
{
|
|
var airbag = DbContext.trade_airbag.FirstOrDefault(x => x.TradeId == tradeId);
|
|
|
|
if (airbag != null)
|
|
{
|
|
airbag.KnockInOutDate = KnockInOutDate;
|
|
airbag.KnockInOutStatus = KnockInOutStatus;
|
|
airbag.OptId = UserId;
|
|
airbag.OptName = UserName;
|
|
airbag.OptDate = DateTime.Now;
|
|
DbContext.SaveChanges();
|
|
|
|
var td = DbContext.trade.Find(tradeId);
|
|
|
|
SaveTradeOperationHistory(td, airbag.KnockInOutStatusCn);
|
|
}
|
|
|
|
return airbag;
|
|
}
|
|
}
|
|
}
|