Files
zszq-trs/YLErpDAL/Modules/ExchangeOptionTradeModule/ExchangeOptionSettlementService.cs
T
2024-05-09 14:06:26 +08:00

217 lines
8.3 KiB
C#

using System.Text;
using YLErp.Model;
using YLErp.Modules.CalculationModule;
namespace YLErp.Modules.ExchangeOptionTradeModule
{
/// <summary>
/// 场内期权交易结算服务
/// </summary>
public class ExchangeOptionSettlementService : YLBaseService
{
/// <summary>
/// 开仓类型
/// </summary>
private readonly string[] openTypes = new[] { "空头开仓", "多头开仓" };
/// <summary>
/// 平仓类型
/// </summary>
private readonly string[] closeTypes = new[] { "空头平仓", "多头平仓" };
public ExchangeOptionSettlementService(OptUserInfo optUser) : base(optUser)
{
}
/// <summary>
/// 执行结算
/// </summary>
public void Execute(DateTime valueDate)
{
RebackOption(valueDate);
SaveOpenTrade(valueDate);
SaveCloseTrade(valueDate);
CloseMaturityTrade(valueDate);
}
/// <summary>
/// 回滚操作
/// </summary>
private void RebackOption(DateTime valueDate)
{
Exchange_Option_Trade tt;
var tableName = DbContext.GetTableName<Exchange_Option_Trade>();
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());
}
/// <summary>
/// 关掉过期合约
/// </summary>
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();
}
/// <summary>
/// 保存开仓交易
/// </summary>
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();
}
}
/// <summary>
/// 保存平仓交易
/// </summary>
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();
}
}
}
}
}