253 lines
12 KiB
C#
253 lines
12 KiB
C#
using Qdp.Pricing.Library.Options.Products.Asian;
|
|
using YLErp.DBModels.Helpers;
|
|
using YLErp.Enums;
|
|
using YLErp.Modules.CalculationModule;
|
|
using YLErp.Modules.DataProviderModule;
|
|
using YLErp.Modules.SalesModule;
|
|
using YLErp.Modules.TagModule;
|
|
using YLErp.Modules.TradeDalModule;
|
|
using YLErp.Modules.TradeModule;
|
|
|
|
namespace YLErp.Web.Controllers
|
|
{
|
|
public abstract class OtcTradeControllerBase : BaseController
|
|
{
|
|
public virtual ActionResult TradeView(string enid, bool isFromPositionReport = false, bool isOnlyCloseButton = false, string operationStatus = "")
|
|
{
|
|
ViewBag.BinaryCalculation = valuedateBLL.BinaryCalculation;
|
|
|
|
var intid = DecryptInt(enid);
|
|
|
|
var tradeObj = yldb.trade.Find(intid);
|
|
|
|
if (tradeObj == null)
|
|
{
|
|
return ShowError("没有找到交易数据");
|
|
}
|
|
|
|
tradeBLL.SetFieldsByTradeType(tradeObj);
|
|
|
|
TradeViewModel model;
|
|
|
|
//如果是结构化主交易则转成第一个子交易显示
|
|
if (tradeObj.TradeType == "结构化交易" && tradeObj.IsGroup == 0)
|
|
{
|
|
tradeObj = yldb.trade.FirstOrDefault(c => c.ParentTradeId == tradeObj.id);
|
|
}
|
|
|
|
var hasTradeProcess = HasTradeProcess();
|
|
|
|
tradeObj.MetaDic = new TradeMetaService(CurUser).GetTradeMeta(tradeObj.id);
|
|
|
|
if (tradeObj.MetaDic.ContainsKey("ActualExerciseDate") && DateTime.TryParse(tradeObj.MetaDic["ActualExerciseDate"],out DateTime newActualExerciseDate))
|
|
{
|
|
tradeObj.ActualExerciseDate = newActualExerciseDate;
|
|
}
|
|
model = new TradeViewModel(tradeObj)
|
|
{
|
|
IsFromPositionReport = isFromPositionReport,
|
|
BinaryCalculation = valuedateBLL.BinaryCalculation,
|
|
IsOnlyCloseButton = isOnlyCloseButton,
|
|
OperationStatus = operationStatus
|
|
};
|
|
if (model.Trade.trade_autocall != null && model.Trade.TradeType == "凤凰期权")
|
|
{
|
|
var koInfo = TradeObservationHelper.GetAutocallKOObservationAndCoupon(model.Trade.trade_autocall.KOObservationDates, model.Trade.trade_autocall.CouponBarrier);
|
|
model.Trade.trade_autocall.CouponObservation = koInfo.Item1;
|
|
model.Trade.trade_autocall.KOObservationDates = string.IsNullOrWhiteSpace(koInfo.Item2) ? null : koInfo.Item2;
|
|
}
|
|
|
|
|
|
//获取结构化交易伙伴交易
|
|
if (tradeObj.ParentTradeId > 0 && tradeObj.IsGroup == 0)
|
|
{
|
|
model.SubTrades = yldb.trade.AsNoTracking().Where(n => n.ParentTradeId == tradeObj.ParentTradeId)
|
|
.Select(t => new OtcTradeDto { id = t.id, BuySell = t.BuySell }).ToArray();
|
|
}
|
|
|
|
//获取交易现金数据
|
|
var tradeWithSettlement = new TradeDalService(CurUser).GetTradeWithSettlementTradeCash(tradeObj);
|
|
|
|
//获取交易销售提成数据
|
|
model.SalesCommission = new SalesCommissionDataService(CurUser).GetSalesCommissionInfoDtos(intid);
|
|
if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1")
|
|
{
|
|
foreach (var item in model.SalesCommission)
|
|
{//为了迁就前端逻辑,前端展示时只取第一个;
|
|
item.Commission = item.Commission * model.SalesCommission.Count();
|
|
}
|
|
}
|
|
model.ClientCashInCashOutList = yldb.ClientCashInCashOut.Where(c => c.TradeId == intid && c.ValidState != ConsGlobal.InValid).ToList();
|
|
model.unWindTradeCashList = tradeWithSettlement.UnwindTradeCashList;
|
|
model.unwindChildrenTradeCashList = tradeWithSettlement.UnwindChildrenTradeCashList;
|
|
model.maturityTradeCash = tradeWithSettlement.MaturityTradeCash;
|
|
model.swapTradeCashList = tradeWithSettlement.SwapTradeCashList;
|
|
model.couponTradeCashList = tradeWithSettlement.CouponTradeCashList;
|
|
model.tradeMarginTemplates = new TradeQueryService(CurUser).SearchTradeMarginTemplateList(intid);
|
|
model.canEditMaturityDate = tradeObj.CanEditMaturityDate() && model.maturityTradeCash != null && CurUser.交易管理_到期修改;
|
|
//需要审批或者复核的交易都会显示行权审核提交按钮
|
|
model.IsShowReCheckClose = ((valuedateBLL.SystemDate.CloseReCheck == 1) ||
|
|
(valuedateBLL.SystemDate.CloseReApprove == 1 && hasTradeProcess)) && tradeObj.TradeStatus != ConsTrade.平仓待复核;
|
|
model.CanEdit = tradeObj.CanEdit() && !isFromPositionReport && CurUser.交易管理_交易编辑;
|
|
|
|
|
|
|
|
using (var tagService = new TagService(CurUser))
|
|
{
|
|
model.Tags = tagService.GetTagByTradeId(intid);
|
|
}
|
|
|
|
using (var tagService = new TagService(CurUser))
|
|
{
|
|
ViewBag.TagList = tagService.GetTagListByType(TagTypeEnum.Trade);
|
|
}
|
|
if (tradeObj.TradeType == "远期")
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(tradeObj.OptionType))
|
|
{
|
|
tradeObj.OptionType = (tradeObj.OptionType == "看涨") ? "多头" : "空头";
|
|
}
|
|
if (!string.IsNullOrWhiteSpace(tradeObj.BasisUnderlyingCode))
|
|
{
|
|
ViewBag.Underlying2Name = DataCacheProvider.GetUnderlyingDataSource().GetData(tradeObj.BasisUnderlyingCode)?.UnderlyingName;
|
|
}
|
|
|
|
if (model.Trade.Comments!=null && model.Trade.Comments.Contains("累计期权"))
|
|
{
|
|
model.Trade.AccumulatorOptionId = yldb.trade.FirstOrDefault(l => l.TradeNumber == model.Trade.Comments.Replace("累计期权:", ""))?.EncryptId;
|
|
}
|
|
return View("~/Views/ForwardTrade/TradeView.cshtml", model);
|
|
}
|
|
|
|
if (model.maturityTradeCash != null)
|
|
{
|
|
//对于历史过期交易到期的数据做一下处理;
|
|
//最新的到期交易,ValueDate不会大于ExerciseDate;
|
|
//敲出的交易,ValueDate会小于ExerciseDate。
|
|
model.maturityTradeCash.ValueDate = model.maturityTradeCash.ValueDate > tradeObj.ExerciseDate.Value ? tradeObj.ExerciseDate.Value : model.maturityTradeCash.ValueDate;
|
|
}
|
|
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(tradeObj.UnderlyingCode);
|
|
if (um != null)
|
|
{
|
|
model.Trade.UnderlyingInstrumentType = um?.UnderlyingInstrumentType;
|
|
model.Trade.QuoteUnitSingle = ConsGlobal.InstrumentType.Stock.Equals(um?.UnderlyingInstrumentType) ? "元/股" : ("元/" + um.QuoteUnitString);
|
|
model.Trade.QuoteUnit = um.QuoteUnit;
|
|
//方顿 JD TradeUnit 录的是 千克 数量是用 吨 计算的
|
|
model.Trade.TradeUnit = um.QuoteUnit == "500千克" ? "吨" : um.TradeUnit;
|
|
model.Trade.CountRatio = um.CountRatio;
|
|
model.Trade.TradeAmount = model.Trade.Notional / um.CountRatio;
|
|
|
|
var v = DataCacheProvider.GetVarietyDataSource().GetData(um.UnderlyingTypeId);
|
|
model.Trade.QuoteCurrency = v != null ? v.QuoteCurrency : "";
|
|
|
|
}
|
|
|
|
SetTradeExtendForView(model);
|
|
|
|
if (model.CanEdit && tradeObj.ParentTradeId > 0)
|
|
{
|
|
var subTrades = yldb.trade.AsNoTracking().Where(n => n.ParentTradeId == tradeObj.ParentTradeId && n.id != tradeObj.id).ToArray();
|
|
model.CanEdit &= subTrades.All(t => t.CanEdit());
|
|
}
|
|
|
|
double exchangeRate = 0;
|
|
|
|
if (PS.Config.Company == Configuration.CompanyEnum.中粮 && !string.IsNullOrEmpty(model.Trade.QuoteCurrency) && !"CNY".Equals(model.Trade.QuoteCurrency)
|
|
&& model.Trade.OriginalStockEqvNotionalV2 != null && model.Trade.MetaDic.ContainsKey("ExchangeRate")
|
|
&& double.TryParse(model.Trade.MetaDic["ExchangeRate"], out exchangeRate))
|
|
{
|
|
model.OriginalStockEqvNotionalV2MultipleExchangeRate = ((double)model.Trade.OriginalStockEqvNotionalV2 * exchangeRate).OtcFormat(OtcFormatFlag.StockEqvNotional);
|
|
}
|
|
|
|
if (model.Trade.trade_accumulator_option != null && model.Trade.TradeType == "累计期权" && model.autoCallObsercationList.Where(l => !string.IsNullOrWhiteSpace(l.ConvTradeNumber)).Any())
|
|
{
|
|
|
|
model.autoCallObsercationList.Where(l => !string.IsNullOrWhiteSpace(l.ConvTradeNumber)).ToList().ForEach(o => o.ConvForwardTradeId = yldb.trade.FirstOrDefault(l => l.TradeNumber == o.ConvTradeNumber)?.EncryptId);
|
|
}
|
|
return View("~/Views/Trade/TradeView.cshtml", model);
|
|
}
|
|
|
|
|
|
//交易数据扩展
|
|
private void SetTradeExtendForView(TradeViewModel model)
|
|
{
|
|
var tradeObj = model.Trade;
|
|
|
|
switch (tradeObj.TradeType)
|
|
{
|
|
case "凤凰期权":
|
|
case "累计期权":
|
|
case "区间累积期权":
|
|
{
|
|
model.autoCallObsercationList = yldb.autocall_observation.Where(x => x.TradeId == tradeObj.id)
|
|
.OrderBy(n => n.EndDate).ToList();
|
|
break;
|
|
}
|
|
case "雪球期权":
|
|
{
|
|
try
|
|
{
|
|
model.autoCallObsercationList = new TradeSnowballService(CurUser).GetObservations(tradeObj.id, valuedateBLL.ValueDate);
|
|
if (model.autoCallObsercationList != null)
|
|
{
|
|
var tc = yldb.trade_cash.Where(c => c.TradeId == tradeObj.id && c.Action == ClientCashInCashOut.系统操作_票息 && !c.IsDeleted).FirstOrDefault();
|
|
model.autoCallObsercationList.ForEach(x =>
|
|
{
|
|
if (tc != null)
|
|
{
|
|
//tc的Amount包含了年化权利金,PaymentAmount代表的是票息,从detail获取
|
|
var detail = yldb.trade_cash_detail.Where(y => y.TradeCashId == tc.id && y.Action == ClientCashInCashOut.系统操作_票息).FirstOrDefault();
|
|
if (detail != null)
|
|
{
|
|
x.PaymentAmount = detail.Amount.Value;
|
|
}
|
|
else
|
|
{
|
|
x.PaymentAmount = TradeHelper.GetAmountByPaymentAmount(x.PaymentAmount, tradeObj.PrincipalSum(), tradeObj.BuySell);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
x.PaymentAmount = TradeHelper.GetAmountByPaymentAmount(x.PaymentAmount, tradeObj.PrincipalSum(), tradeObj.BuySell);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ViewBag.Error = ex.Message;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Final Price赋值
|
|
if (tradeObj.TradeStatus != ConsTrade.确认成交 || tradeObj.ExerciseDate == null)
|
|
{
|
|
return;
|
|
}
|
|
if (tradeObj.TradeType != "现金流交易")
|
|
{
|
|
model.ClosePrice = EodPriceQueryService.GetClosePrice(tradeObj.ExerciseDate.Value, tradeObj.UnderlyingCode);
|
|
tradeObj.FinalPrice = model.ClosePrice;
|
|
}
|
|
|
|
if (tradeObj.TradeType == "亚式期权" && tradeObj.trade_asian_option != null
|
|
&& tradeObj.trade_asian_option.StrikeType != "Floating"
|
|
&& tradeObj.trade_asian_option.AveragingPeriodStartDate < valuedateBLL.ValueDate)
|
|
{
|
|
var QdpTrade = TradeCalcHelper.GetQdpTrade(tradeObj);
|
|
if (QdpTrade.Instrument is AsianOption asianOpt && asianOpt.Fixings?.Count > 0)
|
|
{
|
|
tradeObj.FinalPrice = asianOpt.FinalPrice();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected bool HasTradeProcess()
|
|
{
|
|
return yldb.approvalprocess.Where(t => t.processType == "TradeProcess").Any();
|
|
}
|
|
}
|
|
} |