Files
zszq-trs/YLErpDAL/Model/Trade_Self.cs
T
张名锐 13b9c2a451 refactor(Trade_Self): 优化互换交易编辑权限判断逻辑
- 提取互换事件检查条件为独立变量 hasSwapDealEvent
- 添加对平仓、互换、自动互换事件类型的检查
- 将复杂条件判断重构为更清晰的逻辑结构
- 保持原有业务逻辑不变的情况下提高代码可读性
2026-07-02 10:14:42 +08:00

644 lines
21 KiB
C#

using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using YLErp.BLL;
using YLErp.DBModels.Attributes;
using YLErp.DBModels.Helpers;
using YLErp.Helpers;
using YLErp.Models;
using YLErp.Models.Tag;
namespace YLErp.DBModels
{
[DataChange]
public partial class trade
{
/// <summary>
/// 是否允许根据交易类型设置奇异期权或互换远期的扩展字段,默认true
/// </summary>
[Newtonsoft.Json.JsonIgnore, NotMapped]
public bool EnableSetFieldsByTradeType { get; set; } = true;
/// <summary>
/// 计算ID(用于定价计算V2)
/// </summary>
[NotMapped]
public string CalcId { get; set; }
[NotMapped]
public double? TTMDays { get; set; }
[DisplayName("标的资产类型")]
[NotMapped]
public string UnderlyingInstrumentTypeCn => ConsGlobal.InstrumentType.GetDesc(UnderlyingInstrumentType);
[DisplayName("行权方式")]
[NotMapped, TradeAuditChangeMsg]
public string ExerciseModeCn
{
get { return TradeType == "收益互换" ? "" : TradeHelper.GetExerciseModeCn(ExerciseMode); }
}
[NotMapped]
public string ClientNumber { get; set; }
/// <summary>
/// 期权类型,例如:欧式香草看涨
/// </summary>
[DisplayName("期权类型")]
[NotMapped]
public string SummaryType
{
get
{
if (TradeType == "自定义交易")
{
return TradeType;
}
return ExerciseModeCn + (TradeType == "结构化交易" ? StructureType : TradeType?.Replace("期权", "")) + OptionType;
}
}
/// <summary>
/// 标的物的交易单位
/// </summary>
[NotMapped]
public string QuoteUnitSingle { get; set; }
[NotMapped]
public string QuoteUnit { get; set; }
[NotMapped]
[DataChange]
public trade_forward trade_forward { get; set; } = new trade_forward();
[NotMapped]
[DataChange]
public trade_asian_option trade_asian_option { get; set; } = new trade_asian_option();
[NotMapped]
[DataChange]
public trade_rainbow_option trade_rainbow_option { get; set; } = new trade_rainbow_option();
[NotMapped]
[DataChange]
public trade_barrier_option trade_barrier_option { get; set; } = new trade_barrier_option();
[NotMapped]
[DataChange]
public trade_risky_option trade_risky_option { get; set; } = new trade_risky_option();
[NotMapped]
[DataChange]
public trade_binary_option trade_binary_option { get; set; } = new trade_binary_option();
[NotMapped]
[DataChange]
public trade_spread_option trade_spread_option { get; set; } = new trade_spread_option();
[NotMapped]
[DataChange]
public trade_double_sharkfin_option trade_double_sharkfin_option { get; set; } = new trade_double_sharkfin_option();
[NotMapped]
[DataChange]
public trade_autocall trade_autocall { get; set; } = new trade_autocall();
[NotMapped]
[DataChange]
public trade_snowball trade_snowball { get; set; } = new trade_snowball();
[NotMapped]
[DataChange]
public trade_rangeaccrual trade_rangeaccrual { get; set; } = new trade_rangeaccrual();
[NotMapped]
[DataChange]
public trade_airbag trade_airbag { get; set; } = new trade_airbag();
[NotMapped]
[DataChange]
public trade_accumulator_option trade_accumulator_option { get; set; } = new trade_accumulator_option();
[NotMapped]
[DataChange]
public trade_swap trade_swap { get; set; } = new trade_swap();
[NotMapped]
public List<trade_swap_detail> get_trade_swap_details { get; set; } = new List<trade_swap_detail>();
[NotMapped]
public List<trade_swap_detail> pay_trade_swap_details { get; set; } = new List<trade_swap_detail>();
[NotMapped]
[DataChange]
public trade_underlying_enhance trade_underlying_enhance { get; set; } = new trade_underlying_enhance();
[NotMapped]
[DataChange]
public trade_cashflow trade_cashflow { get; set; } = new trade_cashflow();
[NotMapped]
[DataChange]
public trade_custom trade_custom { get; set; } = new trade_custom();
[NotMapped]
[DataChange]
public trade_extend trade_extend { get; set; } = new trade_extend();
/// <summary>
/// 期初持仓
/// </summary>
[NotMapped]
public List<swap_position> swap_positions { get; set; } = new List<swap_position>();
/// <summary>
/// 期初持仓
/// </summary>
[NotMapped]
public List<eod_swap_position> inital_eod_swap_positions { get; set; } = new List<eod_swap_position>();
/// <summary>
/// 实时持仓
/// </summary>
[NotMapped]
public List<eod_swap_position> eod_swap_positions { get; set; } = new List<eod_swap_position>();
[NotMapped]
public trade_initial_margin trade_Initial_Margin { get; set; } = new trade_initial_margin();
/// <summary>
/// 平仓互换事件
/// </summary>
[NotMapped]
public List<swap_flow_event> swap_Flow_Events { get; set; } = new List<swap_flow_event>();
/// <summary>
/// 交易事件
/// </summary>
[NotMapped]
public List<swap_event> swap_Events { get; set; } = new List<swap_event>();
/// <summary>
/// 框架合约估值
/// </summary>
[NotMapped]
public List<eod_swap> eod_swaps { get; set; } = new List<eod_swap>();
/// <summary>
/// 资金记录
/// </summary>
[NotMapped]
public List<ClientCashInCashOut> ClientCashInCashOutList { get; set; }=new List<ClientCashInCashOut>();
/// <summary>
/// 销售提成
/// </summary>
[NotMapped]
[DataChange]
[DisplayName("提成信息")]
public TradeSalesCommissionInfo SalesCommission { get; set; }
#region----权限控制----
public bool CanEdit()
{
//确认成交
return !(ConsTrade.TradeStatusAfterAndWithOutConfirmed.Contains(TradeStatus) || ConsTrade.审批中.Equals(TradeStatus) || HasPartialUnWind == 1 || (!PS.Config.TradeElement.IsAmendableAfterConfirm && TradeDate < valuedateBLL.ValueDate && ConsTrade.确认成交.Equals(TradeStatus)));
}
public bool SwapCanEdit()
{
var hasSwapDealEvent = swap_Events.Any(x =>
!x.Invalid
&& (x.EventType == (int)SwapEventTypeEnum.平仓
|| x.EventType == (int)SwapEventTypeEnum.互换
|| x.EventType == (int)SwapEventTypeEnum.自动互换));
//确认成交
return !(ConsTrade.TradeStatusAfterAndWithOutConfirmed.Contains(TradeStatus) || ConsTrade.审批中.Equals(TradeStatus) || UnWindDate.HasValue || hasSwapDealEvent || (!PS.Config.TradeElement.IsAmendableAfterConfirm && TradeDate < valuedateBLL.ValueDate && ConsTrade.确认成交.Equals(TradeStatus)));
}
public bool CanDelete()
{
return ConsTrade.新增待确认.Equals(TradeStatus) || ConsTrade.修改待确认.Equals(TradeStatus) || IsGroup == 1 && ConsTrade.已拒绝.Equals(TradeStatus) || (!PS.Config.IsGuoJun ? ConsTrade.确认成交.Equals(TradeStatus) : false);
}
public bool CanEditMaturityDate()
{
return (TradeStatus == ConsTrade.已到期 || TradeStatus == ConsTrade.已执行) && ExerciseDate == valuedateBLL.ValueDate;
}
public bool CanConfirm()
{
return (IsOption() || TradeType == "自定义交易" || TradeType == "收益互换" || TradeType == "现金流交易" || TradeType == "结构化产品" || IsGroup == 1) && ValidState != "InValid" && (TradeStatus == ConsTrade.新增待确认 || TradeStatus == ConsTrade.修改待确认);
}
public bool CanUnwind()
{
return (IsOption() || TradeType == "结构化交易" || TradeType == "远期" || TradeType == "现金流交易" || TradeType == "结构化产品") && TradeType != "场内期权" && ValidState != "InValid" && (TradeStatus == ConsTrade.确认成交 || TradeStatus == ConsTrade.提前终止拒绝);
}
public bool CanCustomizedTradeUnwind()
{
return TradeType == "自定义交易" && ValidState != "InValid" && (TradeStatus == ConsTrade.确认成交 || TradeStatus == ConsTrade.提前终止拒绝);
}
public bool CanSwapTradeUnwind()
{
return TradeType == "收益互换" && ValidState != "InValid" && (TradeStatus == ConsTrade.确认成交 || TradeStatus == ConsTrade.提前终止拒绝);
}
public bool CanExercise()
{
if ((IsOption() || TradeType == "结构化交易" || TradeType == "远期" || TradeType == "现金流交易") && TradeType != "场内期权" && TradeType != "区间累积期权" && ValidState != "InValid" && (ConsTrade.确认成交.Equals(TradeStatus) || ConsTrade.提前终止拒绝.Equals(TradeStatus)))
{
var sysDate = valuedateBLL.ValueDate;
if (PS.Config.Company == Configuration.CompanyEnum.厦门象屿 && SettlementType == SettlementTypeEnum.ReferencePrice)
{
sysDate = Modules.SpecialModule.XiaMenXiangYuHelper.GetRefernceValueDate(sysDate);
}
return ExerciseMode == "American" && ExerciseDate >= sysDate;
}
return false;
}
public bool CanExerciseRecheck()
{
return (IsOption() || TradeType == "结构化交易" || TradeType == "远期") && TradeType != "场内期权" && ValidState != "InValid" && TradeStatus == ConsTrade.行权待复核;
}
//是否到期交易
public bool CanExpire()
{
var sysDate = valuedateBLL.ValueDate;
var canExpire = (IsOption() || TradeType == "自定义交易" || TradeType == "结构化交易" || TradeType == "远期") && TradeType != "场内期权" && TradeType != "区间累积期权" && ValidState != "InValid" && (ConsTrade.确认成交.Equals(TradeStatus) || ConsTrade.提前终止拒绝.Equals(TradeStatus));
if (PS.Config.Company == Configuration.CompanyEnum.厦门象屿 && SettlementType == SettlementTypeEnum.ReferencePrice)
{
sysDate = Modules.SpecialModule.XiaMenXiangYuHelper.GetRefernceValueDate(sysDate);
}
return canExpire && ExerciseDate <= sysDate;
}
#endregion
[NotMapped]
public trade_cash trade_cash { get; set; }
[NotMapped]
[DisplayName("备注")]
public string RemarkInfo
{
get
{
if (PS.Config.Is国泰君安)
{
return Comments;
}
return Comments;// + (string.IsNullOrWhiteSpace(Comments) ? "" : "<br/>") + ChangeMsg;
}
}
[NotMapped]
public eod_trade eod_trade { get; set; }
public string GetDataTraceKeyId()
{
return id.ToString();
}
public trade Clone()
{
var td = (trade)MemberwiseClone();
switch (td.TradeType)
{
case "亚式期权":
td.trade_asian_option = td.trade_asian_option?.Clone();
break;
case "Risky期权":
td.trade_risky_option = td.trade_risky_option?.Clone();
break;
case "二元期权":
td.trade_binary_option = td.trade_binary_option?.Clone();
break;
case "雪球期权":
td.trade_snowball = td.trade_snowball?.Clone();
break;
case "凤凰期权":
td.trade_autocall = td.trade_autocall?.Clone();
break;
case "收益互换":
td.trade_swap = td.trade_swap?.Clone();
break;
case "现金流交易":
td.trade_cashflow = td.trade_cashflow?.Clone();
break;
default:
break;
}
td.trade_cash = td.trade_cash?.Clone();
return td;
}
/// <summary>
/// 是否默认对象
/// </summary>
public bool IsDefault()
{
return this == Default;
}
public bool HasGeneratedConfirmBook()
{
if (string.IsNullOrWhiteSpace(TradeNumber))
{
return false;
}
var dbContext = new YLContext();
var query = from td in dbContext.trade_contract_document
join tr in dbContext.trade_contract_r
on td.Code equals tr.ContractCode
where (tr.TradeId == this.id || tr.TradeId == ParentTradeId) && tr.IsValid
select td.Code;
return query.Any();
}
public bool HasUnwindAction()
{
var dbContext = new YLContext();
var childIds = dbContext.trade.Where(x => x.ParentTradeId == id && x.ValidState != "InValid").Select(x => x.id).ToList();
var hasChildUnwindTradeCash = dbContext.trade_cash.Any(x => childIds.Contains(x.TradeId) && x.ValidState != "InValid" && x.Action != ClientCashInCashOut.系统操作_期权费);
return dbContext.trade_cash_group_action.Any(x => x.TradeId == id) || hasChildUnwindTradeCash;
}
/// <summary>
/// 是否专业版雪球
/// </summary>
/// <returns></returns>
public bool IsSnowballSpecialist()
{
return TradeType == "雪球期权" && (trade_snowball?.PrepaymentUsed ?? false);
}
/// <summary>
/// 专用于赋初始值和比较是否初始值
/// </summary>
public static readonly trade Default = new trade();
/// <summary>
/// 结算金额
/// </summary>
[NotMapped]
public double? SettlementAmount { get; set; } = null;
[NotMapped, TradeAuditChangeMsg]
public DateTime? ActualExerciseDate { get; set; }
[NotMapped]
[DataChange]
public trade_swap_GJ trade_swap_gj { get; set; } = new trade_swap_GJ();
/// <summary>
/// 交易标签
/// </summary>
[NotMapped]
public List<TagDto> Tags { get; set; }
/// <summary>
/// 交易标签
/// </summary>
[NotMapped]
public string OutputTags { get; set; }
#region----object container----
public override T Get<T>()
{
var type = typeof(T);
if (type == typeof(trade_forward))
{
return this.trade_forward as T;
}
if (type == typeof(trade_asian_option))
{
return this.trade_asian_option as T;
}
if (type == typeof(trade_rainbow_option))
{
return this.trade_rainbow_option as T;
}
if (type == typeof(trade_risky_option))
{
return this.trade_risky_option as T;
}
if (type == typeof(trade_barrier_option))
{
return this.trade_barrier_option as T;
}
if (type == typeof(trade_binary_option))
{
return this.trade_binary_option as T;
}
if (type == typeof(trade_spread_option))
{
return this.trade_spread_option as T;
}
if (type == typeof(trade_double_sharkfin_option))
{
return this.trade_double_sharkfin_option as T;
}
if (type == typeof(trade_autocall))
{
return this.trade_autocall as T;
}
if (type == typeof(trade_snowball))
{
return this.trade_snowball as T;
}
if (type == typeof(trade_rangeaccrual))
{
return this.trade_rangeaccrual as T;
}
if (type == typeof(trade_airbag))
{
return this.trade_airbag as T;
}
if (type == typeof(trade_accumulator_option))
{
return this.trade_accumulator_option as T;
}
if (type == typeof(trade_swap))
{
return this.trade_swap as T;
}
if (type == typeof(trade_underlying_enhance))
{
return this.trade_underlying_enhance as T;
}
if (type == typeof(trade_cashflow))
{
return this.trade_cashflow as T;
}
if (type == typeof(trade_custom))
{
return this.trade_custom as T;
}
if (type == typeof(trade_cash))
{
return this.trade_cash as T;
}
throw new NotSupportedException();
}
public override void Set<T>(T data)
{
if (data is trade_forward forward)
{
this.trade_forward = forward;
}
if (data is trade_asian_option asian_Option)
{
this.trade_asian_option = asian_Option;
}
if (data is trade_risky_option risky_Option)
{
this.trade_risky_option = risky_Option;
}
if (data is trade_rainbow_option rainbow_Option)
{
this.trade_rainbow_option = rainbow_Option;
}
if (data is trade_barrier_option barrier_Option)
{
this.trade_barrier_option = barrier_Option;
}
if (data is trade_binary_option binary_Option)
{
this.trade_binary_option = binary_Option;
}
if (data is trade_spread_option spread_Option)
{
this.trade_spread_option = spread_Option;
}
if (data is trade_double_sharkfin_option dbshark)
{
this.trade_double_sharkfin_option = dbshark;
}
if (data is trade_autocall autocall)
{
this.trade_autocall = autocall;
}
if (data is trade_snowball snowball)
{
this.trade_snowball = snowball;
}
if (data is trade_rangeaccrual rangeaccrual)
{
this.trade_rangeaccrual = rangeaccrual;
}
if (data is trade_airbag airbag)
{
this.trade_airbag = airbag;
}
if (data is trade_accumulator_option accumulator_Option)
{
this.trade_accumulator_option = accumulator_Option;
}
if (data is trade_swap swap)
{
this.trade_swap = swap;
}
if (data is trade_underlying_enhance underlying_Enhance)
{
this.trade_underlying_enhance = underlying_Enhance;
}
if (data is trade_cashflow cashflow)
{
this.trade_cashflow = cashflow;
}
if (data is trade_custom custom)
{
this.trade_custom = custom;
}
if (data is trade_cash cash)
{
this.trade_cash = cash;
}
throw new NotSupportedException();
}
#endregion
}
[NotMapped]
public class tradeDto : trade
{
}
/// <summary>
/// 是否单独生成交易确认书
/// </summary>
public class EnumSingleContract
{
//单笔
public const int Single = 1;
//批量
public const int Batch = 0;
}
public class EnumTradeBuySell
{
//单笔
public const string Buy = "买入";
//批量
public const string Sell = "卖出";
}
[NotMapped]
public class trade_swap_GJ
{
public string LongShort { get; set; }
public double? OpenPrice { get; set; }
public double? OpenCurrencyRate { get; set; }
public double? TradeCommission { get; set; }
public double? PricingOriginalStockEqvNotional { get; set; }
public double? PricingStockEqvNotional { get; set; }
public string SwapTimeAndRate { get; set; }
}
}