using System.Text; using YLErp.Model; using YLErp.Modules.CalculationModule; namespace YLErp.Modules.ExchangeOptionTradeModule { /// /// 场内期权交易结算服务 /// public class ExchangeOptionSettlementService : YLBaseService { /// /// 开仓类型 /// private readonly string[] openTypes = new[] { "空头开仓", "多头开仓" }; /// /// 平仓类型 /// private readonly string[] closeTypes = new[] { "空头平仓", "多头平仓" }; public ExchangeOptionSettlementService(OptUserInfo optUser) : base(optUser) { } /// /// 执行结算 /// public void Execute(DateTime valueDate) { RebackOption(valueDate); SaveOpenTrade(valueDate); SaveCloseTrade(valueDate); CloseMaturityTrade(valueDate); } /// /// 回滚操作 /// private void RebackOption(DateTime valueDate) { Exchange_Option_Trade tt; var tableName = DbContext.GetTableName(); var valueDateStr = valueDate.ToString("yyyy-MM-dd"); var sb = new StringBuilder(500); sb.AppendFormat("delete from {0} where {1}>='{2}';", tableName, nameof(tt.TradeDate), valueDateStr) .AppendLine() .Append("update ").Append(tableName).Append(" set ") .Append(nameof(tt.TradeStatus)).Append("='确认成交',") .Append(nameof(tt.ExerciseDate)).Append("='0001-01-01',") .Append(nameof(tt.ExercisePrice)).Append("=0,") .Append(nameof(tt.ExerciseServiceFee)).Append("=0 ") .Append(" where ") .Append(nameof(tt.ExerciseDate)).Append(">='").Append(valueDateStr).Append("';"); DbContext.Database.ExecuteSqlRaw(sb.ToString()); } /// /// 关掉过期合约 /// private void CloseMaturityTrade(DateTime date) { var startDate = date.AddYears(-2); var exchangeOptionTrade = DbContext.exchange_list_option; var query = from t in DbContext.Exchange_Option_Trade join e in DbContext.exchange_list_option on t.Code equals e.ContractCode where t.TradeDate > startDate && t.TradeStatus == "确认成交" && e.MaturityDate <= date select t; var trades = query.ToList(); foreach (var item in trades) { item.TradeStatus = "已平仓"; item.ExerciseDate = date; item.ExercisePrice = 0; item.ExerciseServiceFee = 0; } DbContext.SaveChanges(); } /// /// 保存开仓交易 /// private void SaveOpenTrade(DateTime date) { var trades = DbContext.ExchangeTrade .Where(t => t.TradeDate == date && t.TradeType == "场内期权" && t.IsValid && openTypes.Contains(t.TradeSide)).ToList(); var result = new ExchangeTradeCommissionCalc().GetTradeCommission(trades); var items = trades.Where(t => t.TradeType == "场内期权" && t.IsValid && openTypes.Contains(t.TradeSide)) .Select(t => new Exchange_Option_Trade() { Code = t.OptionCode, //AssetBookName = t.AssetBookName, AssetId = t.AssetBookId, CreateDate = DateTime.Now, ExerciseDate = DateTime.MinValue, ExerciseMode = t.ExerciseMode, ExercisePrice = 0, TradeAmount = t.TradeAmount, //TradeUnitValue = GetTradeUnitValue(t.TradeUnit) ?? 0, //TradeUnit = Regex.Match(t.TradeUnit, @"(?<=\d)\D+").Value, ServiceFee = result.GetTradeCommission(t.id), OptionType = t.OptionType, Strike = t.OptionStrike ?? 0, TradeDate = t.TradeDate, TradePrice = t.TradeSinglePrice * t.Notional, TraderId = t.TraderId, TraderName = t.TraderName, TradeStatus = "确认成交", TradeType = t.TradeSide == "空头开仓" ? "空头" : "多头", UnderlyingCode = t.UnderlyingCode }).ToList(); if (items.Count > 0) { foreach (var item in items) { var un = UnderlyingDataProvider.GetUnderlying(item.UnderlyingCode); if (un != null) { item.TradeUnitValue = un.ContractSize; item.TradeUnit = un.TradeUnitString; } else { item.TradeUnit = "吨"; //为了收盘通过暂时增加这行代码 } item.AssetBookName = DataCacheProvider.GetAssetUnitDataSource().GetData(item.AssetId)?.Name; } DbContext.Exchange_Option_Trade.AddRange(items); DbContext.SaveChanges(); } } /// /// 保存平仓交易 /// private void SaveCloseTrade(DateTime date) { var trades = DbContext.ExchangeTrade.Where(t => t.TradeDate == date && t.TradeType == "场内期权" && t.IsValid && closeTypes.Contains(t.TradeSide)).ToList(); var result = new ExchangeTradeCommissionCalc().GetTradeCommission(trades); foreach (var close in trades) { var tradeType = ""; switch (close.TradeSide) { case "多头平仓": tradeType = "多头"; break; case "空头平仓": tradeType = "空头"; break; } var tradeAmount = close.TradeAmount; var singlePrice = close.TradeSinglePrice; var singleServiceFee = result.GetTradeCommission(close.id) / tradeAmount; var openInfos = (from exchange in DbContext.Exchange_Option_Trade where exchange.TradeStatus == "确认成交" && exchange.Code == close.OptionCode && exchange.TradeType == tradeType orderby exchange.TradeDate select exchange) .ToList(); foreach (var open in openInfos) { if (tradeAmount == 0) { break; } if (open.TradeAmount > tradeAmount) { var newTrade = open.Clone(); newTrade.id = 0; newTrade.TradeAmount = open.TradeAmount - tradeAmount; newTrade.TradePrice = open.TradePrice / open.TradeAmount * newTrade.TradeAmount; newTrade.ServiceFee = open.ServiceFee / open.TradeAmount * newTrade.TradeAmount; DbContext.Exchange_Option_Trade.Add(newTrade); open.TradePrice = open.TradePrice / open.TradeAmount * tradeAmount; open.TradeAmount = tradeAmount; tradeAmount = 0; } else { tradeAmount = tradeAmount - open.TradeAmount; } open.ExerciseDate = close.TradeDate; open.ExercisePrice = singlePrice * open.TradeAmount; open.ExerciseServiceFee = singleServiceFee * open.TradeAmount; open.TradeStatus = "已平仓"; DbContext.SaveChanges(); } } } } }