/// <summary> /// Gets the nearest tracker hit. /// </summary> /// <param name="series">The series.</param> /// <param name="point">The point.</param> /// <param name="snap">Snap to points.</param> /// <param name="pointsOnly">Check points only (no interpolation).</param> /// <param name="firesDistance">The distance from the series at which the tracker fires</param> /// <param name="checkDistanceBetweenPoints">The value indicating whether to check distance /// when showing tracker between data points.</param> /// <remarks> /// <paramref name="checkDistanceBetweenPoints" /> is ignored if <paramref name="pointsOnly"/> is equal to <c>False</c>. /// </remarks> /// <returns>A tracker hit result.</returns> public static TrackerHitResult GetNearestHit( Series.Series series, ScreenPoint point, bool snap, bool pointsOnly, double firesDistance, bool checkDistanceBetweenPoints) { if (series == null) { return(null); } // Check data points only if (snap || pointsOnly) { var result = series.GetNearestPoint(point, false); if (ShouldTrackerOpen(result, point, firesDistance)) { return(result); } } // Check between data points (if possible) if (!pointsOnly) { var result = series.GetNearestPoint(point, true); if (!checkDistanceBetweenPoints || ShouldTrackerOpen(result, point, firesDistance)) { return(result); } } return(null); }
/// <summary> /// Occurs when an input device begins a manipulation on the plot. /// </summary> /// <param name="e">The <see cref="OxyPlot.OxyMouseEventArgs" /> instance containing the event data.</param> public override void Started(OxyMouseEventArgs e) { base.Started(e); this.currentSeries = this.PlotView.ActualModel != null?this.PlotView.ActualModel.GetSeriesFromPoint(e.Position) : null; this.Delta(e); }
/// <summary> /// Gets the nearest tracker hit. /// </summary> /// <param name="series">The series.</param> /// <param name="point">The point.</param> /// <param name="snap">Snap to points.</param> /// <param name="pointsOnly">Check points only (no interpolation).</param> /// <returns>A tracker hit result.</returns> private static TrackerHitResult GetNearestHit(Series.Series series, ScreenPoint point, bool snap, bool pointsOnly) { if (series == null) { return(null); } // Check data points only if (snap || pointsOnly) { var result = series.GetNearestPoint(point, false); if (result != null) { if (result.Position.DistanceTo(point) < 20) { return(result); } } } // Check between data points (if possible) if (!pointsOnly) { var result = series.GetNearestPoint(point, true); return(result); } return(null); }
/// <summary> /// подсчитывает СКО /// </summary> /// <returns></returns> private double GetMathExpected(Series.Series source) { var deltaCandlesSumm = 0d; var start = source.DataCount - period; if (start < 1) { start = 1; } var count = 0; for (var j = start; j < source.DataCount; j++, count++) { var delta = source is CandlestickSeries ? ((CandlestickSeries)source).Data.Candles[j].close - ((CandlestickSeries)source).Data.Candles[j].open : (((LineSeries)source).GetPrice(j) - ((LineSeries)source).GetPrice(j - 1)) ?? 0; deltaCandlesSumm += (delta * delta); } return(count == 0 ? 0 : Math.Sqrt(deltaCandlesSumm / count)); }
/// <summary> /// Occurs when an input device begins a manipulation on the plot. /// </summary> /// <param name="e">The <see cref="OxyPlot.OxyTouchEventArgs" /> instance containing the event data.</param> public override void Started(OxyTouchEventArgs e) { base.Started(e); this.currentSeries = this.PlotView.ActualModel != null?this.PlotView.ActualModel.GetSeriesFromPoint(e.Position) : null; UpdateTracker(e.Position); }
private float GetPrice(Series.Series source, int i) { var price = source is CandlestickSeries ? ((CandlestickSeries)source).Data.Candles[i].GetPrice(priceType) : series.GetPrice(i) ?? 0; return(price); }
private void BuildIndi(Series.Series source) { if (source is IPriceQuerySeries == false) { return; } var curIndex = 0; var prevAccel = 0f; for (var j = 0; j < source.DataCount; j++) { var medianPrice = source is CandlestickSeries ? (((CandlestickSeries)source).Data.Candles[j].high + ((CandlestickSeries)source).Data.Candles[j].low) * 0.5f : (((IPriceQuerySeries)source).GetPrice(j) ?? 0); queueFast.Add(medianPrice); queueSlow.Add(medianPrice); // Если нечего рисовать то пропускаем var accelerator = 0f; /* А * добил график пустыми столбиками в начале, чтобы крайний столбик был там же, где крайняя свечка */ if (queueSlow.Length >= periodSlow) { var maSlow = queueSlow.Average(); var maFast = queueFast.Average(); //AO = SMA (MEDIAN PRICE, 5) — SMA (MEDIAN PRICE, 34) var awesome = maFast - maSlow; queueAwesomes.Add(awesome); // Собственно значение ускорения/замедления // AC = AO — SMA (AO, 5) if (queueAwesomes.Length == periodAwesome) { accelerator = awesome - queueAwesomes.Average(); } } //? Класс HistogramBar не описал но вроде он не хитрый и понятно по примеру как его юзать. Для документации достаточно описаь поля и предназначение имхо /* А * я чуть иначе раскрасил акселератор, канонически */ seriesDeltas.data.Add(new HistogramBar { color = accelerator >= prevAccel ? ClBarsPositive : ClBarsNegative, index = curIndex++, y = accelerator }); prevAccel = accelerator; } }
/// <summary> /// Occurs when a manipulation is complete. /// </summary> /// <param name="e">The <see cref="OxyPlot.OxyMouseEventArgs" /> instance containing the event data.</param> public override void Completed(OxyMouseEventArgs e) { base.Completed(e); this.currentSeries = null; this.PlotView.HideTracker(); if (this.PlotView.ActualModel != null) { this.PlotView.ActualModel.OnTrackerChanged(null); } }
/// <summary> /// Occurs when a manipulation is complete. /// </summary> /// <param name="e">The <see cref="OxyPlot.OxyTouchEventArgs" /> instance containing the event data.</param> public override void Completed(OxyTouchEventArgs e) { base.Completed(e); this.currentSeries = null; // this.PlotView.HideTracker(); if (this.PlotView.ActualModel != null) { this.PlotView.ActualModel.RaiseTrackerChanged(null); } }
private float GetPrice(Series.Series source, int i) { if (source is CandlestickSeries) { return(((CandlestickSeries)source).Data.Candles[i].GetPrice(priceType)); } if (source is IPriceQuerySeries) { return(((IPriceQuerySeries)source).GetPrice(i) ?? 0); } return(0); }
/// <summary> /// Occurs when a manipulation is complete. /// </summary> /// <param name="e">The <see cref="OxyPlot.OxyMouseEventArgs" /> instance containing the event data.</param> public override void Completed(OxyMouseEventArgs e) { base.Completed(e); e.Handled = true; this.currentSeries = null; this.PlotView.HideTracker(); if (this.PlotView.ActualModel != null) { this.PlotView.ActualModel.OnTrackerChanged(null); } }
/// <summary> /// Добавление точек в серии "seriesUp" и "seriesDown" для прорисовки линии /// </summary> private void MakeRandomWalkLine(Series.Series source) { if (source is CandlestickSeries == false && source is LineSeries == false) { return; } lastCandlestickPrice = source.DataCount > 0 ? (source is CandlestickSeries ? ((CandlestickSeries)source).Data.Candles[source.DataCount - 1].close : (((LineSeries)source).GetPrice(source.DataCount - 1) ?? 0)) : 0; seriesUp.data.Clear(); seriesDown.data.Clear(); var colorIndex = 0; var signs = new Dictionary <int, TrendLineSeries> { { 1, seriesUp }, { -1, seriesDown } }; for (var i = 0; i < percentileDeltaValues.GetLength(0); i++) // перебираем все процентили { var color = clLine[colorIndex++]; // Задаём цвет if (colorIndex >= clLine.Length) { colorIndex = 0; } for (var j = 0; j < percentileDeltaValues.GetLength(1); j++) // перебираем все дельты на порцентили { var x = source.DataCount + j - 1; foreach (var signSeries in signs) { var sign = signSeries.Key; var series = signSeries.Value; series.data.Add(MakeTrendShelf(x, lastCandlestickPrice + sign * percentileDeltaValues[i, j], color, 1)); if (j != 0) { series.data.Add(MakeTrendShelf(x, lastCandlestickPrice + sign * percentileDeltaValues[i, j - 1], color, dy: sign * percentileDeltaValues[i, j] - sign * percentileDeltaValues[i, j - 1])); } } } } }
/// <summary> /// Расчитываем дисперсию и дельты для каждой процентили. /// Если количество свечей не изменяется (а изменяется оно очень редко), то "disper" и "delta" персчитывать не нужно. Они зависят только от /// количества свечей. /// </summary> private void Calculation(Series.Series source) { var disper = GetMathExpected(source); percentileDeltaValues = new double[percentile.Length, forwardSteps]; for (var i = 0; i < percentile.Length; i++) { for (var j = 0; j < forwardSteps; j++) { percentileDeltaValues[i, j] = QNorm(percentile[i] / 100d, 0, Math.Sqrt(j + 1) * disper, true, false); } } MakeRandomWalkLine(source); }
// ReSharper disable InconsistentNaming private void BuildMA(Series.Series source) // ReSharper restore InconsistentNaming { series.Data.Clear(); float sum = 0; var frameLen = 0; for (var i = 0; i < source.DataCount; i++) { var price = GetPrice(source, i); // простая СС if (maType == MovAvgType.Простая) { sum += price; if (frameLen < period) { frameLen++; } else { sum -= GetPrice(source, i - period); } series.Data.Add(sum / frameLen); continue; } // сглаженная СС if (smmaPrev.HasValue) { var smma = ((period - 1) * smmaPrev.Value + price) / period; series.Data.Add(smma); smmaPrev = smma; } else { queue.Add(price); if (queue.Length == period) { smmaPrev = queue.Average(); } series.Data.Add(smmaPrev ?? price); } } }
private void BuildIndi(Series.Series source) { if (source is CandlestickSeries == false) { return; } var candles = ((CandlestickSeries)source).Data.Candles; var currentSign = 0; // текущая операция (покупка/продажа) var curIndex = 0; foreach (var candle in candles) { var price = candle.GetPrice(priceType); // обновить средние queueFast.Add(price); queueSlow.Add(price); // посчитать профит var delta = 0f; if (currentSign != 0) { delta = (candle.close - candle.open) * currentSign; } seriesDeltas.data.Add(new HistogramBar { color = delta >= 0 ? ClBarsPositive : ClBarsNegative, index = curIndex++, y = delta }); // определить знак if (queueSlow.Length < periodSlow) { continue; } var maSlow = queueSlow.Average(); var maFast = queueFast.Average(); var newSign = maFast > maSlow ? 1 : maFast < maSlow ? -1 : 0; if (newSign != 0) { currentSign = newSign; } } }
/// <summary> /// Occurs when the input device changes position during a manipulation. /// </summary> /// <param name="e">The <see cref="OxyPlot.OxyMouseEventArgs" /> instance containing the event data.</param> public override void Delta(OxyMouseEventArgs e) { base.Delta(e); e.Handled = true; if (this.currentSeries == null || !this.LockToInitialSeries) { // get the nearest this.currentSeries = this.PlotView.ActualModel != null?this.PlotView.ActualModel.GetSeriesFromPoint(e.Position, 20) : null; } if (this.currentSeries == null) { if (!this.LockToInitialSeries) { this.PlotView.HideTracker(); } return; } var actualModel = this.PlotView.ActualModel; if (actualModel == null) { return; } if (!actualModel.PlotArea.Contains(e.Position.X, e.Position.Y)) { return; } var result = GetNearestHit(this.currentSeries, e.Position, this.Snap, this.PointsOnly); if (result != null) { result.PlotModel = this.PlotView.ActualModel; this.PlotView.ShowTracker(result); this.PlotView.ActualModel.OnTrackerChanged(result); } }
/// <summary> /// Updates the tracker to the specified position. /// </summary> /// <param name="position">The position.</param> private void UpdateTracker(ScreenPoint position) { if (this.currentSeries == null || !this.LockToInitialSeries) { // get the nearest this.currentSeries = this.PlotView.ActualModel?.GetSeriesFromPoint(position, this.FiresDistance); } if (this.currentSeries == null) { if (!this.LockToInitialSeries) { this.PlotView.HideTracker(); } return; } var actualModel = this.PlotView.ActualModel; if (actualModel == null) { return; } if (!actualModel.PlotArea.Contains(position.X, position.Y)) { return; } var result = TrackerHelper.GetNearestHit( this.currentSeries, position, this.Snap, this.PointsOnly, this.FiresDistance, this.CheckDistanceBetweenPoints); if (result != null) { result.PlotModel = this.PlotView.ActualModel; this.PlotView.ShowTracker(result); this.PlotView.ActualModel.RaiseTrackerChanged(result); } }
/// <summary> /// Occurs when the input device changes position during a manipulation. /// </summary> /// <param name="e">The <see cref="OxyPlot.OxyMouseEventArgs" /> instance containing the event data.</param> public override void Delta(OxyMouseEventArgs e) { base.Delta(e); if (this.currentSeries == null || !this.LockToInitialSeries) { // get the nearest this.currentSeries = this.PlotView.ActualModel != null ? this.PlotView.ActualModel.GetSeriesFromPoint(e.Position, 20) : null; } if (this.currentSeries == null) { if (!this.LockToInitialSeries) { this.PlotView.HideTracker(); } return; } var actualModel = this.PlotView.ActualModel; if (actualModel == null) { return; } if (!actualModel.PlotArea.Contains(e.Position.X, e.Position.Y)) { return; } var result = GetNearestHit(this.currentSeries, e.Position, this.Snap, this.PointsOnly); if (result != null) { result.PlotModel = this.PlotView.ActualModel; this.PlotView.ShowTracker(result); this.PlotView.ActualModel.OnTrackerChanged(result); } }
/// <summary> /// Обновление положения серий "seriesUp" и "seriesDown" (смещение по y). /// </summary> private void UpdateRandomWalkLine(Series.Series source) { if (source is CandlestickSeries == false && source is LineSeries == false) { return; } if (seriesUp == null) { return; } if (seriesUp.data.Count == 0) { BuildSeries(owner); return; } var newCandlestickPrice = source is CandlestickSeries ? ((CandlestickSeries)source).Data.Candles[source.DataCount - 1].close : (((LineSeries)source).GetPrice(source.DataCount - 1) ?? 0); var deltaPrice = newCandlestickPrice - lastCandlestickPrice; for (var i = 0; i < seriesUp.data.Count; i++) { for (var j = 0; j < seriesUp.data[i].linePoints.Count; j++) { seriesUp.data[i].linePoints[j] = new PointD(seriesUp.data[i].linePoints[j].X, seriesUp.data[i].linePoints[j].Y + deltaPrice); seriesDown.data[i].linePoints[j] = new PointD(seriesDown.data[i].linePoints[j].X, seriesDown.data[i].linePoints[j].Y + deltaPrice); } } lastCandlestickPrice = newCandlestickPrice; }
/// <summary> /// Renders the legend for the specified series. /// </summary> /// <param name="rc">The render context.</param> /// <param name="s">The series.</param> /// <param name="rect">The position and size of the legend.</param> private void RenderLegend(IRenderContext rc, Series.Series s, OxyRect rect) { var actualItemAlignment = this.LegendItemAlignment; if (this.LegendOrientation == LegendOrientation.Horizontal) { // center/right alignment is not supported for horizontal orientation actualItemAlignment = HorizontalAlignment.Left; } double x = rect.Left; switch (actualItemAlignment) { case HorizontalAlignment.Center: x = (rect.Left + rect.Right) / 2; if (this.LegendSymbolPlacement == LegendSymbolPlacement.Left) { x -= (this.LegendSymbolLength + this.LegendSymbolMargin) / 2; } else { x -= (this.LegendSymbolLength + this.LegendSymbolMargin) / 2; } break; case HorizontalAlignment.Right: x = rect.Right; // if (LegendSymbolPlacement == LegendSymbolPlacement.Right) x -= this.LegendSymbolLength + this.LegendSymbolMargin; break; } if (this.LegendSymbolPlacement == LegendSymbolPlacement.Left) { x += this.LegendSymbolLength + this.LegendSymbolMargin; } double y = rect.Top; var maxsize = new OxySize(Math.Max(rect.Width - this.LegendSymbolLength - this.LegendSymbolMargin, 0), rect.Height); var actualLegendFontSize = double.IsNaN(this.LegendFontSize) ? this.PlotModel.DefaultFontSize : this.LegendFontSize; var legendTextColor = s.IsVisible ? this.LegendTextColor : this.SeriesInvisibleTextColor; rc.SetToolTip(s.ToolTip); var textSize = rc.DrawMathText( new ScreenPoint(x, y), s.Title, legendTextColor.GetActualColor(this.PlotModel.TextColor), this.LegendFont ?? this.PlotModel.DefaultFont, actualLegendFontSize, this.LegendFontWeight, 0, actualItemAlignment, VerticalAlignment.Top, maxsize, true); this.SeriesPosMap.Add(s, new OxyRect(new ScreenPoint(x, y), textSize)); double x0 = x; switch (actualItemAlignment) { case HorizontalAlignment.Center: x0 = x - (textSize.Width * 0.5); break; case HorizontalAlignment.Right: x0 = x - textSize.Width; break; } if (s.IsVisible) { var symbolRect = new OxyRect( this.LegendSymbolPlacement == LegendSymbolPlacement.Right ? x0 + textSize.Width + this.LegendSymbolMargin : x0 - this.LegendSymbolMargin - this.LegendSymbolLength, rect.Top, this.LegendSymbolLength, textSize.Height); s.RenderLegend(rc, symbolRect); } rc.SetToolTip(null); }
/// <summary> /// Occurs when an input device begins a manipulation on the plot. /// </summary> /// <param name="e">The <see cref="OxyPlot.OxyTouchEventArgs" /> instance containing the event data.</param> public override void Started(OxyTouchEventArgs e) { base.Started(e); this.currentSeries = this.PlotView.ActualModel != null ? this.PlotView.ActualModel.GetSeriesFromPoint(e.Position) : null; UpdateTracker(e.Position); }
private Dictionary <string, double> GetVariableValues(int index, Series.Series seriesSrc, int dataCount, List <string> variableNames, string[] tickerNames) { var varValues = new Dictionary <string, double>(); if (variableNames == null) { return(new Dictionary <string, double>()); } // специальные имена переменных: // open, low, high, close - текущие OHLC-уровни для свечной серии // для серий типа LineSeries доступен только close // close#2 - цена два бара назад // i - индекс текущей свечи // count - количество данных в основном ряду // year, month, day, weekday, hour, minute, second // eurusd, audjpy#100 - close соотв. валютной пары // random - равномерно распред. СЧ на интервале 0..1 // переменные с неизвестными именами инициализируются нулями foreach (var name in variableNames) { var variableName = name; if (name == "i") { varValues.Add(name, index); continue; } if (name == "count") { varValues.Add(name, dataCount); continue; } var tickerName = tickerNames.FirstOrDefault(tn => variableName.StartsWith(tn, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrEmpty(tickerName)) {// котировка var price = 1.0; if (tickerData.ContainsKey(tickerName)) { var tickerQuotes = tickerData[tickerName]; if (tickerQuotes.Count > 0) { var datIndex = index - GetDeltaIndexFromSharpSeparatedString(variableName); datIndex = datIndex < 0 ? 0 : datIndex >= tickerQuotes.Count ? tickerQuotes.Count - 1 : datIndex; price = tickerQuotes[datIndex]; } } varValues.Add(name, price); continue; } if (name == "random") { varValues.Add(name, randomGener.NextDouble()); continue; } if (name.StartsWith("year") || name.StartsWith("month") || name.StartsWith("day") || name.StartsWith("weekday") || name.StartsWith("hour") || name.StartsWith("minute") || name.StartsWith("second")) { // получить дату текущей либо одной из предыдущих точек графика var datIndex = index - GetDeltaIndexFromSharpSeparatedString(name); var curDate = DateTime.Now; if (seriesSrc is StockSeries) { if (datIndex >= 0 && datIndex < ((StockSeries)seriesSrc).Data.Count) { curDate = ((StockSeries)seriesSrc).Data.Candles[datIndex].timeOpen; } } else { if (datIndex >= 0 && datIndex < owner.StockSeries.Data.Count) { curDate = owner.StockSeries.Data.Candles[datIndex].timeOpen; } } if (name.StartsWith("year")) { varValues.Add(name, curDate.Year); } else if (name.StartsWith("month")) { varValues.Add(name, curDate.Month); } else if (name.StartsWith("day")) { varValues.Add(name, curDate.Day); } else if (name.StartsWith("weekday")) { varValues.Add(name, (int)curDate.DayOfWeek); } else if (name.StartsWith("hour")) { varValues.Add(name, curDate.Hour); } else if (name.StartsWith("minute")) { varValues.Add(name, curDate.Minute); } else if (name.StartsWith("second")) { varValues.Add(name, curDate.Second); } continue; } if (name.StartsWith("close") || name.StartsWith("open") || name.StartsWith("low") || name.StartsWith("high")) {// "close", "close#17" ... var datIndex = index - GetDeltaIndexFromSharpSeparatedString(name); // вытащить данные из серии if (seriesSrc is StockSeries) { var candles = ((StockSeries)seriesSrc).Data.Candles; if (datIndex < 0 || datIndex >= candles.Count) { varValues.Add(name, 0); continue; } if (name.StartsWith("open")) { varValues.Add(name, (double)candles[datIndex].open); } else if (name.StartsWith("high")) { varValues.Add(name, (double)candles[datIndex].high); } else if (name.StartsWith("low")) { varValues.Add(name, (double)candles[datIndex].low); } else if (name.StartsWith("close")) { varValues.Add(name, (double)candles[datIndex].close); } } if (seriesSrc is LineSeries) { var serLine = (LineSeries)seriesSrc; if (datIndex < 0 || datIndex >= serLine.Data.Count) { varValues.Add(name, 0); continue; } varValues.Add(name, serLine.Data[datIndex]); } continue; } if (name.StartsWith("src")) { var dotIndex = name.IndexOf('.'); var seriesName = dotIndex != -1 ? name.Substring(3, dotIndex - 2) : name.Substring(3); var seriesIndex = seriesName.ToInt(0); if (seriesIndex == 0) { varValues.Add(name, 0); continue; } seriesIndex--; if (seriesIndex < 0 || seriesIndex >= SeriesSources.Count) { varValues.Add(name, 0); continue; } var series = SeriesSources[seriesIndex]; var dataIndex = index - GetDeltaIndexFromSharpSeparatedString(name); var stockSeries = series as StockSeries; if (stockSeries != null) { var candles = stockSeries.Data.Candles; if (dataIndex < 0 || dataIndex >= candles.Count) { varValues.Add(name, 0); continue; } var candleValue = dotIndex != -1 ? name.Substring(dotIndex + 1) : ""; if (candleValue == "open") { varValues.Add(name, candles[dataIndex].open); } else if (candleValue == "high") { varValues.Add(name, candles[dataIndex].high); } else if (candleValue == "low") { varValues.Add(name, candles[dataIndex].low); } else // "close" & default { varValues.Add(name, candles[dataIndex].close); } continue; } var lineSeries = series as LineSeries; if (lineSeries != null) { if (dataIndex < 0 || dataIndex >= lineSeries.Data.Count) { varValues.Add(name, 0); continue; } varValues.Add(name, lineSeries.Data[dataIndex]); continue; } varValues.Add(name, 0); continue; } // переменная не определена вообще - инициализируем 0-м varValues.Add(name, 0); } return(varValues); }
private void BuildSeries(ChartControl chart, bool shouldLoadTickers) { if (DrawPane != owner.StockPane) { DrawPane.Title = UniqueName; } seriesLine.Data.Clear(); Series.Series seriesSrc = chart.StockSeries; var dataCount = seriesSrc is StockSeries ? ((StockSeries)seriesSrc).Data.Count : seriesSrc is LineSeries ? ((LineSeries)seriesSrc).Data.Count : 0; var varNames = new List <string>(); foreach (var resv in resolvers) { if (resv == null) { continue; } var resvVars = resv.GetVariableNames(); foreach (var varName in resvVars.Where(varName => !varNames.Contains(varName))) { varNames.Add(varName); } } randomGener = new Random(DateTime.Now.Millisecond); if (shouldLoadTickers) { LoadTickers(varNames); } var tickerNames = DalSpot.Instance.GetTickerNames(); bool hasResolvers = resolvers.Any(resv => resv != null); for (var i = 0; i < dataCount; i++) { if (!hasResolvers) { seriesLine.Data.Add(0); continue; } var values = GetVariableValues(i, seriesSrc, dataCount, varNames, tickerNames); // выражение содержит "переменную", которая нигде не определена if (values.Count == 0 && varNames.Count > 0) { seriesLine.Data.Add(0); continue; } double totalResult = 0; for (var j = 0; j < resolvers.Length; j++) { if (resolvers[j] == null) { continue; } double result; if (!resolvers[j].Calculate(values, out result)) { result = SubstituteNaN ?? 0; } if (SubstituteNegInfinite.HasValue && double.IsNegativeInfinity(result)) { result = SubstituteNegInfinite.Value; } else if (SubstituteInfinite.HasValue && double.IsInfinity(result)) { result = SubstituteInfinite.Value; } // обновляем список переменных var resultFuncName = string.Format("fn{0}", j + 1); if (values.ContainsKey(resultFuncName)) { values[resultFuncName] = result; } else { values.Add(resultFuncName, result); } // сохраняем последний результат totalResult = result; } seriesLine.Data.Add(totalResult); } }
/// <summary> /// Occurs when an input device begins a manipulation on the plot. /// </summary> /// <param name="e">The <see cref="OxyPlot.OxyMouseEventArgs" /> instance containing the event data.</param> public override void Started(OxyMouseEventArgs e) { base.Started(e); this.currentSeries = this.PlotView.ActualModel != null ? this.PlotView.ActualModel.GetSeriesFromPoint(e.Position) : null; this.Delta(e); }
/// <summary> /// Updates the tracker to the specified position. /// </summary> /// <param name="position">The position.</param> private void UpdateTracker(ScreenPoint position) { if (this.currentSeries == null || !this.LockToInitialSeries) { // get the nearest this.currentSeries = this.PlotView.ActualModel != null ? this.PlotView.ActualModel.GetSeriesFromPoint(position, 20) : null; } if (this.currentSeries == null) { if (!this.LockToInitialSeries) { this.PlotView.HideTracker(); } return; } var actualModel = this.PlotView.ActualModel; if (actualModel == null) { return; } if (!actualModel.PlotArea.Contains(position.X, position.Y)) { return; } var result = GetNearestHit(this.currentSeries, position, this.Snap, this.PointsOnly); if (result != null) { result.PlotModel = this.PlotView.ActualModel; this.PlotView.ShowTracker(result); this.PlotView.ActualModel.RaiseTrackerChanged(result); } }
private void BuildBollinger(Series.Series source) { series.Data.Clear(); seriesUp.Data.Clear(); seriesDn.Data.Clear(); if (source is CandlestickSeries == false && source is LineSeries == false) { return; } float sum = 0; var frameLen = 0; for (var i = 0; i < source.DataCount; i++) { var price = GetPrice(source, i); // простая СС if (MaType == MovAvgType.Простая) { sum += price; if (frameLen < period) { frameLen++; } else { sum -= GetPrice(source, i - period); } series.Data.Add(sum / frameLen); } // сглаженная СС else { if (smmaPrev.HasValue) { var smma = ((period - 1) * smmaPrev.Value + price) / period; series.Data.Add(smma); smmaPrev = smma; } else { queue.Add(price); if (queue.Length == period) { smmaPrev = queue.Average(); } series.Data.Add(smmaPrev ?? price); } } // волатильность (СКО) // очередь из квадратов отклонений var lastMedian = series.Data[series.Data.Count - 1]; var dev = lastMedian - price; queueDisper.Add((float)(dev * dev)); var ssd = queueDisper.Length == period ? Math.Sqrt(queueDisper.Average()) : 0; seriesUp.Data.Add(lastMedian + KVolatile * ssd); seriesDn.Data.Add(lastMedian - KVolatile * ssd); } }