217 lines
8.3 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|