643 lines
25 KiB
C#
643 lines
25 KiB
C#
using System.Text;
|
|
using YLErp.DBModels.Consts;
|
|
using YLErp.Models;
|
|
using YLErp.Modules.TradeModule.DealModule;
|
|
using YLErp.QdpModule;
|
|
|
|
namespace YLErp.Modules.TradeModule.AccumulatorOptionModule
|
|
{
|
|
public class TradeAccumulatorChangeService : TradeActionDataService
|
|
{
|
|
public TradeAccumulatorChangeService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
|
|
}
|
|
|
|
private static Func<TradeAction, bool> BasePredicate(int tradeId) =>
|
|
n => n.TradeId == tradeId && n.IsValid && n.ActionType == TradeActionType.AccumulatorChange;
|
|
|
|
/// <summary>
|
|
/// 获取历史操作数据
|
|
/// </summary>
|
|
public IEnumerable<TradeAccumulatorChangeData> GetHisDatas(int tradeId)
|
|
{
|
|
var hisPredicate = BasePredicate(tradeId);
|
|
|
|
var hisDatas = new TradeActionQueryService(this).GetDatas(hisPredicate);
|
|
|
|
return hisDatas.Select(n =>
|
|
{
|
|
var data = JsonHelper.Deserialize<TradeAccumulatorChangeData>(n.ActionData);
|
|
data.ValueDate = n.ValueDate.OtcFormatDate();
|
|
return data;
|
|
}).ToArray();
|
|
}
|
|
|
|
#region----保存/删除换月数据----
|
|
|
|
/// <summary>
|
|
/// 保存换月数据
|
|
/// </summary>
|
|
/// <param name="tradeId"></param>
|
|
/// <param name="changeData"></param>
|
|
/// <param name="removeObCheckDatas">是否删除累计收益记录</param>
|
|
public TradeAccumulatorChangeResult SaveChangeData(int tradeId, TradeAccumulatorChangeData changeData, bool removeObCheckDatas)
|
|
{
|
|
if (!DateTime.TryParse(changeData.ValueDate, out var valueDate))
|
|
{
|
|
throw new ServiceException("解析换月日期失败:" + changeData.ValueDate);
|
|
}
|
|
|
|
var td = DbContext.trade.Find(tradeId);
|
|
|
|
if (td == null)
|
|
{
|
|
throw new ServiceException("找不到交易信息,tradeId:" + tradeId);
|
|
}
|
|
|
|
if (td.TradeStatus != "确认成交")
|
|
{
|
|
throw new ServiceException("当前交易状态不符合设置换月的条件");
|
|
}
|
|
|
|
if (valueDate <= td.TradeDate.Value)
|
|
{
|
|
throw new ServiceException($"换月日期'需大于交易日期'{td.TradeDate:yyyy-MM-dd}'");
|
|
}
|
|
|
|
if (valueDate >= td.ExerciseDate.Value)
|
|
{
|
|
throw new ServiceException($"换月日期需小于到期日期'{td.ExerciseDate:yyyy-MM-dd}'");
|
|
}
|
|
|
|
if (valueDate > BLL.valuedateBLL.ValueDate)
|
|
{
|
|
throw new ServiceException("换月日期不能大于系统日期:" + changeData.ValueDate);
|
|
}
|
|
|
|
var tdAcc = DbContext.trade_accumulator_option.Where(n => n.TradeId == tradeId).FirstOrDefault();
|
|
if (tdAcc == null)
|
|
{
|
|
throw new ServiceException("找不到交易扩展信息,交易编号:" + td.TradeNumber);
|
|
}
|
|
|
|
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(changeData.UnderlyingCode);
|
|
if (um == null)
|
|
{
|
|
throw new ServiceException("找不到标的信息:" + changeData.UnderlyingCode);
|
|
}
|
|
if (um.IsFutures() && um.MaturityDate.HasValue && um.MaturityDate < valueDate)
|
|
{
|
|
throw new ServiceException($"所选标的'{changeData.UnderlyingCode}'的到期日'{um.MaturityDate:yyyy-MM-dd}'应大于换月日期'{valueDate:yyyy-MM-dd}'");
|
|
}
|
|
|
|
//按换月日期正序排序获取换月设置集合
|
|
var basePredicate = BasePredicate(td.id);
|
|
var dbActions = DbContext.TradeAction.Where(basePredicate).OrderBy(n => n.ValueDate).ToArray();
|
|
|
|
//将已有Action数据无效
|
|
foreach (var exist in dbActions.Where(x => x.ValueDate == valueDate))
|
|
{
|
|
exist.IsValid = false;
|
|
}
|
|
|
|
//更新交易数据(如果当前存入的换月数据是最新一条数据)
|
|
var tradeUpdated = false;
|
|
TradeAction firstDayAction = null;
|
|
var nextAction = dbActions.FirstOrDefault(a => a.ValueDate > valueDate);
|
|
if (nextAction == null)//没有大于当前换月日期的数据则需要更新交易要素
|
|
{
|
|
if (valueDate != td.TradeDate.Value && !dbActions.Any(a => a.ValueDate == td.TradeDate.Value))
|
|
{
|
|
firstDayAction = GetFirstDayChangeData(td, tdAcc);
|
|
}
|
|
tradeUpdated = true;
|
|
RestoreAccumulatorChangeData(td, tdAcc, changeData, um);
|
|
}
|
|
else
|
|
{
|
|
tradeUpdated = true;
|
|
UpdateTradeObDates(tdAcc, changeData, nextAction.ValueDate);
|
|
}
|
|
|
|
//新增Action数据
|
|
var curAction = CreateTradeAction(tradeId, valueDate, TradeActionType.AccumulatorChange);
|
|
curAction.ActionRemark = "换月";
|
|
curAction.ActionData = JsonHelper.Serialize(changeData);
|
|
|
|
var addActions = firstDayAction != null ? new[] { firstDayAction, curAction } : new[] { curAction };
|
|
|
|
//移除累计收益记录
|
|
if (removeObCheckDatas)
|
|
{
|
|
var nextDate = dbActions.Where(n => n.ValueDate > valueDate).FirstOrDefault()?.ValueDate;
|
|
if (!nextDate.HasValue)
|
|
{
|
|
nextDate = td.ExerciseDate.Value.AddYears(1);
|
|
}
|
|
var obDatas = DbContext.autocall_observation.Where(n => n.TradeId == td.id && n.EndDate >= valueDate && n.EndDate < nextDate).ToArray();
|
|
if (obDatas.Any())
|
|
{
|
|
tradeUpdated = true;
|
|
DbContext.autocall_observation.RemoveRange(obDatas);
|
|
//var cashIds = obDatas.Where(n => n.CashId > 0).Select(n => n.CashId ?? 0).ToArray();
|
|
//RemoveEodTradeAndFutureInfo(saveChanges: false, tradeId: td.id, removeStartDate: valueDate, tradeCashIds: cashIds, deleteOtherCashs: false);
|
|
}
|
|
|
|
//移除自定义观察数据
|
|
var manualPriceDatas = DbContext.manually_trade_observation_price.Where(n => n.TradeId == td.id && n.ValueDate >= valueDate).ToArray();
|
|
DbContext.manually_trade_observation_price.RemoveRange(manualPriceDatas);
|
|
|
|
new TradeBackService(this).Execute(tradeId, valueDate);
|
|
}
|
|
|
|
DbContext.TradeAction.AddRange(addActions);
|
|
|
|
AddTradeOperationHistoryAndSetParentTradeInfo(saveChanges: false, trade: td, optType: "设置累计换月", comments: $"{changeData.ValueDate},{changeData.UnderlyingCode}");
|
|
|
|
#region 更新metadic的观察频率数据
|
|
var tMeta = DbContext.TradeMeta.FirstOrDefault(n => n.TradeId == tradeId && n.MetaKey == ConsTradeMetaKey.koObservationRate);
|
|
if (tMeta != null)
|
|
{
|
|
tMeta.MetaValue = changeData.KOObservation;
|
|
}
|
|
else
|
|
{
|
|
tMeta = new TradeMeta
|
|
{
|
|
TradeId = tradeId,
|
|
MetaKey = ConsTradeMetaKey.koObservationRate,
|
|
MetaValue = changeData.KOObservation,
|
|
CreateTime = DateTime.Now
|
|
};
|
|
DbContext.TradeMeta.Add(tMeta);
|
|
}
|
|
#endregion
|
|
|
|
DbContext.SaveChanges();
|
|
|
|
return new TradeAccumulatorChangeResult
|
|
{
|
|
Actions = addActions,
|
|
TradeUpdated = tradeUpdated
|
|
};
|
|
}
|
|
|
|
//还原或更新更新交易要素
|
|
private void RestoreAccumulatorChangeData(OtcTradeBase td, trade_accumulator_option tdAcc, TradeAccumulatorChangeData changeData, underlying_manager um = null)
|
|
{
|
|
var clone = changeData.Clone();
|
|
var isFixed = tdAcc.PayoffType == "固定";
|
|
var preList = ParseKoObservation(tdAcc.KOObservationDates, isFixed ? null : tdAcc.KOObservationSettleDates, td.TradeDate.Value, DateTime.Parse(changeData.ValueDate));
|
|
var curList = ParseKoObservation(changeData.KOObservationDates, isFixed ? null : changeData.KOObservationSettleDates, DateTime.MinValue);
|
|
preList.AddRange(curList);
|
|
(string KOObservationDates, string KOObservationSettleDates) = BuildKOObservationDates(preList, true);
|
|
clone.KOObservationDates = KOObservationDates;
|
|
clone.KOObservationSettleDates = KOObservationSettleDates;
|
|
TradeAccumulatorHelper.RestoreAccumulatorChangeData(td, tdAcc, clone, um);
|
|
}
|
|
|
|
//更新交易要素--观察频率
|
|
private void UpdateTradeObDates(trade_accumulator_option tdAcc, TradeAccumulatorChangeData curChangeData, DateTime nextValueDate)
|
|
{
|
|
var isFixed = tdAcc.PayoffType == "固定";
|
|
var curValueDate = DateTime.Parse(curChangeData.ValueDate);
|
|
var preList = ParseKoObservation(tdAcc.KOObservationDates, isFixed ? null : tdAcc.KOObservationSettleDates, DateTime.MinValue, curValueDate);
|
|
var curList = ParseKoObservation(curChangeData.KOObservationDates, isFixed ? null : curChangeData.KOObservationSettleDates, DateTime.MinValue, nextValueDate);
|
|
var nextList = ParseKoObservation(tdAcc.KOObservationDates, isFixed ? null : tdAcc.KOObservationSettleDates, nextValueDate);
|
|
preList.AddRange(curList);
|
|
preList.AddRange(nextList);
|
|
(string KOObservationDates, string KOObservationSettleDates) = BuildKOObservationDates(preList, true);
|
|
|
|
tdAcc.KOObservationDates = KOObservationDates;
|
|
tdAcc.KOObservationSettleDates = KOObservationSettleDates;
|
|
}
|
|
|
|
//获取交易开始日期的换月存储数据
|
|
private TradeAction GetFirstDayChangeData(OtcTradeBase td, trade_accumulator_option tdAcc)
|
|
{
|
|
var action = CreateTradeAction(td.id, td.TradeDate.Value, TradeActionType.AccumulatorChange);
|
|
|
|
action.ActionRemark = "换月";
|
|
|
|
var data = new TradeAccumulatorChangeData
|
|
{
|
|
KOBarrier = tdAcc.KOBarrier,
|
|
KOObservationDates = tdAcc.KOObservationDates,
|
|
KOObservationSettleDates = tdAcc.KOObservationSettleDates,
|
|
Strike = td.Strike ?? 0,
|
|
UnderlyingCode = td.UnderlyingCode,
|
|
ValueDate = td.TradeDate.Value.ToString("yyyy-MM-dd")
|
|
};
|
|
|
|
action.ActionData = JsonHelper.Serialize(data);
|
|
|
|
return action;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除换月操作
|
|
/// </summary>
|
|
public TradeAccumulatorChangeResult RemoveChangeData(DateTime valueDate, int tradeId)
|
|
{
|
|
var td = DbContext.trade.Find(tradeId);
|
|
|
|
if (td == null)
|
|
{
|
|
throw new ServiceException("交易信息不存在");
|
|
}
|
|
|
|
if (valueDate == td.TradeDate.Value)
|
|
{
|
|
throw new ServiceException("初始记录不允许删除");
|
|
}
|
|
|
|
var predicate = BasePredicate(tradeId);
|
|
|
|
var dbActions = DbContext.TradeAction.Where(predicate).OrderBy(n => n.ValueDate).ToList();
|
|
|
|
var index = dbActions.FindIndex(n => n.ValueDate == valueDate);
|
|
|
|
if (index < 0)
|
|
{
|
|
throw new ServiceException("操作记录已经不存在");
|
|
}
|
|
|
|
if (index == 0)
|
|
{
|
|
//不应该出现的情况,如果出现了还是报错吧
|
|
throw new ServiceException("初始记录丢失,操作不能继续");
|
|
}
|
|
|
|
var removeAction = dbActions[index];
|
|
|
|
var tradeUpdated = false;
|
|
var invalidActions = new List<TradeAction> { removeAction };
|
|
|
|
var tdAcc = DbContext.trade_accumulator_option.Where(n => n.TradeId == tradeId).FirstOrDefault();
|
|
if (tdAcc == null)
|
|
{
|
|
throw new ServiceException("找不到交易扩展信息,交易编号:" + td.TradeNumber);
|
|
}
|
|
|
|
//交易数据还原到上条操作状态
|
|
if (index == dbActions.Count - 1)
|
|
{
|
|
if (index == 0)
|
|
{
|
|
throw new ServiceException("未找到初始记录,操作不能继续");
|
|
}
|
|
var preAction = dbActions[index - 1];
|
|
if (string.IsNullOrWhiteSpace(preAction.ActionData))
|
|
{
|
|
throw new ServiceException("上条操作记录备份数据已经被损坏,交易数据还原失败,操作不能继续");
|
|
}
|
|
var changeData = JsonHelper.Deserialize<TradeAccumulatorChangeData>(preAction.ActionData);
|
|
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(changeData.UnderlyingCode);
|
|
if (um == null)
|
|
{
|
|
throw new ServiceException("交易数据还原失败,找不到标的信息:" + changeData.UnderlyingCode);
|
|
}
|
|
|
|
RestoreAccumulatorChangeData(td, tdAcc, changeData, um);
|
|
|
|
if (preAction.ValueDate == td.TradeDate.Value)
|
|
{
|
|
preAction.IsValid = false;
|
|
invalidActions.Insert(0, preAction);
|
|
}
|
|
|
|
tradeUpdated = true;
|
|
}
|
|
else
|
|
{
|
|
var preAction = dbActions[index - 1];
|
|
var preData = JsonHelper.Deserialize<TradeAccumulatorChangeData>(preAction.ActionData);
|
|
UpdateTradeObDates(tdAcc, preData, dbActions[index + 1].ValueDate);
|
|
tradeUpdated = true;
|
|
}
|
|
|
|
removeAction.IsValid = false;
|
|
var curChangeData = JsonHelper.Deserialize<TradeAccumulatorChangeData>(removeAction.ActionData);
|
|
AddTradeOperationHistoryAndSetParentTradeInfo(saveChanges: false, trade: td, optType: "移除累计换月", comments: $"{valueDate:yyyy-MM-dd},{curChangeData.UnderlyingCode}");
|
|
|
|
DbContext.SaveChanges();
|
|
|
|
return new TradeAccumulatorChangeResult
|
|
{
|
|
Actions = invalidActions,
|
|
TradeUpdated = tradeUpdated
|
|
};
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 根据提供的数据获取换期数据
|
|
/// </summary>
|
|
public TradeAccumulatorChangeDataEx GetChangeData(DateTime valueDate, OtcTradeBase td, trade_accumulator_option tdAcc = null)
|
|
{
|
|
if (td is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(td));
|
|
}
|
|
|
|
if (valueDate > td.ExerciseDate.Value)
|
|
{
|
|
valueDate = td.ExerciseDate.Value;
|
|
}
|
|
|
|
var predicate = BasePredicate(td.id);
|
|
|
|
var query = from a in DbContext.TradeAction.Where(predicate)
|
|
orderby a.ValueDate descending
|
|
select new
|
|
{
|
|
a.ValueDate,
|
|
a.ActionData
|
|
};
|
|
|
|
var dbActions = query.ToArray();
|
|
|
|
TradeAccumulatorChangeDataEx changeData;
|
|
|
|
var dbAction = query.Where(x => x.ValueDate <= valueDate).FirstOrDefault();
|
|
|
|
if (dbAction == null)
|
|
{
|
|
if (tdAcc == null)
|
|
{
|
|
tdAcc = DbContext.trade_accumulator_option.AsNoTracking().FirstOrDefault(n => n.TradeId == td.id);
|
|
}
|
|
|
|
changeData = TradeAccumulatorHelper.GetDefaultChangeData<TradeAccumulatorChangeDataEx>(valueDate, td, tdAcc);
|
|
|
|
var list = ParseKoObservation(changeData.KOObservationDates, changeData.KOObservationSettleDates, valueDate);
|
|
|
|
(string KOObservationDates, string KOObservationSettleDates) = BuildKOObservationDates(list, false);
|
|
|
|
changeData.KOObservationDates = KOObservationDates;
|
|
changeData.KOObservationSettleDates = KOObservationSettleDates;
|
|
}
|
|
else
|
|
{
|
|
changeData = JsonHelper.Deserialize<TradeAccumulatorChangeDataEx>(dbAction.ActionData);
|
|
changeData.ValueDate = valueDate.OtcFormatDate();
|
|
if (dbAction.ValueDate < valueDate)
|
|
{
|
|
var list = ParseKoObservation(changeData.KOObservationDates, changeData.KOObservationSettleDates, valueDate);
|
|
(string KOObservationDates, string KOObservationSettleDates) = BuildKOObservationDates(list, false);
|
|
changeData.KOObservationDates = KOObservationDates;
|
|
changeData.KOObservationSettleDates = KOObservationSettleDates;
|
|
}
|
|
}
|
|
|
|
var nextDate = dbActions.Where(x => x.ValueDate > valueDate).LastOrDefault()?.ValueDate;
|
|
|
|
changeData.NextDate = (nextDate ?? td.ExerciseDate.Value).OtcFormatDate();
|
|
|
|
if (!nextDate.HasValue)
|
|
{
|
|
nextDate = td.ExerciseDate.Value.AddDays(1);
|
|
}
|
|
changeData.HasObCheck = DbContext.autocall_observation.Any(n => n.TradeId == td.id && n.EndDate >= valueDate && n.EndDate < nextDate);
|
|
|
|
return changeData;
|
|
}
|
|
|
|
#region----观察数据静态方法处理----
|
|
|
|
//解析敲出观察数据(包含startDate但不包含endDate)
|
|
private static List<KoObservationItem> ParseKoObservation(string KOObservationDates, string KOObservationSettleDates
|
|
, DateTime startDate, DateTime? endDate = null)
|
|
{
|
|
var customObservDates = QdpHelper.ParseAutocallCustomizedInfo(KOObservationDates);
|
|
|
|
var obDates = customObservDates.Item1;
|
|
|
|
if (!endDate.HasValue)
|
|
{
|
|
endDate = DateTime.MaxValue;
|
|
}
|
|
|
|
if (obDates != null)
|
|
{
|
|
var list = new List<KoObservationItem>(obDates.Length);
|
|
var customKOBarriers = customObservDates.Item2;
|
|
var customCoupons = customObservDates.Item3;
|
|
var settleDates = QdpHelper.ParseObservationDate(KOObservationSettleDates);
|
|
|
|
for (var i = 0; i < obDates.Length; i++)
|
|
{
|
|
var dt = obDates[i].DateTime;
|
|
|
|
if (dt >= startDate && dt < endDate)
|
|
{
|
|
var item = new KoObservationItem
|
|
{
|
|
date = dt
|
|
};
|
|
|
|
if (customKOBarriers != null && customKOBarriers.Length > i)
|
|
{
|
|
item.barrier = customKOBarriers[i];
|
|
}
|
|
|
|
if (customCoupons != null && customCoupons.Length > i)
|
|
{
|
|
item.coupon = customCoupons[i];
|
|
}
|
|
|
|
if (settleDates != null && settleDates.Length > i)
|
|
{
|
|
item.settleDate = settleDates[i].DateTime;
|
|
}
|
|
|
|
list.Add(item);
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
return new List<KoObservationItem>();
|
|
}
|
|
/// <summary>
|
|
/// 获取累计期权平仓定价日的观察日期
|
|
/// </summary>
|
|
/// <param name="kOObservationDates">观察日期</param>
|
|
/// <param name="valueDate">定价日期或平仓日期</param>
|
|
/// <param name="tradeDate">交易日期</param>
|
|
/// <param name="exerciseDate">到期日期</param>
|
|
public int GetAccTradeUnwindDayCount(string kOObservationDates, DateTime? valueDate, DateTime? tradeDate, DateTime? exerciseDate)
|
|
{
|
|
var dayCount = 0;
|
|
var startDate = (valueDate ?? tradeDate).GetValueOrDefault();
|
|
if (kOObservationDates != null)
|
|
{
|
|
var koModel = QdpHelper.ParseAutocallCustomizedInfo(kOObservationDates);
|
|
if (valueDate != null)
|
|
{
|
|
dayCount = koModel.Item1.Count(O => O.DateTime >= valueDate);
|
|
}
|
|
else
|
|
{
|
|
dayCount = koModel.Item1.Count(O => O.DateTime >= startDate);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (startDate == tradeDate)//默认观察日列表不包括首日观察
|
|
{
|
|
startDate = startDate.AddDays(1);
|
|
}
|
|
dayCount = QdpCalendarHelper.GetWorkDayCount(startDate, exerciseDate.GetValueOrDefault()) + 1;
|
|
}
|
|
return dayCount;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 组合观察数据项到字符串
|
|
/// </summary>
|
|
/// <param name="itemList"></param>
|
|
/// <param name="useObDateAsSettleDateIfEmpty">如果结算日为空是否使用观察日</param>
|
|
private static (string KOObservationDates, string KOObservationSettleDates) BuildKOObservationDates(List<KoObservationItem> itemList
|
|
, bool useObDateAsSettleDateIfEmpty)
|
|
{
|
|
if (itemList == null || !itemList.Any())
|
|
{
|
|
return (string.Empty, string.Empty);
|
|
}
|
|
|
|
var sb_obdates = new StringBuilder(512);
|
|
var sb_barrier = new StringBuilder(512);
|
|
var sb_coupon = new StringBuilder(512);
|
|
var sb_stdates = new StringBuilder(512);
|
|
|
|
foreach (var item in itemList)
|
|
{
|
|
sb_obdates.Append(item.date.ToString("yyyy-MM-dd")).Append(',');
|
|
|
|
if (item.barrier.HasValue)
|
|
{
|
|
sb_barrier.Append(item.barrier).Append(',');
|
|
}
|
|
|
|
if (item.coupon.HasValue)
|
|
{
|
|
sb_coupon.Append(item.coupon).Append(',');
|
|
}
|
|
|
|
if (item.settleDate.HasValue)
|
|
{
|
|
sb_stdates.Append(item.settleDate?.ToString("yyyy-MM-dd")).Append(',');
|
|
}
|
|
else if (useObDateAsSettleDateIfEmpty)
|
|
{
|
|
sb_stdates.Append(item.date.ToString("yyyy-MM-dd")).Append(',');
|
|
}
|
|
}
|
|
|
|
sb_obdates.Remove(sb_obdates.Length - 1, 1).Append(';');
|
|
|
|
if (sb_barrier.Length > 0)
|
|
{
|
|
sb_barrier.Remove(sb_barrier.Length - 1, 1);
|
|
sb_obdates.Append(sb_barrier.ToString()).Append(';');
|
|
}
|
|
|
|
if (sb_coupon.Length > 0)
|
|
{
|
|
sb_coupon.Remove(sb_coupon.Length - 1, 1);
|
|
sb_obdates.Append(sb_coupon.ToString());
|
|
}
|
|
|
|
if (sb_stdates.Length > 0)
|
|
{
|
|
sb_stdates.Remove(sb_stdates.Length - 1, 1);
|
|
}
|
|
|
|
return (sb_obdates.ToString(), sb_stdates.ToString());
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class TradeAccumulatorChangeData
|
|
{
|
|
/// <summary>
|
|
/// 执行日期
|
|
/// </summary>
|
|
public string ValueDate { get; set; }
|
|
|
|
/// <summary>
|
|
/// 标的代码
|
|
/// </summary>
|
|
public string UnderlyingCode { get; set; }
|
|
|
|
/// <summary>
|
|
/// 执行价格
|
|
/// </summary>
|
|
public double Strike { get; set; }
|
|
|
|
/// <summary>
|
|
/// 敲出障碍价格
|
|
/// </summary>
|
|
public double? KOBarrier { get; set; }
|
|
|
|
/// <summary>
|
|
/// 观察日期
|
|
/// </summary>
|
|
public string KOObservationDates { get; set; }
|
|
|
|
/// <summary>
|
|
/// 结算日期
|
|
/// </summary>
|
|
public string KOObservationSettleDates { get; set; }
|
|
|
|
/// <summary>
|
|
/// 观察频率
|
|
/// </summary>
|
|
public string KOObservation { get; set; }
|
|
|
|
public TradeAccumulatorChangeData Clone()
|
|
{
|
|
return (TradeAccumulatorChangeData)MemberwiseClone();
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{ValueDate:yyyy-MM-dd}--{UnderlyingCode}";
|
|
}
|
|
}
|
|
|
|
public class TradeAccumulatorChangeDataEx : TradeAccumulatorChangeData
|
|
{
|
|
/// <summary>
|
|
/// 下一日
|
|
/// </summary>
|
|
public string NextDate { get; set; }
|
|
|
|
/// <summary>
|
|
/// 存在累计收益
|
|
/// </summary>
|
|
public bool HasObCheck { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 换月操作结果数据
|
|
/// </summary>
|
|
public class TradeAccumulatorChangeResult
|
|
{
|
|
/// <summary>
|
|
/// 是否交易数据被更新
|
|
/// </summary>
|
|
public bool TradeUpdated { get; set; }
|
|
|
|
/// <summary>
|
|
/// 产生的或受影响的actions
|
|
/// </summary>
|
|
public IEnumerable<TradeAction> Actions { get; set; }
|
|
}
|
|
}
|