Files
zszq-trs/YLErpDAL/Modules/EodModule/SettlementModule/EodHandleSwapFlowService.cs
T

1251 lines
72 KiB
C#

using YLErp.BLL;
using YLErp.CustomizedBizLogic;
using YLErp.DBModels.Consts;
using YLErp.DBModels.Enums;
using YLErp.Enums;
using YLErp.Model;
using YLErp.Model.Enum;
using YLErp.Models;
using YLErp.Modules.CalculationModule;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.TradeModule;
using YLErp.Modules.TradeModule.DealModule;
using YLErp.Modules.TradeModule.OrderModule;
using YLErp.QdpModule;
namespace YLErp.Modules.EodModule
{
/// <summary>
/// 日终结算服务
/// </summary>
public class EodHandleSwapFlowService : TradeServiceBase
{
public EodHandleSwapFlowService(OptUserInfo userInfo) : base(userInfo)
{
}
public void ComposeGroupTrade(string tradeNumber)
{
using (var trans = BeginTransaction())
{
var tradeNumbers = DbContext.trade_swap_flow.Where(x => x.TradeDate == valuedateBLL.ValueDate && x.TradeNumber != null && x.TradeNumber != "").Select(x => x.TradeNumber).Distinct().ToList();
if (!string.IsNullOrWhiteSpace(tradeNumber))
{
tradeNumbers = tradeNumbers.Where(x => x == tradeNumber).ToList();
}
if (tradeNumbers.Any())
{
var flows = DbContext.trade_swap_flow.Where(x => x.TradeDate == valuedateBLL.ValueDate && tradeNumbers.Contains(x.TradeNumber)).ToList();
tradeNumbers.ForEach(x =>
{
var hasNoPosition = true;
var originalTrade = DbContext.trade.FirstOrDefault(y => y.TradeNumber == x);
if (originalTrade == null)
{
throw new ServiceException($"未找到该交易编号:{x}");
}
else
{
var client = DataCacheProvider.GetClientDataSource().GetData(originalTrade.ClientId);
if (!client.DerivativesInvestmentVarieties.Contains((int)DerivativesInvestmentVarietiesEnum.场外互换 + ""))
{
throw new ServiceException($"客户:{client.Name}未设置交易种类“场外互换”,无法生成互换交易!");
}
var tradeFlows = flows.Where(y => y.TradeNumber == x).ToList();
#region 还原之前收盘产生的历史数据
var originalTradeId = originalTrade.id;
//获取收盘日当天已经生成的交易,需要先做删除,再重新生成
var todayTradeIds = (from td in DbContext.trade.Where(y => y.TradeDate == valuedateBLL.ValueDate && y.ValidState != "InValid")
join swap in DbContext.trade_swap.Where(y => y.OriginalTradeId == originalTradeId && y.SwapType == "普通")
on td.id equals swap.TradeId
select td.id).ToList();
if (todayTradeIds.Any())
{
todayTradeIds.ForEach(y =>
{
new TradeInvalidService(this).InvalidTrade(y, false);
});
var tradeSwapDetails = DbContext.trade_swap_detail.Where(y => todayTradeIds.Contains(y.ChildTradeId));
DbContext.trade_swap_detail.RemoveRange(tradeSwapDetails);
DbContext.SaveChanges();
}
//对当天主交易做初始化处理
var todayParentTradesIds = (from td in DbContext.trade.Where(y => y.TradeDate == valuedateBLL.ValueDate && y.ParentTradeId == 0 && y.ValidState != "InValid")
join swap in DbContext.trade_swap.Where(y => y.SwapType == "多空组合")
on td.id equals swap.TradeId
where td.id == originalTradeId || swap.OriginalTradeId == originalTradeId
select td.id).ToList();
if (todayParentTradesIds.Any())
{
var todayParentTrades = DbContext.trade.Where(y => todayParentTradesIds.Contains(y.id)).ToList();
todayParentTrades.ForEach(y =>
{
y.TradeStatus = "确认成交";
y.StockEqvNotional = 0;
y.OriginalStockEqvNotional = 0;
y.StockEqvNotionalReal = 0;
y.TradePrice = 0;
});
DbContext.SaveChanges();
}
var preTradeDate = (from td in DbContext.trade.Where(y => y.TradeDate < valuedateBLL.ValueDate && y.ParentTradeId > 0 && y.ValidState != "InValid")
join swap in DbContext.trade_swap.Where(y => y.OriginalTradeId == originalTradeId)
on td.id equals swap.TradeId
select td.TradeDate).ToList().Max();
var preTradeDateTradeIds = (from td in DbContext.trade.Where(y => y.TradeDate == preTradeDate && y.ParentTradeId > 0 && y.ValidState != "InValid")
join swap in DbContext.trade_swap.Where(y => y.OriginalTradeId == originalTradeId)
on td.id equals swap.TradeId
select td.id).ToList();
if (preTradeDateTradeIds.Any())
{
preTradeDateTradeIds.ForEach(y =>
{
new TradeBackService(this).Execute(y, true, TradeBackActionEnum.backTrade);
});
}
#endregion
#region 生成新的开平仓记录
var preTradeDateTrades = (from td in DbContext.trade.Where(y => y.TradeDate == preTradeDate && y.ParentTradeId > 0 && y.ValidState != "InValid")
join swap in DbContext.trade_swap.Where(y => y.OriginalTradeId == originalTradeId)
on td.id equals swap.TradeId
select new { td, swap }).ToList();
//前一天存在持仓的场景
//先平仓再开仓的情景时,只有完全平仓的子交易:合成的流水手续费记为平仓手续费,存在持仓的子交易:合成的流水手续费记为开仓手续费。
if (preTradeDateTrades.Any())
{
var newParentTradeId = 0;
//对前一天的持仓标的做先平仓后开仓处理
preTradeDateTrades.ForEach(y =>
{
var notional = (y.swap.IsPayFloatingProfit ? y.swap.PayNotional : y.swap.GetNotional) ?? 0;
var longShort = y.swap.IsPayFloatingProfit ? y.swap.PayLongShort : y.swap.GetLongShort;
var spotPrice = (y.swap.IsPayFloatingProfit ? y.swap.PaySpotPrice : y.swap.GetSpotPrice) ?? 0;
y.td.trade_swap = y.swap;
var totalNotional = notional * (longShort == "多头" ? 1 : -1);
var totalSpotPrice = totalNotional * spotPrice;
var underlyingTradeFlows = tradeFlows.Where(z => z.UnderlyingCode == y.td.UnderlyingCode);
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(y.td.UnderlyingCode);
var sumBuyLots = underlyingTradeFlows.Sum(z => z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0));
if (sumBuyLots > 0)
{
var sumBuyNotional = sumBuyLots * underlying.ContractSize;
totalNotional += sumBuyNotional;
var totalBuySpotPrice = underlyingTradeFlows.Sum(z => z.Lots * underlying.ContractSize * (z.SpotPrice ?? 0) * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0));
totalSpotPrice += totalBuySpotPrice;
}
var sumSellLots = underlyingTradeFlows.Sum(z => z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0));
if (sumSellLots > 0)
{
var sumSellNotional = sumSellLots * underlying.ContractSize;
totalNotional -= sumSellNotional;
var totalSellSpotPrice = underlyingTradeFlows.Sum(z => z.Lots * underlying.ContractSize * (z.SpotPrice ?? 0) * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0));
totalSpotPrice -= totalSellSpotPrice;
}
var totalFee = underlyingTradeFlows.Sum(z => z.NeedCostFee ? (z.SingleFee != null ? (z.SingleFee.Value * z.Lots) : (z.UnAnnualRate * z.Lots * z.SpotPrice * underlying.ContractSize ?? 0)) : 0);
//当天该标的完全平仓
if (totalNotional == 0)
{
y.td.UnWindDate = valuedateBLL.ValueDate;
y.td.FinalPrice = spotPrice + totalSpotPrice * (longShort == "多头" ? -1 : 1) / notional;
UnwindSwapTradeCashHandle(y.td, "平仓", null, totalFee);
}
//当天还存在持仓,需要先平仓,再开仓
else
{
#region 平仓
y.td.UnWindDate = valuedateBLL.ValueDate;
//假设先用收盘价将当前的剩余份额平仓掉,再用收盘价重新开仓剩余份额
var fillNotional = -totalNotional;
EodPrice eodPrice = null;
new EodPriceProvider(valuedateBLL.ValueDate, false).TryGetEodPrice(y.td.UnderlyingCode, out eodPrice);
var closePrice = eodPrice?.ClosePrice ?? underlying.Price ?? 0;
totalSpotPrice += fillNotional * closePrice;
y.td.FinalPrice = spotPrice + totalSpotPrice * (longShort == "多头" ? -1 : 1) / notional;
UnwindSwapTradeCashHandle(y.td, "平仓", null, 0);
#endregion
#region 重新开仓
var flow = new trade_swap_flow()
{
UnderlyingCode = y.td.UnderlyingCode,
TradeDate = valuedateBLL.ValueDate,
StartDate = valuedateBLL.ValueDate,
ExerciseDate = y.td.ExerciseDate,
QuoteCurrency = y.td.QuoteCurrency,
SettlementDate = y.td.SettlementDate,
SingleFee = y.swap.IsPayFloatingProfit ? y.swap.GetSingleFee : y.swap.PaySingleFee,
UnAnnualRate = y.swap.IsPayFloatingProfit ? y.swap.GetUnAnnualRate : y.swap.PayUnAnnualRate,
TradeNumber = x
};
flow.Lots = Math.Abs(totalNotional / underlying.ContractSize);
flow.BuySell = totalNotional > 0 ? "买入" : "卖出";
flow.SpotPrice = closePrice;
var trade = MapSwapTradeHandle(flow, false);
InnerSaveSwapTrade(trade, totalFee);
if (newParentTradeId == 0 && trade.ParentTradeId > 0)
{
newParentTradeId = trade.ParentTradeId;
}
hasNoPosition = false;
#endregion
}
});
//对当天新的标的流水处理
var underlyingCodes = preTradeDateTrades.Select(y => y.td.UnderlyingCode).Distinct().ToList();
var tradeFlowsUnderlyingGroupNew = GetTradeFlowsUnderlyingGroup(tradeFlows.Where(y => !underlyingCodes.Contains(y.UnderlyingCode)));
tradeFlowsUnderlyingGroupNew.ForEach(y =>
{
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(y.UnderlyingCode);
var underlyingTradeFlows = tradeFlows.Where(z => z.UnderlyingCode == y.UnderlyingCode).ToList();
double buyTotalFee = 0d;
double sellTotalFee = 0d;
double totalFee = 0d;
underlyingTradeFlows.ForEach(z =>
{
if (z.NeedCostFee)
{
if (z.SingleFee == null && z.UnAnnualRate == null)
{
var varitey = DataCacheProvider.GetVariety(y.UnderlyingCode);
var clientVarietyConfig = DbContext.client_variety_config.Where(o => o.ClientId == client.id && o.VarietyId == varitey.id && o.ValueDate <= y.flow.TradeDate).OrderByDescending(o => o.ValueDate).FirstOrDefault();
if (clientVarietyConfig == null)
{
throw new ServiceException($"该客户[{client.Name}]需要维护品种[{varitey.VarietyCode}]在[{y.flow.TradeDate}]相关的收费参数配置");
}
buyTotalFee += clientVarietyConfig.SingleFee > 0 ? (clientVarietyConfig.SingleFee * z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0)) : (clientVarietyConfig.UnAnnualRate * z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0) * z.SpotPrice * underlying.ContractSize ?? 0);
sellTotalFee += clientVarietyConfig.SingleFee > 0 ? (clientVarietyConfig.SingleFee * z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0)) : (clientVarietyConfig.UnAnnualRate * z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0) * z.SpotPrice * underlying.ContractSize ?? 0);
totalFee += clientVarietyConfig.SingleFee > 0 ? (z.SingleFee.Value * z.Lots) : (z.UnAnnualRate * z.Lots * z.SpotPrice * underlying.ContractSize ?? 0);
}
else
{
buyTotalFee += z.SingleFee != null ? (z.SingleFee.Value * z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0)) : (z.UnAnnualRate * z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0) * z.SpotPrice * underlying.ContractSize ?? 0);
sellTotalFee += z.SingleFee != null ? (z.SingleFee.Value * z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0)) : (z.UnAnnualRate * z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0) * z.SpotPrice * underlying.ContractSize ?? 0);
totalFee += z.SingleFee != null ? (z.SingleFee.Value * z.Lots) : (z.UnAnnualRate * z.Lots * z.SpotPrice * underlying.ContractSize ?? 0);
}
}
});
//当天新增的标的,买卖手数合成为0,即持仓数为0,新增一笔普通互换,然后当天平仓平掉
if (y.Lots == 0)
{
buyTotalFee = underlyingTradeFlows.Sum(z => z.NeedCostFee ? (z.SingleFee != null ? (z.SingleFee.Value * z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0)) : (z.UnAnnualRate * z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0) * z.SpotPrice * underlying.ContractSize ?? 0)) : 0);
sellTotalFee = underlyingTradeFlows.Sum(z => z.NeedCostFee ? (z.SingleFee != null ? (z.SingleFee.Value * z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0)) : (z.UnAnnualRate * z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0) * z.SpotPrice * underlying.ContractSize ?? 0)) : 0);
SetOpenUnwindSingleSwapTrade(y, buyTotalFee, sellTotalFee);
}
//当天新增的标的,存在持仓的,用均价作为开仓价
else
{
y.flow.Lots = Math.Abs(y.Lots);
y.flow.BuySell = y.Lots > 0 ? "买入" : "卖出";
y.flow.SpotPrice = Math.Abs(y.SumSpotPrice / y.Lots);
var trade = MapSwapTradeHandle(y.flow, false);
totalFee = underlyingTradeFlows.Sum(z => z.NeedCostFee ? (z.SingleFee != null ? (z.SingleFee.Value * z.Lots) : (z.UnAnnualRate * z.Lots * z.SpotPrice * underlying.ContractSize ?? 0)) : 0);
InnerSaveSwapTrade(trade, totalFee);
if (newParentTradeId == 0 && trade.ParentTradeId > 0)
{
newParentTradeId = trade.ParentTradeId;
}
hasNoPosition = false;
}
});
var oldParentTradeId = preTradeDateTrades.FirstOrDefault().td.ParentTradeId;
var oldParentTrade = DbContext.trade.Find(oldParentTradeId);
AddTradeOperationHistoryAndSetParentTradeInfo(true, oldParentTrade, "合成多空组合流水平仓操作");
var newParentTrade = DbContext.trade.Find(newParentTradeId);
if (newParentTrade != null)
{
AddTradeOperationHistoryAndSetParentTradeInfo(true, newParentTrade, "合成多空组合流水开仓操作");
}
}
//当天开仓的场景
//第一天开仓的交易,将流水费用合成变为对应子交易的交易费用;
else
{
var tradeFlowsUnderlyingGroup = GetTradeFlowsUnderlyingGroup(tradeFlows);
tradeFlowsUnderlyingGroup.ForEach(y =>
{
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(y.UnderlyingCode);
var underlyingTradeFlows = tradeFlows.Where(z => z.UnderlyingCode == y.UnderlyingCode).ToList();
double buyTotalFee = 0d;
double sellTotalFee = 0d;
double totalFee = 0d;
underlyingTradeFlows.ForEach(z =>
{
if (z.NeedCostFee)
{
if (z.SingleFee == null && z.UnAnnualRate == null)
{
var varitey = DataCacheProvider.GetVariety(y.UnderlyingCode);
var clientVarietyConfig = DbContext.client_variety_config.Where(o => o.ClientId == client.id && o.VarietyId == varitey.id && o.ValueDate <= y.flow.TradeDate).OrderByDescending(o => o.ValueDate).FirstOrDefault();
if (clientVarietyConfig == null)
{
throw new ServiceException($"该客户[{client.Name}]需要维护品种[{varitey.VarietyCode}]在[{y.flow.TradeDate}]相关的收费参数配置");
}
buyTotalFee += clientVarietyConfig.SingleFee > 0 ? (clientVarietyConfig.SingleFee * z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0)) : (clientVarietyConfig.UnAnnualRate * z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0) * z.SpotPrice * underlying.ContractSize ?? 0);
sellTotalFee += clientVarietyConfig.SingleFee > 0 ? (clientVarietyConfig.SingleFee * z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0)) : (clientVarietyConfig.UnAnnualRate * z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0) * z.SpotPrice * underlying.ContractSize ?? 0);
totalFee += clientVarietyConfig.SingleFee > 0 ? (clientVarietyConfig.SingleFee * z.Lots) : (clientVarietyConfig.UnAnnualRate * z.Lots * z.SpotPrice * underlying.ContractSize ?? 0);
}
else
{
buyTotalFee += z.SingleFee != null ? (z.SingleFee.Value * z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0)) : (z.UnAnnualRate * z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0) * z.SpotPrice * underlying.ContractSize ?? 0);
sellTotalFee += z.SingleFee != null ? (z.SingleFee.Value * z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0)) : (z.UnAnnualRate * z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0) * z.SpotPrice * underlying.ContractSize ?? 0);
totalFee += z.SingleFee != null ? (z.SingleFee.Value * z.Lots) : (z.UnAnnualRate * z.Lots * z.SpotPrice * underlying.ContractSize ?? 0);
}
}
});
//持仓数为0,新增一笔普通互换,然后当天平仓平掉
if (y.Lots == 0)
{
SetOpenUnwindSingleSwapTrade(y, buyTotalFee, sellTotalFee);
}
//存在持仓的,用均价作为开仓价
else
{
y.flow.Lots = Math.Abs(y.Lots);
y.flow.BuySell = y.Lots > 0 ? "买入" : "卖出";
y.flow.SpotPrice = Math.Abs(y.SumSpotPrice / y.Lots);
var trade = MapSwapTradeHandle(y.flow, false);
InnerSaveSwapTrade(trade, totalFee);
}
});
AddTradeOperationHistoryAndSetParentTradeInfo(true, originalTrade, "合成多空组合流水开仓");
}
tradeFlows.ForEach(y => y.Status = "已完成");
DbContext.SaveChanges();
if (hasNoPosition)
{
var tradeDateTradeIds = (from td in DbContext.trade.Where(z => z.TradeDate == valuedateBLL.ValueDate && z.ValidState != "InValid")
join swap in DbContext.trade_swap.Where(z => z.OriginalTradeId == originalTradeId && z.SwapType == "多空组合")
on td.id equals swap.TradeId
select td.id).ToList();
if (tradeDateTradeIds.Any())
{
tradeDateTradeIds.ForEach(z =>
{
new TradeInvalidService(this).InvalidTrade(z, false);
});
}
}
#endregion
}
});
}
trans.Commit();
}
}
private List<trade_swap_flow_group> GetTradeFlowsUnderlyingGroup(IEnumerable<trade_swap_flow> tradeFlows)
{
var tradeFlowsUnderlyingGroup = tradeFlows.GroupBy(y => y.UnderlyingCode)
.Select(y =>
new trade_swap_flow_group()
{
UnderlyingCode = y.Key,
BuyLots = y.Sum(z => z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0)),
SellLots = y.Sum(z => z.Lots * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0)),
Lots = y.Sum(z => z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : -1)),
SumBuySpotPrice = y.Sum(z => z.Lots * (z.SpotPrice ?? 0) * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : 0)),
SumSellSpotPrice = y.Sum(z => z.Lots * (z.SpotPrice ?? 0) * (z.BuySell == "卖出" || z.BuySell == "S" ? 1 : 0)),
SumSpotPrice = y.Sum(z => z.Lots * (z.SpotPrice ?? 0) * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : -1)),
flow = new trade_swap_flow()
{
UnderlyingCode = y.Key,
BuySell = y.Sum(z => z.Lots * (z.BuySell == "买入" || z.BuySell == "B" ? 1 : -1)) >= 0 ? "买入" : "卖出",
ClearingAgency = y.First().ClearingAgency,
TradeNumber = y.First().TradeNumber,
TradeDate = y.First().TradeDate,
StartDate = y.First().StartDate,
ExerciseDate = y.First().ExerciseDate,
QuoteCurrency = y.First().QuoteCurrency,
SettlementDate = y.First().SettlementDate,
NeedCostFee = y.First().NeedCostFee,
SingleFee = y.First().SingleFee,
UnAnnualRate = y.First().UnAnnualRate
}
}
).ToList();
return tradeFlowsUnderlyingGroup;
}
private void SetOpenUnwindSingleSwapTrade(trade_swap_flow_group flowGroup, double openCostFee, double closeCostFee)
{
flowGroup.flow.Lots = flowGroup.BuyLots;
flowGroup.flow.SpotPrice = flowGroup.SumBuySpotPrice / flowGroup.BuyLots;
var trade = MapSwapTradeHandle(flowGroup.flow, true);
InnerSaveSwapTrade(trade, openCostFee);
trade.UnWindDate = valuedateBLL.ValueDate;
trade.FinalPrice = flowGroup.SumSellSpotPrice / flowGroup.SellLots;
UnwindSwapTradeCashHandle(trade, "平仓", null, closeCostFee);
AddTradeOperationHistoryAndSetParentTradeInfo(true, trade, "合成多空组合流水时生成的单笔交易开平仓记录");
}
private trade MapSwapTradeHandle(trade_swap_flow swapFlow, bool isSingleTrade)
{
var originalTrades = DbContext.trade.Where(x => x.TradeNumber == swapFlow.TradeNumber);
new TradeExtendService(UserInfo).SetTradeExtend(originalTrades, true);
var originalTrade = originalTrades.FirstOrDefault();
var lastParentTrade = originalTrade;
if (originalTrade == null)
{
throw new ServiceException($"该交易编号[{swapFlow.TradeNumber}]在系统中不存在");
}
else if (originalTrade.TradeType != "收益互换" || originalTrade.trade_swap.SwapType != "多空组合")
{
throw new ServiceException($"该交易编号[{swapFlow.TradeNumber}]的交易类型非多空组合的收益互换");
}
var defaultExerciseDate = originalTrade.ExerciseDate;
var td = new trade
{
TradeDate = swapFlow.TradeDate,
StartDate = swapFlow.StartDate,
ExerciseDate = swapFlow.ExerciseDate,
TradeType = "收益互换",
StructureType = "收益互换",
ClientId = originalTrade.ClientId,
ClientName = originalTrade.ClientName,
QuoteCurrency = swapFlow.QuoteCurrency,
SettlementCurrency = originalTrade.SettlementCurrency,
UnderlyingCode = swapFlow.UnderlyingCode,
SpotPrice = swapFlow.SpotPrice,
Lots = swapFlow.Lots,
IsNight = swapFlow.IsNight,
OpponentRole = "甲方",
MarginTemplateName = null,
MarginType = MarginTypeEnum.DEFAULT,
IsGroup = isSingleTrade ? 0 : 2
};
if (!isSingleTrade)
{
if (originalTrade.TradeDate == swapFlow.TradeDate)
{
td.ParentTradeId = originalTrade.id;
}
else if (originalTrade.TradeDate < swapFlow.TradeDate)
{
var todayParentTrade = (from trade in DbContext.trade.Where(x => x.ValidState != "InValid" && x.TradeDate == swapFlow.TradeDate && x.ClientId == originalTrade.ClientId)
join swap in DbContext.trade_swap.Where(x => x.OriginalTradeId == originalTrade.id)
on trade.id equals swap.TradeId
select trade).FirstOrDefault();
if (todayParentTrade == null)
{
var lastParentTrades = (from trade in DbContext.trade.Where(x => x.ValidState != "InValid" && x.TradeDate < swapFlow.TradeDate && x.ClientId == originalTrade.ClientId && x.IsGroup == 1)
join swap in DbContext.trade_swap.Where(x => x.OriginalTradeId == originalTrade.id)
on trade.id equals swap.TradeId
select trade).OrderByDescending(x => x.TradeDate);
if (lastParentTrades.Any())
{
new TradeExtendService(UserInfo).SetTradeExtend(lastParentTrades, true);
lastParentTrade = lastParentTrades.First();
defaultExerciseDate = lastParentTrade.ExerciseDate;
}
var newParentTrade = new trade
{
TradeDate = swapFlow.TradeDate,
StartDate = swapFlow.StartDate,
ExerciseDate = defaultExerciseDate,
TradeType = "收益互换",
StructureType = "收益互换",
ClientId = lastParentTrade.ClientId,
ClientName = lastParentTrade.ClientName,
QuoteCurrency = lastParentTrade.QuoteCurrency,
SettlementCurrency = lastParentTrade.SettlementCurrency,
UnderlyingCode = lastParentTrade.UnderlyingCode,
UnderlyingId = lastParentTrade.UnderlyingId,
UnderlyingAssetClass = lastParentTrade.UnderlyingAssetClass,
MaturityDate = lastParentTrade.MaturityDate,
UnderlyingInstrumentType = lastParentTrade.UnderlyingInstrumentType,
UnderlyingAssetName = lastParentTrade.UnderlyingName,
SpotPrice = lastParentTrade.SpotPrice,
IsNight = lastParentTrade.IsNight,
OpponentRole = lastParentTrade.OpponentRole,
MarginTemplateName = lastParentTrade.MarginTemplateName,
MarginType = lastParentTrade.MarginType,
IsUsePremiumRate = lastParentTrade.IsUsePremiumRate,
PrincipalRate = lastParentTrade.PrincipalRate,
ParticipationRate = lastParentTrade.ParticipationRate,
TraderId = lastParentTrade.TraderId,
TraderName = lastParentTrade.TraderName,
AssetId = lastParentTrade.AssetId,
AssetBookName = lastParentTrade.AssetBookName,
IsGroup = lastParentTrade.IsGroup
};
newParentTrade.MetaDic = lastParentTrade.MetaDic;
newParentTrade.trade_swap = new trade_swap()
{
SwapType = lastParentTrade.trade_swap.SwapType,
OriginalTradeId = originalTrade.id,
IsGetFloatingProfit = lastParentTrade.trade_swap.IsGetFloatingProfit,
GetSingleFee = lastParentTrade.trade_swap.GetSingleFee,
GetUnAnnualRate = lastParentTrade.trade_swap.GetUnAnnualRate,
GetSwapTimeAndRate = lastParentTrade.trade_swap.GetSwapTimeAndRate,
GetMarginRate = lastParentTrade.trade_swap.GetMarginRate,
GetUnderlyingId = lastParentTrade.trade_swap.GetUnderlyingId,
GetUnderlyingCode = lastParentTrade.trade_swap.GetUnderlyingCode,
GetSpotPrice = lastParentTrade.trade_swap.GetSpotPrice,
IsPayFloatingProfit = lastParentTrade.trade_swap.IsPayFloatingProfit,
PaySingleFee = lastParentTrade.trade_swap.PaySingleFee,
PayUnAnnualRate = lastParentTrade.trade_swap.PayUnAnnualRate,
PayMarginRate = lastParentTrade.trade_swap.PayMarginRate,
PayUnderlyingId = lastParentTrade.trade_swap.PayUnderlyingId,
PayUnderlyingCode = lastParentTrade.trade_swap.PayUnderlyingCode,
PaySpotPrice = lastParentTrade.trade_swap.PaySpotPrice,
PaySwapTimeAndRate = lastParentTrade.trade_swap.PaySwapTimeAndRate,
AnnualDays = lastParentTrade.trade_swap.AnnualDays,
AnnualVarIncome = lastParentTrade.trade_swap.AnnualVarIncome,
RateCalcMode = lastParentTrade.trade_swap.RateCalcMode,
IsTradePriceWhenOpen = lastParentTrade.trade_swap.IsTradePriceWhenOpen,
};
InnerSaveSwapTrade(newParentTrade, 0);
td.ParentTradeId = newParentTrade.id;
}
else
{
td.ParentTradeId = todayParentTrade.id;
defaultExerciseDate = todayParentTrade.ExerciseDate;
}
}
else
{
throw new ServiceException($"交易编号[{swapFlow.TradeNumber}]对应的交易流水的交易日期[{swapFlow.TradeDate?.ToString("yyyy-MM-dd")}]不该在多空组合交易的交易日[{originalTrade.TradeDate?.ToString("yyyy-MM-dd")}]之前");
}
}
td.MetaDic = lastParentTrade.MetaDic;
//标的代码(必需)
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
if (underlying == null)
{
throw new ServiceException($"该标的代码[{td.UnderlyingCode}]在系统中不存在");
}
else
{
td.UnderlyingId = underlying.id;
td.UnderlyingAssetClass = underlying.UnderlyingType;
td.MaturityDate = underlying.MaturityDate;
if (td.ExerciseDate == null)
{
td.ExerciseDate = underlying.MaturityDate;
swapFlow.ExerciseDate = underlying.MaturityDate;
}
td.UnderlyingInstrumentType = underlying.UnderlyingInstrumentType;
td.UnderlyingAssetName = underlying.UnderlyingName;
}
if (td.ExerciseDate == null)
{
td.ExerciseDate = defaultExerciseDate;
}
var variety = DataCacheProvider.GetVarietyDataSource().GetData(underlying.UnderlyingTypeId);
//交易份额
td.Notional = (td.Lots ?? 0) * underlying.ContractSize;
td.TradeAmount = td.Notional / variety.CountRatio;
td.OriginalNotional = td.Notional;
td.StockEqvNotional = (td.SpotPrice ?? 0) * td.Notional;
td.StockEqvNotionalReal = td.StockEqvNotional;
td.OriginalStockEqvNotional = td.StockEqvNotional;
td.PrincipalRate = 0;
td.ParticipationRate = 1;
td.AssetId = originalTrade.AssetId;
td.AssetBookName = originalTrade.AssetBookName;
td.TraderId = originalTrade.TraderId;
td.TraderName = originalTrade.TraderName;
//td.InitialMargin = td.StockEqvNotional * (lastParentTrade.trade_swap.GetMarginRate - lastParentTrade.trade_swap.PayMarginRate);
td.trade_swap = new trade_swap()
{
TradeId = td.id,
OriginalTradeId = originalTrade.id
};
td.trade_swap.SwapType = "普通";
td.trade_swap.AnnualDays = lastParentTrade.trade_swap.AnnualDays;
td.trade_swap.AnnualVarIncome = lastParentTrade.trade_swap.AnnualVarIncome;
td.trade_swap.RateCalcMode = lastParentTrade.trade_swap.RateCalcMode;
td.trade_swap.IsTradePriceWhenOpen = true;
td.trade_swap.IsPayFloatingProfit = lastParentTrade.trade_swap.IsPayFloatingProfit;
td.trade_swap.IsGetFloatingProfit = lastParentTrade.trade_swap.IsGetFloatingProfit;
td.trade_swap.GetSwapTimeAndRate = lastParentTrade.trade_swap.GetSwapTimeAndRate;
td.trade_swap.PaySwapTimeAndRate = lastParentTrade.trade_swap.PaySwapTimeAndRate;
var isAnnualSet = swapFlow.SingleFee != null || swapFlow.UnAnnualRate != null;
if (isAnnualSet)
{
if (td.trade_swap.IsPayFloatingProfit)
{
td.trade_swap.GetSingleFee = swapFlow.SingleFee ?? 0;
td.trade_swap.GetUnAnnualRate = swapFlow.UnAnnualRate ?? 0;
}
else
{
td.trade_swap.PaySingleFee = swapFlow.SingleFee ?? 0;
td.trade_swap.PayUnAnnualRate = swapFlow.UnAnnualRate ?? 0;
}
}
else
{
var varitey = DataCacheProvider.GetVariety(td.UnderlyingCode);
var clientVarietyConfig = DbContext.client_variety_config.Where(x => x.ClientId == td.ClientId && x.VarietyId == varitey.id && x.ValueDate <= td.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault();
if (clientVarietyConfig == null)
{
throw new ServiceException($"该客户[{td.ClientName}]需要维护品种[{varitey.VarietyCode}]在[{td.TradeDate}]相关的收费参数配置");
}
if (td.trade_swap.IsPayFloatingProfit)
{
td.trade_swap.GetSingleFee = clientVarietyConfig.SingleFee;
td.trade_swap.GetUnAnnualRate = clientVarietyConfig.UnAnnualRate;
}
else
{
td.trade_swap.PaySingleFee = clientVarietyConfig.SingleFee;
td.trade_swap.PayUnAnnualRate = clientVarietyConfig.UnAnnualRate;
}
}
if (td.trade_swap.IsPayFloatingProfit)
{
td.trade_swap.GetTradePrice = (td.trade_swap.GetSingleFee ?? 0) * (td.Lots ?? 0) + (td.trade_swap.GetUnAnnualRate ?? 0) * td.StockEqvNotional;
td.trade_swap.GetMarginRate = lastParentTrade.trade_swap.GetMarginRate;
td.trade_swap.PaySpotPrice = td.SpotPrice;
td.trade_swap.PayUnderlyingId = td.UnderlyingId;
td.trade_swap.PayUnderlyingCode = td.UnderlyingCode;
td.trade_swap.PayNotional = td.Notional;
td.trade_swap.PayTradeAmount = td.TradeAmount;
}
else
{
td.trade_swap.PayTradePrice = (td.trade_swap.PaySingleFee ?? 0) * (td.Lots ?? 0) + (td.trade_swap.PayUnAnnualRate ?? 0) * td.StockEqvNotional;
td.trade_swap.PayMarginRate = lastParentTrade.trade_swap.PayMarginRate;
td.trade_swap.GetSpotPrice = td.SpotPrice;
td.trade_swap.GetUnderlyingId = td.UnderlyingId;
td.trade_swap.GetUnderlyingCode = td.UnderlyingCode;
td.trade_swap.GetNotional = td.Notional;
td.trade_swap.GetTradeAmount = td.TradeAmount;
}
//交易方向
var longshort = swapFlow.BuySell;
switch (longshort)
{
case "买入":
case "B":
if (td.trade_swap.IsPayFloatingProfit)
{
td.trade_swap.PayLongShort = "多头";
}
else
{
td.trade_swap.GetLongShort = "多头";
}
break;
case "卖出":
case "S":
if (td.trade_swap.IsPayFloatingProfit)
{
td.trade_swap.PayLongShort = "空头";
}
else
{
td.trade_swap.GetLongShort = "空头";
}
break;
default:
throw new ServiceException("买卖方向 填写错误:" + longshort);
}
return td;
}
private void InnerSaveSwapTrade(trade td, double tradePriceQuote)
{
if (!string.IsNullOrWhiteSpace(td.TradeNumber))
{
if (DbContext.trade.Any(x => x.TradeNumber == td.TradeNumber))
{
throw new ServiceException($"存在重复的交易编号[{td.TradeNumber}]");
}
}
td.TradeStatus = ConsTrade.确认成交;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.TradeDate.Value, seekPreday: true);
if (td.trade_swap.IsPayFloatingProfit)
{
td.trade_swap.GetTradePrice = tradePriceQuote;
td.TradePrice = tradePriceQuote * currencyRate;
td.BuySell = "卖出";
}
else
{
td.trade_swap.PayTradePrice = tradePriceQuote;
td.TradePrice = tradePriceQuote * currencyRate;
td.BuySell = "买入";
}
td.OriginalNotional = td.Notional;
td.OriginalStockEqvNotional = td.StockEqvNotional;
td.StockEqvNotionalReal = td.StockEqvNotionalReal;
td.MarginTemplateName = null;
td.MarginType = MarginTypeEnum.DEFAULT;
td.IsTradePricePayType = true;
td.TradeSource = TradeSourceEnum.导入交易.ToString();
td.OptId = UserId;
td.OptName = UserName;
td.OptDate = DateTime.Now;
td.CreatorId = UserId;
td.CreatorName = UserName;
td.CreateDate = DateTime.Now;
DbContext.trade.Add(td);
DbContext.SaveChanges();
td.trade_swap.TradeId = td.id;
td.trade_swap.OptId = UserId;
td.trade_swap.OptName = UserName;
td.trade_swap.OptDate = DateTime.Now;
DbContext.trade_swap.Add(td.trade_swap);
SaveTradeMeta(td);
var tc = new trade_cash
{
ValidState = "Valid"
};
DbContext.trade_cash.Add(tc);
tc.OptId = UserId;
tc.OptName = UserName;
tc.OptDate = DateTime.Now;
tc.Action = ClientCashInCashOut.系统操作_期权费;
tc.Amount = (td.TradePrice ?? 0) * (td.BuySell == "买入" ? -1 : 1);
tc.QuoteAmount = tradePriceQuote * (td.BuySell == "买入" ? -1 : 1);
tc.CurrencyRate = currencyRate;
tc.ExceciseType = "现金";
tc.TradeId = td.id;
tc.ValueDate = td.TradeDate.Value;
tc.Notional = td.Notional;
tc.TradeAmount = td.TradeAmount;
tc.Status = TradeCashStatusEnum.已执行;
tc.TradeType = td.BuySell;
DbContext.SaveChanges();
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var tcdGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = tc.Amount,
QuoteAmount = tc.QuoteAmount,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString(),
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now
};
DbContext.trade_cash_detail.Add(tcdGet);
if (td.ParentTradeId > 0)
{
var parentTrade = DbContext.trade.Find(td.ParentTradeId);
if (parentTrade != null)
{
parentTrade.OriginalStockEqvNotional += td.StockEqvNotional;
parentTrade.StockEqvNotional += td.StockEqvNotional;
parentTrade.StockEqvNotionalReal += td.StockEqvNotional;
var tradePrice = (parentTrade.TradePrice ?? 0) * (parentTrade.BuySell == "买入" ? -1 : 1) + (td.TradePrice ?? 0) * (td.BuySell == "买入" ? -1 : 1);
parentTrade.TradePrice = Math.Abs(tradePrice);
parentTrade.BuySell = tradePrice >= 0 ? "卖出" : "买入";
var swapTrade = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == parentTrade.id);
if (swapTrade != null)
{
if (swapTrade.IsPayFloatingProfit)
{
swapTrade.GetTradePrice = tradePrice;
}
else
{
swapTrade.PayTradePrice = -tradePrice;
}
}
td.trade_swap.AnnualDays = swapTrade.AnnualDays;
trade_swap_detail detail = new trade_swap_detail()
{
IsForGet = td.trade_swap.IsGetFloatingProfit,
TradeId = td.ParentTradeId,
ChildTradeId = td.id,
LongShort = td.trade_swap.IsGetFloatingProfit ? td.trade_swap.GetLongShort : td.trade_swap.PayLongShort,
UnderlyingCode = td.UnderlyingCode,
SpotPrice = td.SpotPrice,
OriginalNotional = td.OriginalNotional,
Notional = td.Notional,
TradePrice = td.trade_swap.IsGetFloatingProfit ? (td.trade_swap.PayTradePrice ?? 0) : (td.trade_swap.GetTradePrice ?? 0)
};
DbContext.trade_swap_detail.Add(detail);
if (string.IsNullOrWhiteSpace(td.TradeNumber))
{
var childCount = DbContext.trade.Where(x => x.ParentTradeId == parentTrade.id && x.ValidState != "InValid").Count();
td.TradeNumber = BizLogicSingleton.Instance.GenerateSubTradeNumberBeforeConfirm(td, parentTrade, childCount, DbContext);
}
}
}
else
{
if (string.IsNullOrWhiteSpace(td.TradeNumber))
{
td.TradeNumber = BizLogicSingleton.Instance.GenerateTradeNumberBeforeConfirm(td, DbContext);
}
}
DbContext.SaveChanges();
}
private void SaveTradeMeta(trade t)
{
if (t != null && t.MetaDic != null && t.MetaDic.Count() > 0)
{
foreach (var kv in t.MetaDic)
{
if (!string.IsNullOrEmpty(kv.Value))
{
new TradeServiceBase(UserInfo).AddTradeMeta(false, t.id, kv.Key, kv.Value);
}
}
}
}
private void UnwindSwapTradeCashHandle(trade td, string action, double? annualFee, double? costFee)
{
var client = DataCacheProvider.GetClientDataSource().GetData(td.ClientId);
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
//增加现金交割交易记录
var tc = new trade_cash();
DbContext.trade_cash.Add(tc);
tc.OptId = UserId;
tc.OptName = UserName;
tc.OptDate = OptDate;
tc.ExceciseType = "现金";
tc.TradeType = td.BuySell;
tc.CallPut = td.CallPut;
tc.Notional = td.Notional;
tc.TradeAmount = td.TradeAmount;
tc.IsLastAction = true;
tc.TradeId = td.id;
tc.FinalPrice = td.FinalPrice;
tc.UnwindType = "全部平仓";
tc.UnwindNotional = td.Notional;
tc.UnwindTradeAmount = td.TradeAmount;
tc.UnwindPercentRate = 1;
tc.NotionalPercentRate = tc.UnwindPercentRate;
var trade_cash_swap = new trade_cash_swap();
if (td.trade_swap.IsPayFloatingProfit)
{
var initialAmountPayQuote = PayoffSwapCalcService.GetInitialAmountSwapPay(td, td.trade_swap, td.SpotPrice ?? 0
, td.FinalPrice ?? 0, (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0), td.UnWindDate.Value, null);
var preSwapDate = td.trade_swap.IncludeFirstDay ? td.StartDate.Value.AddDays(-1) : td.StartDate.Value;
var extraAmountGetQuote = annualFee ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.GetSwapTimeAndRate, preSwapDate, td.UnWindDate.Value, td.trade_swap.AnnualDays ?? 0, (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0));
var extraAmountPayQuote = annualFee ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.PaySwapTimeAndRate, preSwapDate, td.UnWindDate.Value, td.trade_swap.AnnualDays ?? 0, (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0));
var costFeeGetQuote = costFee ?? 0;
var costTradePriceGetQuote = 0.0;
if (!td.trade_swap.IsTradePriceWhenOpen)
{
costTradePriceGetQuote = PayoffSwapCalcService.GetCostFee(td, td, tc, true, true);
}
var quoteAmount = extraAmountGetQuote + costFeeGetQuote + costTradePriceGetQuote - initialAmountPayQuote - extraAmountPayQuote;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.UnWindDate.Value, seekPreday: true, currencyRateType: quoteAmount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
var initialAmountPay = initialAmountPayQuote * currencyRate;
var extraAmountGet = extraAmountGetQuote * currencyRate;
var extraAmountPay = extraAmountPayQuote * currencyRate;
var costFeeGet = costFeeGetQuote * currencyRate;
var costTradePriceGet = costTradePriceGetQuote * currencyRate;
td.TradeStatus = tc.ValueDate == td.ExerciseDate ? "已到期" : "已平仓";
td.StockEqvNotional = 0;
td.Notional = 0;
td.TradeAmount = 0;
td.UnWindNotional = tc.UnwindNotional;
tc.Amount = extraAmountGet + costFeeGet + costTradePriceGet - initialAmountPay - extraAmountPay;
tc.QuoteAmount = quoteAmount;
tc.CurrencyRate = currencyRate;
tc.Action = action == "平仓" ? ClientCashInCashOut.系统操作_平仓费 : ClientCashInCashOut.系统操作_互换;
tc.IsLastAction = true;
tc.Status = TradeCashStatusEnum.已执行;
tc.ValueDate = td.UnWindDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = td.UnWindDate == td.ExerciseDate ? TradeCashExerciseWayEnum.到期行权 : TradeCashExerciseWayEnum.提前终止行权;
DbContext.SaveChanges();
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
trade_cash_swap.StartDate = td.StartDate.Value;
trade_cash_swap.PayStartPrice = trade_swap.PayFinalPrice ?? trade_swap.PaySpotPrice;
trade_cash_swap.PayFinalPrice = tc.FinalPrice;
trade_cash_swap.PayInitialAmount = initialAmountPay;
trade_cash_swap.PayExtraAmount = extraAmountPay;
trade_cash_swap.PayAmount = initialAmountPay + extraAmountPay;
var customizedResultsPay = QdpHelper.ParseAutocallCustomizedInfo(td.trade_swap.PaySwapTimeAndRate);
var paySwapRates = customizedResultsPay.Item2;
trade_cash_swap.PaySwapRate = paySwapRates.FirstOrDefault();
trade_cash_swap.GetExtraAmount = extraAmountGet;
trade_cash_swap.GetCostFee = costFeeGet + costTradePriceGet;
trade_cash_swap.GetAmount = extraAmountGet + costFeeGet + costTradePriceGet;
var customizedResultsGet = QdpHelper.ParseAutocallCustomizedInfo(td.trade_swap.GetSwapTimeAndRate);
var getSwapRates = customizedResultsGet.Item2;
trade_cash_swap.GetSwapRate = getSwapRates.FirstOrDefault();
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
var tcdGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = extraAmountGet - extraAmountPay,
QuoteAmount = extraAmountGetQuote - extraAmountPayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGet);
var tcdCostFeeGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = costFeeGet,
QuoteAmount = costFeeGetQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostFeeGet);
var tcdCostTradePriceGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = costTradePriceGet,
QuoteAmount = costTradePriceGetQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostTradePriceGet);
var tcdPay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -initialAmountPay,
QuoteAmount = -initialAmountPayQuote,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPay);
}
else
{
var initialAmountGetQuote = PayoffSwapCalcService.GetInitialAmountSwapGet(td, td.trade_swap, td.SpotPrice ?? 0
, td.FinalPrice ?? 0, td.OriginalStockEqvNotional ?? 0, td.UnWindDate.Value, null);
var preSwapDate = td.trade_swap.IncludeFirstDay ? td.StartDate.Value.AddDays(-1) : td.StartDate.Value;
var extraAmountPayQuote = annualFee ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.PaySwapTimeAndRate, preSwapDate, td.UnWindDate.Value, td.trade_swap.AnnualDays ?? 0, (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0));
var extraAmountGetQuote = annualFee ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.GetSwapTimeAndRate, preSwapDate, td.UnWindDate.Value, td.trade_swap.AnnualDays ?? 0, (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0));
var costFeePayQuote = costFee ?? 0;
var costTradePricePayQuote = 0.0;
if (!td.trade_swap.IsTradePriceWhenOpen)
{
costTradePricePayQuote = PayoffSwapCalcService.GetCostFee(td, td, tc, false, true);
}
var quoteAmount = initialAmountGetQuote + extraAmountGetQuote - extraAmountPayQuote - costFeePayQuote - costTradePricePayQuote;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.UnWindDate.Value, seekPreday: true, currencyRateType: quoteAmount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
var initialAmountGet = initialAmountGetQuote * currencyRate;
var extraAmountPay = extraAmountPayQuote * currencyRate;
var extraAmountGet = extraAmountGetQuote * currencyRate;
var costFeePay = costFeePayQuote * currencyRate;
var costTradePricePay = costTradePricePayQuote * currencyRate;
tc.Amount = initialAmountGet + extraAmountGet - extraAmountPay - costFeePay - costTradePricePay;
tc.QuoteAmount = quoteAmount;
tc.CurrencyRate = currencyRate;
tc.Action = action == "平仓" ? ClientCashInCashOut.系统操作_平仓费 : ClientCashInCashOut.系统操作_互换;
tc.IsLastAction = true;
tc.Status = TradeCashStatusEnum.已执行;
tc.ValueDate = td.UnWindDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = td.UnWindDate == td.ExerciseDate ? TradeCashExerciseWayEnum.到期行权 : TradeCashExerciseWayEnum.提前终止行权;
DbContext.SaveChanges();
td.TradeStatus = tc.ValueDate == td.ExerciseDate ? "已到期" : "已平仓";
td.StockEqvNotional = 0;
td.Notional = 0;
td.TradeAmount = 0;
td.UnWindNotional = tc.UnwindNotional;
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
trade_cash_swap.StartDate = td.StartDate.Value;
trade_cash_swap.GetStartPrice = trade_swap.GetFinalPrice ?? trade_swap.GetSpotPrice;
trade_cash_swap.GetFinalPrice = tc.FinalPrice;
trade_cash_swap.GetInitialAmount = initialAmountGet;
trade_cash_swap.GetExtraAmount = extraAmountGet;
trade_cash_swap.GetAmount = initialAmountGet + extraAmountGet;
var customizedResultsGet = QdpHelper.ParseAutocallCustomizedInfo(td.trade_swap.GetSwapTimeAndRate);
var getSwapRates = customizedResultsGet.Item2;
trade_cash_swap.GetSwapRate = getSwapRates.FirstOrDefault();
trade_cash_swap.PayExtraAmount = extraAmountPay;
trade_cash_swap.PayCostFee = costFeePay + costTradePricePay;
trade_cash_swap.PayAmount = extraAmountPay + costFeePay + costTradePricePay;
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(td.trade_swap.PaySwapTimeAndRate);
var paySwapRates = customizedResults.Item2;
trade_cash_swap.PaySwapRate = paySwapRates.FirstOrDefault();
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
var tcdGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = extraAmountGet - extraAmountPay,
QuoteAmount = extraAmountGetQuote - extraAmountPayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGet);
var tcdCostFeeGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -costFeePay,
QuoteAmount = -costFeePayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostFeeGet);
var tcdCostTradePriceGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -costTradePricePay,
QuoteAmount = -costTradePricePayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostTradePriceGet);
var tcdPay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = initialAmountGet,
QuoteAmount = initialAmountGetQuote,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPay);
}
if (td.ParentTradeId > 0)
{
var parentTrade = DbContext.trade.Find(td.ParentTradeId);
if (parentTrade != null)
{
parentTrade.UnWindDate = tc.ValueDate;
parentTrade.StockEqvNotional = 0;
parentTrade.TradeStatus = "已平仓";
var tradeSwapDetail = DbContext.trade_swap_detail.FirstOrDefault(x => x.TradeId == parentTrade.id && x.ChildTradeId == td.id);
if (tradeSwapDetail != null)
{
tradeSwapDetail.Notional = td.Notional;
}
var tradeCash = DbContext.trade_cash.FirstOrDefault(x => x.TradeId == td.ParentTradeId && x.Action == ClientCashInCashOut.系统操作_平仓费 && x.ValidState != "InValid");
if (tradeCash == null)
{
tradeCash = new trade_cash()
{
TradeId = td.ParentTradeId,
Notional = parentTrade.OriginalNotional ?? 0,
ValueDate = tc.ValueDate,
Action = tc.Action,
Amount = 0,
ExerciseWay = tc.ExerciseWay,
IsLastAction = true,
UnwindNotional = parentTrade.OriginalNotional ?? 0,
UnwindPercentRate = 1,
OptId = UserId,
OptName = UserName,
OptDate = DateTime.Now
};
DbContext.trade_cash.Add(tradeCash);
}
DbContext.SaveChanges();
var tradeCashSwap = DbContext.trade_cash_swap.FirstOrDefault(x => x.TradeCashId == tradeCash.id && x.TradeId == parentTrade.id);
if (tradeCashSwap == null)
{
tradeCashSwap = new trade_cash_swap()
{
TradeId = parentTrade.id,
TradeCashId = tradeCash.id,
StartDate = parentTrade.StartDate,
OptId = UserId,
OptName = UserName,
OptDate = DateTime.Now
};
DbContext.trade_cash_swap.Add(tradeCashSwap);
}
tradeCashSwap.GetAmount = (tradeCashSwap.GetAmount ?? 0) + (trade_cash_swap.GetAmount ?? 0);
tradeCashSwap.GetInitialAmount = (tradeCashSwap.GetInitialAmount ?? 0) + (trade_cash_swap.GetInitialAmount ?? 0);
tradeCashSwap.GetExtraAmount = (tradeCashSwap.GetExtraAmount ?? 0) + (trade_cash_swap.GetExtraAmount ?? 0);
tradeCashSwap.GetCostFee = (tradeCashSwap.GetCostFee ?? 0) + (trade_cash_swap.GetCostFee ?? 0);
tradeCashSwap.PayAmount = (tradeCashSwap.PayAmount ?? 0) + (trade_cash_swap.PayAmount ?? 0);
tradeCashSwap.PayInitialAmount = (tradeCashSwap.PayInitialAmount ?? 0) + (trade_cash_swap.PayInitialAmount ?? 0);
tradeCashSwap.PayExtraAmount = (tradeCashSwap.PayExtraAmount ?? 0) + (trade_cash_swap.PayExtraAmount ?? 0);
tradeCashSwap.PayCostFee = (tradeCashSwap.PayCostFee ?? 0) + (trade_cash_swap.PayCostFee ?? 0);
new TradeCashService(this).SaveTradeCashDetail(tradeCash);
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(parentTrade, tradeCash, tradeCash.ValueDate, true);
tradeCash.Amount += tc.Amount;
tc.ParentTradeId = td.ParentTradeId;
tc.ParentTradeCashId = tradeCash.id;
DbContext.SaveChanges();
}
}
DbContext.SaveChanges();
}
}
}