663 lines
25 KiB
C#
663 lines
25 KiB
C#
using Qdp.Pricing.Base.Implementations;
|
||
using YLErp.Abstract.DataProviders;
|
||
using YLErp.Commons;
|
||
using YLErp.Modules;
|
||
using YLErp.Modules.CalculationModule;
|
||
using YLErp.Modules.DataProviderModule;
|
||
using YLErp.Modules.MarginModule;
|
||
using YLErp.QdpModule;
|
||
|
||
namespace YLErp.BLL.MarginCalculation
|
||
{
|
||
public partial class MarginCalculationBase
|
||
{
|
||
/// <summary>
|
||
/// 预付金计算帮助类
|
||
/// </summary>
|
||
protected class RunMarginCalculationHelper
|
||
{
|
||
public readonly RunMarginCalculationReq req;
|
||
readonly IUnderlyingDataProvider underlyingDataProvider;
|
||
|
||
HashSet<string> _underlyingCodeSet;
|
||
Dictionary<int, InnerClient> _clientDic;
|
||
readonly MarginParamProvider _mpProvider;
|
||
|
||
public RunMarginCalculationHelper(RunMarginCalculationReq req, IUnderlyingDataProvider underlyingDataProvider)
|
||
{
|
||
this.req = req;
|
||
this.underlyingDataProvider = underlyingDataProvider;
|
||
_mpProvider = new MarginParamProvider(req.UserInfo, req.settleDate);
|
||
}
|
||
|
||
#region----数据准备(内部方法)----
|
||
|
||
/// <summary>
|
||
/// 交易对应客户信息
|
||
/// </summary>
|
||
protected void PrepareClient()
|
||
{
|
||
if (_clientDic != null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
var clientIds = req.tradeList.Select(t => t.ClientId).ToHashSet();
|
||
using (var db = DbContextFactory.GetClientDbContext(req.UserInfo))
|
||
{
|
||
var query = from c in db.client
|
||
join cl in db.clientlevel on c.LevelId equals cl.id into t_cl
|
||
from cl in t_cl.DefaultIfEmpty()
|
||
where clientIds.Contains(c.id)
|
||
select new InnerClient
|
||
{
|
||
ClientId = c.id,
|
||
Ratio = cl == null ? null : cl.Ratio,
|
||
Ratio1 = cl == null ? null : cl.Ratio1,
|
||
AddRatio = cl == null ? null : cl.AddRatio,
|
||
MarginOptionType = c.MarginOptionType,
|
||
ProperClientClass = c.ProperClientClass,
|
||
QuestionnaireScore = c.QuestionnaireScore,
|
||
RuleT0orT1 = c.RuleT0orT1,
|
||
BoundSide = c.BoundSide
|
||
};
|
||
|
||
_clientDic = query.ToDictionary(n => n.ClientId);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
protected HashSet<string> PrepareUnderlyingCodes()
|
||
{
|
||
if (_underlyingCodeSet != null)
|
||
{
|
||
return _underlyingCodeSet;
|
||
}
|
||
|
||
_underlyingCodeSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
void setUnderlyingCode(trade td)
|
||
{
|
||
if (td?.UnderlyingCode == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
_underlyingCodeSet.Add(td.UnderlyingCode);
|
||
|
||
switch (td.TradeType)
|
||
{
|
||
case "彩虹期权":
|
||
if (td.trade_rainbow_option != null)
|
||
{
|
||
_underlyingCodeSet.Add(td.trade_rainbow_option.UnderlyingAssetCode2);
|
||
}
|
||
break;
|
||
case "价差期权":
|
||
if (td.trade_spread_option != null)
|
||
{
|
||
var codes = td.trade_spread_option.UnderlyingAssetCodes();
|
||
foreach (var code in codes)
|
||
{
|
||
_underlyingCodeSet.Add(code);
|
||
}
|
||
}
|
||
break;
|
||
case "结构化交易":
|
||
if (td.SubTrades != null)
|
||
{
|
||
foreach (var std in td.SubTrades)
|
||
{
|
||
setUnderlyingCode(std);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
foreach (var td in req.tradeList)
|
||
{
|
||
setUnderlyingCode(td);
|
||
}
|
||
|
||
return _underlyingCodeSet;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region----提供数据(公共)----
|
||
|
||
/// <summary>
|
||
/// 获取标的数据
|
||
/// </summary>
|
||
public underlying_manager GetUnderlying(string underlyingCode)
|
||
{
|
||
return underlyingDataProvider.GetUnderlying(underlyingCode);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取underlying code集合
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public HashSet<string> GetUnderlyingCodes()
|
||
{
|
||
return _underlyingCodeSet;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据交易获取客户数据
|
||
/// </summary>
|
||
public InnerClient GetClient(trade trade)
|
||
{
|
||
return GetClient(trade.ClientId);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据客户ID获取客户数据
|
||
/// </summary>
|
||
public InnerClient GetClient(int clientId)
|
||
{
|
||
if (clientId < 1)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
if (_clientDic == null)
|
||
{
|
||
PrepareClient();
|
||
}
|
||
|
||
return _clientDic.TryGetValue(clientId, out var client) ? client : null;
|
||
}
|
||
|
||
public List<InnerClient> GetClients()
|
||
{
|
||
if (_clientDic == null)
|
||
{
|
||
PrepareClient();
|
||
}
|
||
|
||
return _clientDic.Values.ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取预付金参数提供
|
||
/// </summary>
|
||
public MarginParamProvider GetMarginParamProvider(MarginParamTypeEnum initTypeEnums = MarginParamTypeEnum.None)
|
||
{
|
||
if (initTypeEnums != MarginParamTypeEnum.None)
|
||
{
|
||
var umCodeSet = PrepareUnderlyingCodes();
|
||
_mpProvider.Initialize(umCodeSet, initTypeEnums);
|
||
}
|
||
return _mpProvider;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据标的ID获取涨跌停价格
|
||
/// </summary>
|
||
public UpdownLimit GetUpDownLimit(string underlyingCode, double price, bool useMinPriceChange = false, double extendLimitRate = 1)
|
||
{
|
||
if (_mpProvider.TryGetUpdownLimit(underlyingCode, out var limit, out var isFixed))
|
||
{
|
||
if (!isFixed)
|
||
{
|
||
limit *= price;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
limit = price * 0.05;
|
||
}
|
||
|
||
//注意:price价格可能为负值
|
||
limit = Math.Abs(limit);
|
||
|
||
if (useMinPriceChange)
|
||
{
|
||
var um = underlyingDataProvider.GetUnderlying(underlyingCode);
|
||
var minPriceChange = um?.PriceTick ?? 0.01;
|
||
var half = minPriceChange / 2;
|
||
var diff = limit % minPriceChange;
|
||
limit -= diff;
|
||
if (diff >= half)
|
||
{
|
||
limit += minPriceChange;
|
||
}
|
||
}
|
||
|
||
return new UpdownLimit
|
||
{
|
||
UpLimitPrice = price + limit * extendLimitRate,
|
||
DownLimitPrice = price - limit * extendLimitRate
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据涨跌停比例获取张跌停价
|
||
/// </summary>
|
||
/// <param name="price"></param>
|
||
/// <param name="limitRate"></param>
|
||
/// <returns></returns>
|
||
public UpdownLimit GetUpDownLimitByRate(double price, double limitRate)
|
||
{
|
||
return new UpdownLimit
|
||
{
|
||
UpLimitPrice = price * (1 + limitRate),
|
||
DownLimitPrice = price * (1 - limitRate)
|
||
};
|
||
}
|
||
|
||
public UpdownLimit GetStockUpDownLimit(string underlyingCode, double price)
|
||
{
|
||
var limit = 0.1;
|
||
double limitPrice;
|
||
if (underlyingCode.StartsWith("30") || underlyingCode.StartsWith("688"))
|
||
{
|
||
limit = 0.2;
|
||
}
|
||
limitPrice = price * limit;
|
||
|
||
var minPriceChange = 0.01;
|
||
var half = minPriceChange / 2;
|
||
var diff = limitPrice % minPriceChange;
|
||
limitPrice -= diff;
|
||
if (diff >= half)
|
||
{
|
||
limitPrice += minPriceChange;
|
||
}
|
||
|
||
return new UpdownLimit
|
||
{
|
||
UpLimitPrice = OtcFormatHelper.FormatValue(price + limitPrice, 2),
|
||
DownLimitPrice = OtcFormatHelper.FormatValue(price - limitPrice, 2)
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取涨跌停价格字典
|
||
/// </summary>
|
||
/// <param name="upLimitPrices"></param>
|
||
/// <param name="downLimitPrices"></param>
|
||
/// <param name="useMinPriceChange"></param>
|
||
/// <param name="extendLimitRate">涨跌停额外系数,默认为1</param>
|
||
public void GetUpDownLimitPrices(out IPriceProvider upLimitPrices, out IPriceProvider downLimitPrices, bool useMinPriceChange = false, double extendLimitRate = 1, bool isUsePriceLimit = true)
|
||
{
|
||
var umCodeSet = PrepareUnderlyingCodes();
|
||
|
||
var upLimitPrices2 = new ManualPriceProvider();
|
||
var downLimitPrices2 = new ManualPriceProvider();
|
||
|
||
//根据涨跌幅限制以及当日结算价计算涨停价以及跌停价
|
||
foreach (var code in umCodeSet)
|
||
{
|
||
var price = req.PriceProvider.GetPrice(code);
|
||
var updown = isUsePriceLimit ? GetUpDownLimit(code, price, useMinPriceChange, extendLimitRate) : GetUpDownLimitByRate(price, extendLimitRate);
|
||
upLimitPrices2.SetPrice(code, updown.UpLimitPrice);
|
||
downLimitPrices2.SetPrice(code, updown.DownLimitPrice);
|
||
}
|
||
|
||
upLimitPrices = upLimitPrices2;
|
||
downLimitPrices = downLimitPrices2;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取涨跌停价格字典
|
||
/// <para>可通过SplitNumber控制涨停到跌停的分割数量</para>
|
||
/// <para>例如:涨停24,跌停6,splitNumber=6,</para>
|
||
/// <para>则返回的数组的lenght=7,分别为24,21,18,15,12,9,6</para>
|
||
/// </summary>
|
||
/// <param name="splitNumber">从涨停到跌停分割多少次</param>
|
||
/// <param name="useMinPriceChange"></param>
|
||
/// <param name="extendLimitRate"></param>
|
||
/// <param name="isUsePriceLimit">涨跌停额外系数,默认为1</param>
|
||
/// <returns></returns>
|
||
public IPriceProvider[] GetUpDownLimitPrices(int splitNumber, bool useMinPriceChange = false, double extendLimitRate = 1, bool isUsePriceLimit = true)
|
||
{
|
||
var umCodeSet = PrepareUnderlyingCodes();
|
||
var priceArr = new ManualPriceProvider[splitNumber + 1];
|
||
for (int i = 0; i < priceArr.Length; i++)
|
||
{
|
||
priceArr[i] = new ManualPriceProvider();
|
||
}
|
||
|
||
//根据涨跌幅限制以及当日结算价计算涨停价以及跌停价
|
||
foreach (var code in umCodeSet)
|
||
{
|
||
var price = req.PriceProvider.GetPrice(code);
|
||
var updown = isUsePriceLimit ? GetUpDownLimit(code, price, useMinPriceChange, extendLimitRate) : GetUpDownLimitByRate(price, extendLimitRate);
|
||
var gap = (updown.UpLimitPrice - updown.DownLimitPrice) / splitNumber;
|
||
for (int i = 0; i < priceArr.Length - 1; i++)
|
||
{
|
||
priceArr[i].SetPrice(code, (updown.UpLimitPrice - (gap * i)).FormatValue(10));
|
||
}
|
||
priceArr[priceArr.Length - 1].SetPrice(code, updown.DownLimitPrice);
|
||
}
|
||
return priceArr.Cast<IPriceProvider>().ToArray();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取持仓波动率字典
|
||
/// </summary>
|
||
public void GetTradVolRateDic(out Dictionary<int, double> volRateDic, Func<trade, double> addVol = null)
|
||
{
|
||
var tradeVolRateArr = req.tradeList.Select(t => new
|
||
{
|
||
tradeId = t.id,
|
||
volRate = (_mpProvider.GetVolatilityRate(t.UnderlyingCode) ?? 0) + (addVol?.Invoke(t) ?? 0)
|
||
}).Where(d => d.volRate > 0).ToArray();
|
||
|
||
volRateDic = tradeVolRateArr.ToDictionary(d => d.tradeId, d => d.volRate);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取持仓波动率字典
|
||
/// </summary>
|
||
public void GetMarginTradVolRateDic(out Dictionary<int, double> volRateDic, Func<trade, double> addVol = null)
|
||
{
|
||
var tradeVolRateArr = req.tradeList.Select(t => new
|
||
{
|
||
tradeId = t.id,
|
||
volRate = GetTradeVol(t.TradeNumber, req.settleDate) ?? 0
|
||
}).Where(d => d.volRate > 0).ToArray();
|
||
|
||
volRateDic = tradeVolRateArr.ToDictionary(d => d.tradeId, d => d.volRate);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取持仓波动率字典
|
||
/// </summary>
|
||
public void GetUpDownVolRateDic(out Dictionary<int, double> upVolRateDic, out Dictionary<int, double> downVolRateDic)
|
||
{
|
||
var tradeVolRateArr = req.tradeList.Select(t => new
|
||
{
|
||
tradeId = t.id,
|
||
volRate = _mpProvider.GetVolatilityRate(t.UnderlyingCode) ?? 0
|
||
}).Where(d => d.volRate > 0).ToArray();
|
||
|
||
upVolRateDic = tradeVolRateArr.ToDictionary(d => d.tradeId, d => d.volRate);
|
||
downVolRateDic = tradeVolRateArr.ToDictionary(d => d.tradeId, d => -d.volRate);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region----实用方法(公共)----
|
||
|
||
/// <summary>
|
||
/// 将BuySell换做相反的方向,
|
||
/// 交易列表变更为克隆数据,所以不需要再对交易恢复原来的方向
|
||
/// </summary>
|
||
/// <param name="force">强制转换</param>
|
||
public void ReverseTradeSide(bool force = false)
|
||
{
|
||
if (!force && !req.forOtherSide)
|
||
{
|
||
return;
|
||
}
|
||
|
||
req.tradeList = req.tradeList.Select(n =>
|
||
{
|
||
var clone = n.Clone();
|
||
|
||
clone.BuySell = clone.BuySell == "买入" ? "卖出" : "买入";
|
||
|
||
if (clone.SubTrades != null && clone.SubTrades.Any())
|
||
{
|
||
clone.SubTrades = clone.SubTrades.Select(m =>
|
||
{
|
||
var xs = m.Clone();
|
||
xs.BuySell = xs.BuySell == "买入" ? "卖出" : "买入";
|
||
return xs;
|
||
|
||
}).ToArray();
|
||
}
|
||
|
||
return clone;
|
||
|
||
}).ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public void SetFieldsByTradeType()
|
||
{
|
||
if (!req.hasOptionInfo)
|
||
{
|
||
tradeBLL.SetFieldsByTradeType(req.tradeList);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取特殊预付金(手动维护或收益互换交易)
|
||
/// </summary>
|
||
public bool GetSpecialMargin(trade trade, double calcPv, out double value, bool isForOtherSide = false)
|
||
{
|
||
value = 0;
|
||
|
||
//首先获取手动维护(包括收益互换交易)的预付金值
|
||
|
||
using (var db = DbContextFactory.GetYLDbContext())
|
||
{
|
||
var predicate = PredicateBuilder.Create<eod_trade_risk_manual>(x => x.TradeId == trade.id && x.Margin != null && string.IsNullOrEmpty(x.VolType));
|
||
|
||
if (trade.TradeType == "自定义交易")
|
||
{
|
||
predicate = predicate.And(x => x.ValueDate <= req.settleDate);
|
||
}
|
||
else
|
||
{
|
||
//非自定义交易只取当天保存的持仓预付金
|
||
predicate = predicate.And(x => x.ValueDate == req.settleDate);
|
||
}
|
||
|
||
var manual = db.eod_trade_risk_manual.Where(predicate)
|
||
.OrderByDescending(x => x.ValueDate)
|
||
.Select(n => new { n.Margin, n.ValueDate }).FirstOrDefault();
|
||
|
||
if (manual != null && manual.Margin != null)
|
||
{
|
||
if (isForOtherSide)
|
||
{
|
||
value = 0;
|
||
}
|
||
else
|
||
{
|
||
value = manual.Margin.Value;
|
||
}
|
||
}
|
||
|
||
//自定义交易总是返回true并有一些特殊逻辑判断
|
||
if (trade.TradeType == "自定义交易")
|
||
{
|
||
//收盘时如果自定义交易还活着且没有维护当日风险,并且收的时系统日期当日的盘,抛出exception
|
||
if ((manual == null || manual.ValueDate != req.settleDate)
|
||
&& req.CalcMarginType == Enums.CalcMarginTypeEnum.EodMargin && !ConsTrade.TradeCompleteStatus.Contains(trade.TradeStatus)
|
||
&& req.settleDate == valuedateBLL.ValueDate && !PS.Config.Is润和 && !PS.Config.IsMustRiskManual)
|
||
{
|
||
throw new Exception($"交易'{trade.TradeNumber}'在{req.settleDate:yyyy-MM-dd}需先进行交易风险维护");
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
//非自定义交易如果有手工维护的预付金则返回true
|
||
//否则如果是收益互换交易则进行计算,其他交易返回false
|
||
if (manual != null && manual.Margin != null)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
//获取收益互换交易的预付金值
|
||
if (trade.TradeType == "收益互换")
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建trade_span实例
|
||
/// </summary>
|
||
public trade_span CreateTradeSpan(trade td, underlying_manager un = null)
|
||
{
|
||
if (td is null)
|
||
{
|
||
throw new ArgumentNullException(nameof(td));
|
||
}
|
||
|
||
if (un == null || td.UnderlyingCode != un.UnderlyingCode)
|
||
{
|
||
un = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
|
||
}
|
||
|
||
return new trade_span
|
||
{
|
||
TradeId = td.id,
|
||
ClientId = td.ClientId,
|
||
ValueDate = req.settleDate,
|
||
VarietyId = un?.UnderlyingTypeId,
|
||
UnderlyingId = td.UnderlyingId,
|
||
UnderlyingCode = td.UnderlyingCode,
|
||
OptId = req.userId,
|
||
OptName = req.userName,
|
||
OptDate = DateTime.Now
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取计算一组交易的风险指标输入参数
|
||
/// </summary>
|
||
public CalculateRisksForTradesReq GetCalculateRisksForTradesReq(IPriceProvider priceProvider,
|
||
Dictionary<int, double> addVolRateDic, Dictionary<int, double> overrideVols, PricingRequest pricingRequest = QdpPricingRequest.PV_ONLY, bool isEodCalc = false, string pricekey = null)
|
||
{
|
||
var tlist = pricekey != null && pricekey.Contains("barPrice") ? req.tradeList.Where(l => l.UnderlyingCode == pricekey.Split(',')[1]).ToList() : req.tradeList;
|
||
var reqConv = new CalculateRisksForTradesReq
|
||
{
|
||
valueDate = req.settleDate,
|
||
tradeList = tlist,
|
||
priceProvider = priceProvider,
|
||
pricingRequest = pricingRequest,
|
||
addVolRateDic = addVolRateDic,
|
||
volType = req.volType,
|
||
settlementType = req.settlementType,
|
||
isUseTradeVol = PS.Config.IsTradeVol,
|
||
PreciseTimeMode = req.CalcMarginType != Enums.CalcMarginTypeEnum.EodMargin,
|
||
isAddVolPercent = true,
|
||
overrideVolsForTrade = overrideVols,
|
||
isMarginCalc = true,
|
||
isEodCalc = isEodCalc
|
||
};
|
||
|
||
if (req.CalcMarginType == Enums.CalcMarginTypeEnum.EodMargin)
|
||
{
|
||
reqConv.calcScenario = Enums.CalcScenarioEnum.EodSettlement;
|
||
}
|
||
|
||
if (req.CalcMarginType == Enums.CalcMarginTypeEnum.InitialMargin)
|
||
{
|
||
reqConv.calcScenario = Enums.CalcScenarioEnum.InitialMargin;
|
||
}
|
||
|
||
return reqConv;
|
||
}
|
||
|
||
public double? GetTradeVol(string TradeNumber, DateTime ValueDate)
|
||
{
|
||
using (var db = DbContextFactory.GetYLDbContext())
|
||
{
|
||
var tradeVol = db.trade_vol.Where(a => a.IsValid && a.TradeNumber == TradeNumber && a.ValueDate == ValueDate).FirstOrDefault();
|
||
if (tradeVol != null)
|
||
{
|
||
return tradeVol.Vol;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
|
||
#region----内部类----
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
protected class InnerClient
|
||
{
|
||
public int ClientId { get; set; }
|
||
|
||
/// <summary>
|
||
/// 维持预付金系数(R2)
|
||
/// </summary>
|
||
public double? Ratio { get; set; }
|
||
|
||
/// <summary>
|
||
/// 初始预付金系数(R1)
|
||
/// </summary>
|
||
public double? Ratio1 { get; set; }
|
||
|
||
/// <summary>
|
||
/// 商品预付金率加点
|
||
/// </summary>
|
||
public double? AddRatio { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否有双向预付金
|
||
/// </summary>
|
||
public int? MarginOptionType { get; set; }
|
||
|
||
/// <summary>
|
||
/// 适当性类型
|
||
/// </summary>
|
||
public string ProperClientClass { get; set; }
|
||
|
||
/// <summary>
|
||
/// 资信评估分数
|
||
/// </summary>
|
||
public int? QuestionnaireScore { get; set; }
|
||
|
||
/// <summary>
|
||
/// 方顿预付金模板选择
|
||
/// </summary>
|
||
public string RuleT0orT1 { get; set; }
|
||
|
||
/// <summary>
|
||
/// 资金流向
|
||
/// </summary>
|
||
public BoundSideEnum BoundSide { get; set; }
|
||
|
||
public override string ToString()
|
||
{
|
||
return ClientId.ToString();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 涨跌停限制
|
||
/// </summary>
|
||
protected struct UpdownLimit
|
||
{
|
||
/// <summary>
|
||
/// 涨停价
|
||
/// </summary>
|
||
public double UpLimitPrice { get; set; }
|
||
|
||
/// <summary>
|
||
/// 跌停价
|
||
/// </summary>
|
||
public double DownLimitPrice { get; set; }
|
||
|
||
/// <summary>
|
||
/// 涨跌停幅度:创业板为20%,其他默认为10%
|
||
/// </summary>
|
||
public double limit { get; set; }
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|