从山证v2.3.0拷贝

This commit is contained in:
吴方海
2024-05-09 14:06:26 +08:00
parent 566ff33259
commit f9d8a256a6
4471 changed files with 1203456 additions and 9 deletions
@@ -0,0 +1,896 @@
using Org.BouncyCastle.Ocsp;
using System.Data;
using YLErp.BLL;
using YLErp.Commons;
using YLErp.Configuration.Enums;
using YLErp.DBModels;
using YLErp.DBModels.Enums;
using YLErp.DBModels.Helpers;
using YLErp.Helpers;
using YLErp.Model;
using YLErp.Model.Enum;
using YLErp.Modules.TradeModule.DealModule;
using YLErp.Modules.TradeModule.OrderModule;
using YLErp.QdpModule;
namespace YLErp.Modules.TradeModule.ForwardModule
{
public class ForwardTradeImportService : TradeCashService
{
public ForwardTradeImportService(OptUserInfo userInfo) : base(userInfo)
{
}
public void ImportFromExcel(Stream streamIn, string TypeName, out int totalNum, out int successNum)
{
totalNum = 0;
successNum = 0;
var rowIndex = 0;
try
{
var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0);
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 2)
{
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
}
var table = ds.Tables[0];
var reader = new DataRowReader(table, 0);
rowIndex = 1;
totalNum = table.Rows.Count - rowIndex;
foreach (var row in table.Rows.Cast<DataRow>().Skip(1))
{
using (var trans = BeginTransaction())
{
rowIndex++;
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
{
totalNum--;
continue;
}
reader.SetDataRow(row);
switch (TypeName)
{
case "远期交易":
HandleForwardTrade(reader, ForwardTradePriceModel.STANDARD);//标准模式导入
break;
case "远期交易挂钩标的":
HandleForwardTrade(reader, ForwardTradePriceModel.HOOK_PRICE);//挂钩标的模式导入
break;
default:
HandleFinishForwardTrade(reader);//批量了结导入
break;
}
successNum++;
trans.Commit();
}
}
}
catch (ServiceException se)
{
if (se.Tag != null)
{
throw;
}
throw new ServiceException($"已成功导入{successNum}条;\n第{rowIndex}行,{se.Message}");
}
catch (Exception ex)
{
LogFactory.GetLogger(TypeName).Error(ex);
throw new ServiceException($"已成功导入{successNum}条,\n第{rowIndex}行,发生错误:{ex.Message}", ex);
}
}
#region
/// <summary>
/// 处理每行数据
/// </summary>
/// <param name="reader"></param>
public void HandleForwardTrade(DataRowReader reader, ForwardTradePriceModel priceModel)
{
OtcTradeForward td = new OtcTradeForward();
td = MapForwardTrade(reader, priceModel);
var otcOptionTradeFullEx = new OtcOptionTradeFullEx { ClientName = td.ClientName };
new OtcOptionSaveChecker(this).CheckAssetBook(td).CheckTrader(td).CheckClient(otcOptionTradeFullEx);
td.ClientId = otcOptionTradeFullEx.ClientId;
CalculatedForwardFieldValue(td, reader);
td.TradeType = "远期";
var mapTd = TradeConverter.ConvertForward(td);
new TradeSaveService(OptUser).SaveTrade(mapTd, TradeSourceEnum.);
}
public OtcTradeForward MapForwardTrade(DataRowReader reader, ForwardTradePriceModel priceModel)
{
var td = new OtcTradeForward
{
TradeNumber = reader.GetString("交易编号", false),
AssetBookName = reader.GetString("簿记账户名称", true),
TraderName = reader.GetString("交易员名称", true),
ClientName = reader.GetString("交易对手方名称", true),
StructureType = reader.GetString("结构类型", true),
//UnderlyingCode = reader.GetString("标的代码", true),
//BasisUnderlyingCode = reader.GetString("挂钩标的代码", false),
//BasisGap = reader.GetDouble("基差", false),
BuySell = reader.GetString("交易方向", true),
OptionType = reader.GetString("多空方向", false),
TradeAmount = reader.GetDouble("成交数量", false) ?? 0,
Lots = reader.GetDouble("手数", false),
Strike = reader.GetDouble("交割价格", true),
//SpotPrice = reader.GetDouble("期初标的价格", true) ?? 0,
AnnualMarginRate = reader.GetPercent("年化预付金成本", false) ?? 0,
AnnualStoragePrice = reader.GetDouble("年化仓储成本", false) ?? 0,
NoRiskRate = reader.GetPercent("无风险利率", false) ?? 0,
MarginTemplateName = reader.GetString("预付金模板", false),
TradeDate = reader.GetDate("成交日期", true),
ExerciseDate = reader.GetDate("到期日期", true),
SettlementDate = reader.GetDate("结算日期", true),
ObservationDates = reader.GetString("均价结算日", false),
Comments = reader.GetString("备注", false)
};
string IsSupplyForwardValue = reader.GetString("是否补偿远期价值", true);
if (IsSupplyForwardValue == "补偿" || IsSupplyForwardValue == "是")
{
td.MetaDic.Add("IsSupplyForwardValue", "1");
}
else if (IsSupplyForwardValue == "支付")
{
td.MetaDic.Add("IsSupplyForwardValue", "-1");
}
else if (IsSupplyForwardValue == "否")
{
td.MetaDic.Add("IsSupplyForwardValue", "0");
}
else
{
//添加拓展字段 是否补充远期价值,Type2:默认值 -1,其他默认值 0
if (PS.Config.ErpElement.ForwardValueIsSupplyOrPay == YLErp.Configuration.Enums.ForwardValueIsSupplyOrPay.Type2)
{
td.MetaDic.Add("IsSupplyForwardValue", "-1");
}
else
{
td.MetaDic.Add("IsSupplyForwardValue", "0");
}
}
if (priceModel == ForwardTradePriceModel.STANDARD)
{
td.UnderlyingCode = reader.GetString("标的1代码", true);
//判断是否组合标的
var synthetic = DataCacheProvider.GetUnderlyingDataSource().GetSyntheticUnderlying(td.UnderlyingCode);
if (synthetic != null)
{
var model = synthetic.GetSyntheticPriceModel();
var basisUnderlyingCode = reader.GetString("标的2代码", false);
var basisUnderlyingPrice = reader.GetString("标的2期初价格", false);
if (!string.IsNullOrEmpty(basisUnderlyingCode) || !string.IsNullOrEmpty(basisUnderlyingPrice))
{
throw new ServiceException("[组合标的]标的2代码必须为空");
}
var codeSet = synthetic.GetUnderlyingCodes().ToHashSet(StringComparer.OrdinalIgnoreCase);
double SpotPrice = 0;
List<string> spList = new List<string>();
for (var i = 1; i <= 4; i++)
{
var code = reader.GetString("组合标的" + i + "代码", false);
if (string.IsNullOrWhiteSpace(code))
{
continue;
}
if (!codeSet.Remove(code))
{
throw new ServiceException($"[组合标的]{i}_代码 填写错误,组合标的中不存在此标的:{code}");
}
var curSportprice = reader.GetDouble("组合标的" + i + "期初价格", true).Value;
var curUC = model.SuList.FirstOrDefault(n => n.UnderlyingCode == code);
if (curUC != null)
{
curUC.Price = curSportprice;
SpotPrice += curUC.Price * curUC.Coefficient;
}
}
if (codeSet.Any())
{
throw new ServiceException("[组合标的]未填写完整");
}
spList.Add(SpotPrice.OtcFormatUmPrice());
td.SpotPrice = SpotPrice;
td.MetaDic["期初信息"] = spList.ToJson();
td.MetaDic["组合标的"] = model.ToJson();
}
else
{
double SpotPrice = reader.GetDouble("标的1期初价格", true) ?? 0;
td.BasisUnderlyingCode = reader.GetString("标的2代码", false);
double? SpotPrice2 = reader.GetDouble("标的2期初价格", false);
//string[] sp = new string[] { SpotPrice.OtcFormatUmPrice(), SpotPrice2 };
List<string> spList = new List<string>();
spList.Add(SpotPrice.ToString("0.####"));
if (!string.IsNullOrEmpty(td.BasisUnderlyingCode))
{
if (SpotPrice2 == null)
{
throw new ServiceException("填写标的2代码,则必须填写标的2期初价格");
}
else
{
spList.Add((SpotPrice2 ?? 0).ToString("0.####"));
}
}
td.SpotPrice = (double)((decimal)SpotPrice - (decimal)(SpotPrice2 ?? 0));
td.MetaDic["期初信息"] = spList.ToJson();
}
}
else
{
td.UnderlyingCode = reader.GetString("标的代码", true);
td.BasisUnderlyingCode = reader.GetString("挂钩标的代码", false);
td.BasisGap = reader.GetDouble("基差", false);
GetSpotPrice(td);
}
//var um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
if (PS.Config.Is浙期)
{
var flag = false;
var codes = new List<string>();
codes.Add(td.UnderlyingCode);
codes.Add(td.BasisUnderlyingCode);
//判断标的是否为现货
flag = UndelyingHelper.IsCodesExistsCommoditySpot(codes, (um) =>
{
return um.UnderlyingInstrumentType == "CommoditySpot" ? true : false;
});
if (flag)
{
var dateStr = reader.GetDate("实际到期日期", false) ?? td.ExerciseDate;
td.MetaDic["ActualExerciseDate"] = dateStr.Value.ToString("yyyy-MM-dd");
}
}
//DateTime.TryParse(dateStr, out var date);
switch (td.BuySell)
{
case "Buy":
td.BuySell = "买入";
break;
case "Sell":
td.BuySell = "卖出";
break;
case "买入":
case "卖出":
break;
default:
throw new ServiceException("交易方向 填写错误:" + td.BuySell);
}
td.OptionType = GetOptionType(td.OptionType, td.BuySell);
if (string.IsNullOrEmpty(td.MarginTemplateName))
{
td.MarginTemplateName = "系统默认";
td.MarginRate = 0;
td.PositionMarginRate = 0;
}
else
{
var marginTemplateList = GetMarginTemplateItems();
if (marginTemplateList.Any(a => a.Name.Equals(td.MarginTemplateName)))
{
switch (td.MarginTemplateName)
{
case "系统默认":
td.MarginType = MarginTypeEnum.DEFAULT;
td.MarginRate = 0;
td.PositionMarginRate = 0;
break;
case "无预付金":
td.MarginType = MarginTypeEnum.NONE;
td.MarginRate = 0;
td.PositionMarginRate = 0;
break;
default:
break;
}
var MarginRate = reader.GetDouble("初始预付金率", false);
var PositionMarginRate = reader.GetDouble("持仓预付金率", false);
td.MarginRate = MarginRate ?? 0;
td.PositionMarginRate = PositionMarginRate ?? 0;
var marginTemplate = marginTemplateList.Where(a => a.Name.Equals(td.MarginTemplateName)).FirstOrDefault();
td.MarginType = (MarginTypeEnum)marginTemplate.MarginType;
if (MarginRate == null)
{
td.MarginRate = marginTemplate.InitialMarginRatio ?? 0;
}
if (PositionMarginRate == null)
{
td.PositionMarginRate = marginTemplate.PositionMarginRatio ?? 0;
}
}
else
{
throw new ServiceException("预付金模板填写错误:" + td.MarginTemplateName);
}
}
if (QdpCalendarHelper.IsHoliday((DateTime)td.TradeDate))
{
throw new ServiceException("成交日期:" + td.TradeDate + ",不能为节假日");
}
if (QdpCalendarHelper.IsHoliday((DateTime)td.ExerciseDate))
{
throw new ServiceException("到期日期:" + td.ExerciseDate + ",不能为节假日");
}
if (QdpCalendarHelper.IsHoliday((DateTime)td.SettlementDate))
{
throw new ServiceException("结算日期:" + td.SettlementDate + ",不能为节假日");
}
if (td.TradeDate > td.ExerciseDate)
{
throw new ServiceException("交易日应该在到期日之前");
}
if (td.SettlementDate < td.ExerciseDate)
{
throw new ServiceException("结算日期不能小于到期日期");
}
if (!string.IsNullOrEmpty(td.ObservationDates))
{
DateTime dt = new DateTime();
if (td.ObservationDates.Contains(','))
{
string[] arrayDate = td.ObservationDates.Split(',');
if (!arrayDate.Any(a => DateTime.TryParse(a, out dt)))
throw new ServiceException("均价结算日日期格式填写错误" + td.ObservationDates);
}
else
{
if (!DateTime.TryParse(td.ObservationDates, out dt))
throw new ServiceException("均价结算日日期格式填写错误" + td.ObservationDates);
}
}
#region metadic表中
string termStr = null;
var ruleStr = reader.GetString("观察周期", false);
if (!string.IsNullOrWhiteSpace(ruleStr))
{
switch (ruleStr)
{
case "每日":
termStr = "1D";
break;
case "每周":
termStr = "1W";
break;
case "每月":
termStr = "1M";
break;
case "每年":
termStr = "1Y";
break;
}
if (termStr == null)
{
var strs = ruleStr.Split(new[] { ',' });
termStr = strs[0].Trim();
}
//敲入观察周期写入metadic中
td.MetaDic["敲入观察周期"] = termStr;
}
#endregion
return td;
}
public string GetOptionType(string OptionType, string BuySell = "")
{
switch (OptionType)
{
case "多头":
case "Call":
return "看涨";
case "空头":
case "Put":
return "看跌";
case "看涨":
case "看跌":
return OptionType;
case "":
case null:
return BuySell == "买入" ? "看涨" : "看跌";
default:
throw new ServiceException("多空方向 填写错误:" + OptionType);
}
}
/// <summary>
/// 计算远期字段值
/// </summary>
/// <param name="td"></param>
/// <returns></returns>
public void CalculatedForwardFieldValue(OtcTradeForward td, DataRowReader reader)
{
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
if (um == null)
{
throw new ServiceException("系统中不存在,导入的标的1代码");
}
else if (!string.IsNullOrEmpty(td.BasisUnderlyingCode))
{
if (DataCacheProvider.GetUnderlyingDataSource().GetData(td.BasisUnderlyingCode) == null)
{
throw new ServiceException("系统中不存在,导入的标的2代码");
}
}
//GetSpotPrice(td);
GetCountRatio(td);
GetNotional_TradeAmount_Lots(td, um);
GetForwardValue(td);
GetOpenCommission_TradePrice(td, reader, null, null);
}
/// <summary>
/// 获取期初价格
/// </summary>
/// <param name="td"></param>
public void GetSpotPrice(OtcTradeForward td)
{
//计算期初价格 期初价格 = 挂钩标的价格 + 基差
if (!string.IsNullOrWhiteSpace(td.BasisUnderlyingCode))
{
var umBasis = DataCacheProvider.GetUnderlyingDataSource().GetData(td.BasisUnderlyingCode);
td.SpotPrice = umBasis.Price + (td.BasisGap ?? 0);
}
else
{
var umBasis = DataCacheProvider.GetUnderlyingDataSource().GetData(td.BasisUnderlyingCode);
td.SpotPrice = umBasis.Price;
}
}
public void GetCountRatio(OtcTradeForward td)
{
var CountRatio = td.CountRatio ?? 0;
if (CountRatio < 1)
{
CountRatio = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode)?.CountRatio ?? 1;
}
td.CountRatio = CountRatio;
}
/// <summary>
/// 获取份额,成交数量,手数
/// </summary>
/// <param name="td"></param>
/// <param name="um"></param>
public void GetNotional_TradeAmount_Lots(OtcTradeForward td, underlying_manager um)
{
if (td.Lots < 0)
throw new ServiceException("手数不能为负数");
if (td.TradeAmount < 0)
throw new ServiceException("成交数量不能为负数");
if (td.TradeAmount == 0 && td.Lots == 0)
throw new ServiceException("成交数量与手数,两者必须填写一个");
if (td.Lots > 0)
{
td.Notional = (double)td.Lots * um.ContractSize;
td.TradeAmount = td.Notional / (double)td.CountRatio;
}
else if (td.TradeAmount > 0)
{
td.Notional = td.TradeAmount * (double)td.CountRatio;
td.Lots = td.Notional / um.ContractSize;
}
td.OriginalNotional = td.Notional;
}
/// <summary>
/// 获取远期价值
/// (交割价格- 期初价格) * 成交数量 * CountRatio *(多-1,空1]*(买入1,卖出 - 1)
/// </summary>
/// <param name="td"></param>
public void GetForwardValue(OtcTradeForward td)
{
var OptionType = GetOptionType(td.OptionType, td.BuySell);
var ForwardValue = (td.Strike - td.SpotPrice) * td.TradeAmount * td.CountRatio * (OptionType == "看涨" ? -1 : 1) * (td.BuySell == "买入" ? 1 : -1);
td.ForwardValue = ForwardValue ?? 0;
}
/// <summary>
/// 获取远期价值
/// </summary>
/// <param name="Strike"></param>
/// <param name="SpotPrice"></param>
/// <param name="TradeAmount"></param>
/// <param name="CountRatio"></param>
/// <param name="OptionType"></param>
/// <param name="BuySell"></param>
/// <returns></returns>
public double GetForwardValue(double Strike, double SpotPrice, double TradeAmount, int CountRatio, string OptionType, string BuySell)
{
OptionType = GetOptionType(OptionType, BuySell);
return (Strike - SpotPrice) * TradeAmount * CountRatio * (OptionType == "看涨" ? -1 : 1) * (BuySell == "买入" ? 1 : -1);
}
/// <summary>
/// 获取远期价值
/// </summary>
/// <param name="Strike"></param>
/// <param name="SpotPrice"></param>
/// <param name="TradeAmount"></param>
/// <param name="CountRatio"></param>
/// <param name="OptionType"></param>
/// <param name="BuySell"></param>
/// <returns></returns>
public double GetForwardValue(double Strike, double SpotPrice, double OriginalNotional, string OptionType, string BuySell)
{
OptionType = GetOptionType(OptionType, BuySell);
return (Strike - SpotPrice) * OriginalNotional * (OptionType == "看涨" ? -1 : 1) * (BuySell == "买入" ? 1 : -1);
}
/// <summary>
/// 获取开仓费用,开仓总费用
/// </summary>
/// <param name="td"></param>
public void GetOpenCommission_TradePrice(OtcTradeForward td, DataRowReader reader, double? OpenCommission, double? TradePrice)
{
if (reader != null)
{
OpenCommission = reader.GetDouble("开仓费用", false);
TradePrice = reader.GetDouble("开仓总费用", false);
}
if (OpenCommission == null && TradePrice == null)
{
throw new ServiceException("开仓费用与开仓总费用,两者必须填写一个");
}
var supplyPrice = td.MetaDic["IsSupplyForwardValue"] == "1" ? td.ForwardValue : td.MetaDic["IsSupplyForwardValue"] == "-1" ? -td.ForwardValue : 0;
//补偿远期价值+开仓费用
if (OpenCommission != null && TradePrice == null)
{
td.TradePrice = supplyPrice + OpenCommission * td.Lots;
td.OpenCommission = OpenCommission.Value;
}
//开仓费用 = (开仓总费用 -(补充远期价值))/ 手数
else if ((OpenCommission != null && TradePrice != null) || (OpenCommission == null && TradePrice != null))
{
td.TradePrice = TradePrice;
td.OpenCommission = ((td.TradePrice - supplyPrice) / td.Lots) ?? 0;
}
}
#endregion
#region
public void HandleFinishForwardTrade(DataRowReader reader)
{
TradeCashImportReq tcReq = MapFinishForward(reader);
var td = DbContext.trade.FirstOrDefault(t => t.TradeNumber == tcReq.TradeNumber && t.ValidState != "InValid");
if (td == null)
{
throw new ServiceException("交易数据 不存在,交易编号:" + tcReq.TradeNumber);
}
if (td.TradeStatus != ConsTrade.)
{
throw new ServiceException("只有交易状态为‘确认成交’,才能进行批量了结导入");
}
td.trade_cash = DbContext.trade_cash.FirstOrDefault(t => t.TradeId == td.id && t.Action == "系统操作-期权费" && t.ValidState != "InValid" && t.IsDeleted == false);
var otcTradeForward = new TradeForwardService(OptUser).GetDetail(td.id);
if ((tcReq.UnwindTradeAmount ?? 0) == 0 && tcReq.UnwindType == "部分平仓")
{
throw new ServiceException("平仓数量不能为0或空值");
}
if (tcReq.UnwindTradeAmount > td.TradeAmount)
{
throw new ServiceException("平仓数量不能大于持仓数量");
}
else if (tcReq.UnwindTradeAmount < td.TradeAmount && tcReq.UnwindType == "全部平仓")
{
throw new ServiceException("全部平仓时,平仓数量等于持仓数量");
}
if (tcReq.UnwindPriceCheck == null && tcReq.UnwindFee == null)
{
throw new ServiceException("当每手平仓费用未填,则平仓总费用必填");
}
CheckValueDate(td, tcReq.ValueDate);
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
var CountRatio = td.CountRatio ?? 0;
if (CountRatio < 1)
{
CountRatio = um?.CountRatio ?? 1;
}
td.CountRatio = CountRatio;
var eodpriceProvider = new YLErp.Modules.DataProviderModule.EodPriceProvider((DateTime)tcReq.ValueDate);
if (tcReq.FinalPrice == null)
{
tcReq.FinalPrice = eodpriceProvider.GetPrice(td.UnderlyingCode, SettlementTypeEnum.ClosePrice);//平仓当天标的价格;
}
if (tcReq.UnwindTradeAmount == td.TradeAmount && tcReq.UnwindType == "部分平仓")
{
tcReq.UnwindType = "全部平仓";
}
if (tcReq.UnwindType == "全部平仓")
{
tcReq.UnwindTradeAmount = td.TradeAmount;
}
var unwindNotional = tcReq.UnwindTradeAmount * td.CountRatio;
double extraAmount = ComputeExtraAmount(td, tcReq) ?? 0;
tcReq.UnwindForwardValue = GetForwardValue(otcTradeForward.Strike ?? 0, tcReq.FinalPrice ?? 0, tcReq.UnwindTradeAmount ?? 0, td.CountRatio ?? 1, td.OptionType, td.BuySell);
tcReq.UnwindRatio = (unwindNotional ?? 0) / (td.OriginalNotional ?? 0);
var supplyPrice = otcTradeForward.MetaDic["IsSupplyForwardValue"] == "1" ? otcTradeForward.ForwardValue : otcTradeForward.MetaDic["IsSupplyForwardValue"] == "-1" ? -otcTradeForward.ForwardValue : 0;
if (tcReq.UnwindFee == null)
{
tcReq.UnwindPriceCheck = tcReq.UnwindPriceCheck ?? 0;
//平仓的总费用 =远期收益+每手平仓费用×平仓手数-(开仓时补偿的远期价值)×平仓数量/成交数量+预付金成本
//其中开仓时补偿的远期价值 = 持仓价值(期初)*Flag
var unwindPrice = (tcReq.UnwindPriceCheck * td.Lots * tcReq.UnwindRatio) ?? 0;
tcReq.UnwindFee = tcReq.UnwindForwardValue + unwindPrice - supplyPrice * tcReq.UnwindRatio + extraAmount;
}
else
{
tcReq.UnwindFee = tcReq.UnwindFee ?? 0;
//平仓费用 = (平仓的总费用 +(开仓时补偿的远期价值* 平仓比例)- 远期收益 - 预付金成本)/ (平仓比例 *手数)
tcReq.UnwindPriceCheck = (tcReq.UnwindFee + supplyPrice * tcReq.UnwindRatio - tcReq.UnwindForwardValue - extraAmount) / (otcTradeForward.Lots * tcReq.UnwindRatio);
}
TradeCashReq req = new TradeCashReq();
req.ValidState = "Valid";
req.UnwindFee = tcReq.UnwindFee ?? 0;
req.Notional = td.Notional;
req.TradeAmount = td.TradeAmount;
req.UnwindPrice = tcReq.UnwindPriceCheck;
req.FinalPrice = tcReq.FinalPrice;
req.UnwindType = tcReq.UnwindType;
req.UnwindNotional = (tcReq.UnwindTradeAmount * td.CountRatio) ?? 0;
req.UnwindPercentRate = td.OriginalNotional > 0 ? (req.UnwindNotional / td.OriginalNotional) ?? 0 : 0;
req.UnwindPricePercentRate = TradeHelper.GetPremiumRateByTradeSinglePrice(req.UnwindPrice, td.SpotPrice);
req.ExtraAmount = extraAmount;
req.ValueDate = tcReq.ValueDate;
//增加现金交割交易记录
var tc = CloseTrade_TradeCashSave(td, req, false, !false, !false);
new TradeCashService(this).SaveTradeCashDetail(tc);
td.TradeSource = TradeSourceEnum..ToString();
td.OptId = UserId;
td.OptName = UserName;
td.OptDate = DateTime.Now;
td.StockEqvNotional -= (double)(td.OriginalStockEqvNotional * tc.UnwindPercentRate);
td.Notional -= (double)(td.OriginalNotional * tc.NotionalPercentRate);
td.TradeAmount = td.Notional / um.CountRatio;
td.UnWindNotional = tc.UnwindNotional;
td.UnWindDate = tc.ValueDate;
if (tc.UnwindType == "全部平仓" || (((decimal)(td.OriginalNotional ?? 0) - (decimal)req.UnwindNotional) == 0 && tc.UnwindType == "部分平仓"))
{
td.TradeStatus = ConsTrade.;
tc.IsLastAction = true;
}
else
{
td.TradeStatus = ConsTrade.;
td.HasPartialUnWind = 1;
tc.IsLastAction = false;
}
DbContext.SaveChanges();
//增加出入金记录
var ee = new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
//删除E/Bod数据
RemoveEodTradeAndFutureInfo(false, td.id, tc.ValueDate);
AddTradeAuditLog(td.id);
}
public TradeCashImportReq MapFinishForward(DataRowReader reader)
{
var tc = new TradeCashImportReq
{
TradeNumber = reader.GetString("交易编号", true),
UnwindType = reader.GetString("平仓类型", true),
UnwindTradeAmount = reader.GetDouble("平仓数量", false),
ValueDate = (DateTime)reader.GetDate("平仓日期", true),
FinalPrice = reader.GetDouble("标的价格", false),
UnwindPriceCheck = reader.GetDouble("每手平仓费用", false),
UnwindFee = reader.GetDouble("平仓总费用", false)
};
if (QdpCalendarHelper.IsHoliday((DateTime)tc.ValueDate))
{
throw new ServiceException("平仓日期:" + tc.ValueDate + ",不能为节假日");
}
return tc;
}
/// <summary>
/// 验证平仓日期
/// </summary>
/// <param name="td"></param>
/// <param name="ValueDate"></param>
/// <exception cref="ServiceException"></exception>
public void CheckValueDate(trade td, DateTime ValueDate)
{
if (td.TradeDate > ValueDate)
{
throw new ServiceException("平仓日期必须要大于或等于成交日期");
}
if (ValueDate > td.ExerciseDate)
{
throw new ServiceException("平仓日期必须要小于或等于到期日期");
}
if (ValueDate > valuedateBLL.ValueDate)
{
throw new ServiceException("平仓日期必须要小于或等于系统日期");
}
}
/// <summary>
/// 计算预付金成本
/// </summary>
/// <param name="td"></param>
/// <param name="tcReq"></param>
/// <returns></returns>
public double? ComputeExtraAmount(trade td, TradeCashImportReq tcReq)
{
var valueDate = valuedateBLL.ValueDate;
if (valueDate > td.ExerciseDate)
{
valueDate = td.ExerciseDate.Value;
}
var lastMarginRecord = DbContext.eod_forward_margin.Where(f => f.TradeId == td.id && f.ValueDate < SystemValueDate).OrderByDescending(x => x.ValueDate).FirstOrDefault();
if (lastMarginRecord != null)
{
var totaldays = (valuedateBLL.ValueDate.Date - lastMarginRecord.ValueDate.Date).TotalDays;
double HolidayMargin = lastMarginRecord.SettlePrice * lastMarginRecord.MarginRate * lastMarginRecord.AnnualRate * totaldays / 365;
var unwindAmount = tcReq.UnwindTradeAmount;
var holidayMarginTotal = unwindAmount * HolidayMargin;
var lastMargin = (lastMarginRecord.MarginSum - lastMarginRecord.CloseMarginSum) * ((unwindAmount) / lastMarginRecord.Notional) + lastMarginRecord.CloseMarginSum;
return lastMargin + holidayMarginTotal;
}
return 0;
}
/// <summary>
/// 计算 交易员角度的远期价值
/// </summary>
/// <param name="buySell"></param>
/// <param name="pptionType"></param>
/// <param name="strike"></param>
/// <param name="FinalPrice"></param>
/// <param name="unwindNotional"></param>
/// <returns></returns>
public double ComputForwardValue(string buySell, string optionType, double strike, double FinalPrice, double unwindNotional)
{
//(行权价-标的价格)* 平仓份额
decimal ForwardValue = 0;
if ((buySell == "卖出" && optionType == "看跌") || (buySell == "买入" && optionType == "看涨"))
{
ForwardValue = ((decimal)strike - (decimal)FinalPrice) * (decimal)unwindNotional;
}
else if ((buySell == "卖出" && optionType == "看涨") || (buySell == "买入" && optionType == "看跌"))
{
ForwardValue = -(((decimal)strike - (decimal)FinalPrice) * (decimal)unwindNotional);
}
return (double)ForwardValue;
}
public void AddTradeAuditLog(int TradeId)
{
var auditLog = new TradeAuditLog
{
TradeId = TradeId,
Changes = null,
DataType = "00",
OptType = "批量了结-平仓",
OptId = UserId,
OptName = UserName,
OptDate = OptDate,
AuditFlag = TradeAuditFlag.operation
};
//记录审核日志
DbContext.TradeAuditLog.Add(auditLog);
DbContext.SaveChanges();
}
public List<margin_template> GetMarginTemplateItems()
{
var marginTemplates = DbContext.margin_template.ToList();
List<margin_template> strList = new List<margin_template>();
strList = marginTemplates;
strList.Add(new margin_template
{
Name = "系统默认",
MarginType = (int)MarginTypeEnum.DEFAULT,
InitialMarginRatio = 0,
PositionMarginRatio = 0
});
strList.Add(new margin_template
{
Name = "无预付金",
MarginType = (int)MarginTypeEnum.NONE,
InitialMarginRatio = 0,
PositionMarginRatio = 0
});
return strList;
}
#endregion
}
}