/// <summary> /// Применяет настройки видимой области, переданные в аргументе rect /// </summary> /// <param name="rect">невалидные настройки игнорируются</param> private void ApplySettings(ICanvasPane pane, Rect rect) { // PROD-3577 - Если иы используем кубик SetViewport, то эта настройка всегда должна стоять pane.FeetToBorder2ByDefault = true; // PROD-5747 - Применяем только валидные настройки if ((pane == null) || (!DoubleUtil.IsPositive(rect.Width)) || (!DoubleUtil.IsPositive(rect.Height))) { string tradeName = (m_context.Runtime?.TradeName ?? "NULL").Replace(Constants.HtmlDot, "."); string msg = String.Format(CultureInfo.InvariantCulture, "[{0}.ApplySettings] BAD RECT. TradeName:'{1}'; Width:{2}; Height:{3}", GetType().Name, tradeName, rect.Width, rect.Height); m_context.Log(msg, MessageType.Info, false); return; } if (ApplyVisualSettings) { // Флаг выставляется однократно по нажатию кнопки и потом сбрасывается, если нужно pane.FeetToBorder2 = true; } if (ManageX) { //pane.BorderX1 = rect.X; //pane.BorderX2 = rect.X + rect.Width; pane.Border2X1 = rect.X; pane.Border2X2 = rect.X + rect.Width; } if (ManageY) { pane.Border2Y1 = rect.Y - rect.Height; pane.Border2Y2 = rect.Y; } if (ManageXGridStep) { pane.XAxisStep = m_xAxisGridStep; pane.XAxisDiviser = m_xAxisDivisor; } if (ManageYGridStep) { // TODO: прокинуть через АПИ настройки грида оси Y? //pane.YA = m_yAxisGridStep; //pane.YAX = m_yAxisDivisor; } }
public void Execute(double price, double time, double sigma, ICanvasPane pane, int barNum) { int barsCount = ContextBarsCount; if (barNum < barsCount - 1) { return; } // PROD-3577 pane.FeetToBorder2ByDefault = true; double futPx = price; double dT = time; //double sigma = sigmas[sigmas.Count - 1]; if (!DoubleUtil.IsPositive(futPx)) { return; } if (!DoubleUtil.IsPositive(dT)) { return; } if (!DoubleUtil.IsPositive(sigma)) { return; } if (pane != null) { Rect rect = PrepareVieportSettings(null, futPx, dT, sigma); ApplySettings(pane, rect); //if (ShouldWarmSecurities) //WarmSecurities(Context, rect); } }
public ICanvasPane Execute(ICanvasPane pane) { return(pane ?? throw new ArgumentNullException(nameof(pane))); }
public void Execute(double price, double time, IOptionSeries optSer, ICanvasPane pane, int barNum) { int barsCount = ContextBarsCount; if ((barNum < barsCount - 1) || (optSer == null)) { return; } // PROD-3577 pane.FeetToBorder2ByDefault = true; double futPx = price; double dT = time; if (!DoubleUtil.IsPositive(futPx)) { return; } if (!DoubleUtil.IsPositive(dT)) { return; } double sigma; IFunction smileFunc = IvOnF.PrepareExchangeSmileSpline(optSer, Double.MinValue, Double.MaxValue); if ((smileFunc == null) || (!smileFunc.TryGetValue(futPx, out sigma)) || (!DoubleUtil.IsPositive(sigma))) { //При работе с Эксанте и прочим Западом Биржевой улыбки не будет //Поэтому надо иметь 'План Б': подставить фиксированную волатильность 30%! sigma = DefaultSigma; // PROD-5968 - У биткойна совсем другой типичный уровень волатильности var parent = optSer.UnderlyingAsset; var secDesc = parent.SecurityDescription; var tp = secDesc.TradePlace; var dsClassName = tp?.DataSource?.GetType().Name; if (dsClassName == "DeribitDS") { sigma = DefaultSigmaDeribit; } else if (dsClassName == "ExanteDataSource") { if (tp.Id == "CME") { if (secDesc.ActiveType.IsFuture() && parent.Symbol.StartsWith("ES")) { sigma = DefaultSigmaEs; } } } } if (pane != null) { string expiryStr = optSer.ExpirationDate.ToString(TimeToExpiry.DateTimeFormat, CultureInfo.InvariantCulture); Rect rect = PrepareVieportSettings(expiryStr, futPx, dT, sigma); ApplySettings(pane, rect); if (ManageXGridStep) { var pairs = optSer.GetStrikePairs().ToArray(); int pLen = pairs.Length; if (pLen > 1) { double dK = pairs[1].Strike - pairs[0].Strike; if (pLen > 2) { int t = pLen / 2; // Делим нацело. Для pLen==3 получаем 1 dK = pairs[t + 1].Strike - pairs[t].Strike; } pane.XAxisStep = GetXAxisStep(dK); pane.XAxisDiviser = GetXAxisDivisor(dK); } } } }
public void Execute(double price, double time, InteractiveSeries smile, ICanvasPane pane, int barNum) { int barsCount = ContextBarsCount; if ((barNum < barsCount - 1) || (smile == null) || (smile.Tag == null)) { return; } // PROD-3577 pane.FeetToBorder2ByDefault = true; SmileInfo smileInfo = smile.GetTag <SmileInfo>(); if ((smileInfo == null) || (smileInfo.ContinuousFunction == null)) { return; } double futPx = price; double dT = time; if (!DoubleUtil.IsPositive(futPx)) { return; } if (!DoubleUtil.IsPositive(dT)) { return; } double sigma; if ((!smileInfo.ContinuousFunction.TryGetValue(futPx, out sigma)) || (!DoubleUtil.IsPositive(sigma))) { //При работе с Эксанте и прочим Западом Биржевой улыбки не будет //Поэтому надо иметь 'План Б': подставить фиксированную волатильность 30%! sigma = DefaultSigma; } if (pane != null) { string expiryStr = smileInfo.Expiry.ToString(TimeToExpiry.DateTimeFormat, CultureInfo.InvariantCulture); Rect rect = PrepareVieportSettings(expiryStr, futPx, dT, sigma); ApplySettings(pane, rect); int cpLen = smile.ControlPoints.Count; if (ManageXGridStep && (cpLen > 1)) { double dK = smile.ControlPoints[1].Anchor.ValueX - smile.ControlPoints[0].Anchor.ValueX; if (cpLen > 2) { int t = cpLen / 2; // Делим нацело. Для cpLen==3 получаем 1 dK = smile.ControlPoints[t + 1].Anchor.ValueX - smile.ControlPoints[t].Anchor.ValueX; } pane.XAxisStep = GetXAxisStep(dK); pane.XAxisDiviser = GetXAxisDivisor(dK); } } }