Exemplo n.º 1
0
        public void BuildSeries(ChartControl chart)
        {
            var commentText = GetStatText();
            if (string.IsNullOrEmpty(commentText)) return;
            var candles = chart.StockSeries.Data.Candles;

            // добавить комментарий с текстом
            var series = chart.Owner.seriesComment;
            var indiTitle = MakeCommentTitle();
            var comment = series.data.FirstOrDefault(c => c.Magic == CommentMagic && c.Text.StartsWith(indiTitle));
            if (comment != null)
            {
                comment.Text = commentText;
                return;
            }

            // таки создать новый комментарий
            comment = new ChartComment
                {
                    ArrowAngle = nextAngle,
                    ArrowLength = 50,
                    Magic = CommentMagic,
                    Text = commentText,
                    Owner = series,
                    PivotIndex = candles.Count - 1,
                    PivotPrice = candles[candles.Count - 1].open,
                };
            nextAngle += 45;
            series.data.Add(comment);
        }
Exemplo n.º 2
0
        public DropDownWindowPopup(ChartControl ownerChart)
        {
            Margin = Padding.Empty;
            Padding = Padding.Empty;
            AutoSize = false;

            var window = new SummaryPositionDropWindow(ownerChart.Owner)
            {
                Parent = ownerChart
            };

            Width = window.Width;
            Height = window.Height;
            window.closeControl += Close;
            Closing += (sender, args) =>
            {
                if (window.isPinup) args.Cancel = true;
            };

            var host = new ToolStripControlHost(window)
            {
                Margin = Padding.Empty,
                Padding = Padding.Empty,
                AutoSize = false
            };
            Items.Add(host);
        }
Exemplo n.º 3
0
 public TurnBar(List<int> candles, bool isKeyBar, ChartControl owner)
 {
     this.owner = owner;
     candleIndexes = candles;
     IsKeyBar = isKeyBar;
     Name = string.Format("{0} {1}", ClassName, nextObjectNumber++);
 }
Exemplo n.º 4
0
 public void BuildSeries(ChartControl chart)
 {
     if (DrawPane != owner.StockPane)
         DrawPane.Title = string.Format("{0} [{1}]", UniqueName, Period);
     seriesRatio.Data.Clear();
     BuildERatioMarker();
 }
Exemplo n.º 5
0
 public TurnBar(TurnBar bar)
 {
     owner = bar.owner;
     IsKeyBar = bar.IsKeyBar;
     Name = bar.Name;
     candleIndexes = new List<int>();
     candleIndexes.AddRange(bar.candleIndexes);
 }
Exemplo n.º 6
0
 public Pane(string name, ChartControl owner)
 {
     Name = name;
     Owner = owner;
     paneFrame = new PaneFrame(this);
     yAxis = new YAxis(this);
     series = new SeriesCollection(this);
     ResetWorldRect(false);
 }
Exemplo n.º 7
0
        public void BuildSeries(ChartControl chart)
        {
            series.Data.Clear();

            var sources = (StockSeries)SeriesSources[0];
            var candles = sources.Data.Candles;
            if (candles.Count == 0 || Period == 0 || candles.Count <= Period) return;

            var periodRoot = Math.Sqrt(period);
            double totalPath = 0, totalPathPredicted = 0;
            var deltas = new float[period];

            for (var j = period + 1; j < candles.Count; j++)
            {
                // вычисляю изменение цены
                //var averageChange = (candles[j].close - candles[j - Period].close) / Period;
                //float overall = 0;
                //dispers = 0;
                //for (var i = j - period; i <= j; i++)
                //{
                //    overall += Math.Abs((candles[i].close - candles[i - 1].close) - averageChange);
                //}
                float avg = 0;
                for (var i = 0; i < period; i++)
                {
                    var delta = (candles[j - i].close - candles[j - i - 1].close) / candles[j - i - 1].close;
                    deltas[i] = delta;
                    avg += avg;
                }
                avg /= period;

                double overall = 0;
                for (var i = 0; i < period; i++)
                    overall += (deltas[i] - avg) * (deltas[i] - avg);
                overall /= period;

                var sigma = Math.Sqrt(overall);
                series.Data.Add(sigma * 100);

                var priceDelta = Math.Abs(candles[j].close - candles[j - period].close);
                var predictedDelta = periodRoot * sigma;
                totalPath += priceDelta;
                totalPathPredicted += predictedDelta;
            }

            var countSteps = candles.Count - period - 1;
            if (countSteps > 0)
            {
                totalPath /= countSteps;
                totalPathPredicted /= countSteps;
                TradeSharp.Util.Logger.InfoFormat("path is: {0:f5}, predicted value: {1:f5}",
                    totalPath, totalPathPredicted);
            }
        }
Exemplo n.º 8
0
 public void Add(ChartControl chart, Pane ownerPane)
 {
     owner = chart;
     series = new LineSeries("price changes")
     {
         LineColor = ColorLine,
         ShiftX = Period + 1
     };
     SeriesResult = new List<Series.Series> { series };
     EntitleIndicator();
 }
Exemplo n.º 9
0
 public Pane(string name, ChartControl owner, string backgroundImageName)
 {
     Name = name;
     Owner = owner;
     paneFrame = new PaneFrame(this);
     yAxis = new YAxis(this);
     series = new SeriesCollection(this);
     ResetWorldRect(false);
     BackgroundImageResourceName = backgroundImageName;
     if (!string.IsNullOrEmpty(BackgroundImageResourceName))
         LoadBackImage(backgroundImageName);
 }
Exemplo n.º 10
0
 public void Add(ChartControl chart, Pane ownerPane)
 {
     owner = chart;
     seriesRatio = new LineSeries("E-Ratio")
     {
         LineColor = Color.Blue,
         ShiftX = 1,
         MarkerSpanPoints = 2,
         MinPixelsBetweenMarkers = 10
     };
     SeriesResult = new List<Series.Series> { seriesRatio };
     // инициализируем индикатор
     EntitleIndicator();
 }
Exemplo n.º 11
0
        public DealMarker(ChartControl owner, List<DealMarker> markers,
            DealMarkerType markerType, DealType side, 
            double candleIndex, double price, DateTime time)
        {
            this.markers = markers;
            var maxId = markers.Count == 0 ? 0 : markers.Max(m => m.id);
            if (nextNumber <= maxId) nextNumber = maxId + 1;
            id = nextNumber++;

            Name = string.Format("{0} {1}", ClassName, id);
            this.owner = owner;
            MarkerType = markerType;
            this.candleIndex = candleIndex;
            Price = price;
            DateStart = time;
            this.side = side;
        }
Exemplo n.º 12
0
 public DealMarker(ChartControl owner, List<DealMarker> markers)
 {
     this.markers = markers;
     this.owner = owner;
 }
Exemplo n.º 13
0
 public void GetStateFromChartObject(ChartControl chart)
 {
     if (getStateFromChart != null)
         IconChecked = getStateFromChart(chart);
 }
 public ChartVisualSettings(ChartControl owner)
 {
     this.owner = owner;
     ApplyTheme();
 }
Exemplo n.º 15
0
        public void BuildSeries(ChartControl chart)
        {
            series.data.Clear();
            //var candles = chart.StockSeries.Data.Candles;

            if (SeriesSources[0].GetType() == typeof(CandlestickSeries))
            {
                var candles = ((StockSeries) SeriesSources[0]).Data.Candles;
                if (candles.Count < period) return;

                for (var i = period; i < candles.Count; i += period)
                {
                    var turtle = new TrendLine
                                     {
                                         LineColor = clLine,
                                         ShapeAlpha = 128,
                                         ShapeFillColor = Color.Green,
                                         LineStyle = Shape == IndicatorShape.Черепаха ?
                                            TrendLine.TrendLineStyle.Черепаха : TrendLine.TrendLineStyle.Пэкмен
                                     };
                    turtle.AddPoint(i - period, (double) candles[i - period].open);
                    turtle.AddPoint(i, (double) candles[i].close);
                    series.data.Add(turtle);
                }
            }
            else
            {
                if (SeriesSources[0].GetType()== typeof(LineSeries))
                {
                    var candles = ((LineSeries)SeriesSources[0]).Data;
                    if (candles.Count < period) return;

                    for (var i = period; i < candles.Count; i += period)
                    {
                        var turtle = new TrendLine
                        {
                            LineColor = clLine,
                            ShapeAlpha = 128,
                            ShapeFillColor = Color.Green,
                            LineStyle = Shape == IndicatorShape.Черепаха ?
                                TrendLine.TrendLineStyle.Черепаха : TrendLine.TrendLineStyle.Пэкмен
                        };
                        turtle.AddPoint(i - period, (double)candles[i - period]);
                        turtle.AddPoint(i, (double)candles[i]);
                        series.data.Add(turtle);
                    }
                }
            }
        }
Exemplo n.º 16
0
        public void Add(ChartControl chart, Pane ownerPane)
        {
            owner = chart;
            // инициализируем индикатор
            MainLine = new LineSeries(Name + " Main")
            {
                LineColor = LineColor1,
                Transparent = true,
                ShiftX = 1,
                DrawShadow = DrawShadow,
                ShadowWidth = ShadowWidth,
                ShadowColor = Color.Gray,
                ShadowAlpha = ShadowAlpha,
            };
            SignalLine = new LineSeries(Name + " Signal")
            {
                LineColor = LineColor2,
                Transparent = true,
                ShiftX = 1,
                DrawShadow = DrawShadow,
                ShadowWidth = ShadowWidth,
                ShadowColor = Color.Gray,
                ShadowAlpha = ShadowAlpha,
            };
            FastEMALine = new SeriesData();
            SlowEMALine = new SeriesData();

            SeriesResult = new List<Series.Series> { MainLine, SignalLine};
            EntitleIndicator();
        }
Exemplo n.º 17
0
        public void BuildSeries(ChartControl chart)
        {
            seriesRSI.Data.Clear();
            seriesBound.data.Clear();
            // границы
            var reg = new BarRegion { Color = Color.Black, UpperBound = 100 - marginPercent, LowerBound = marginPercent };
            seriesBound.data.Add(reg);
            // RSI
            for (var i = 0; i < Period; i++)
                seriesRSI.Data.Add(50);

            var dataCount = GetSourceDataCount();
            for (var i = Period; i < dataCount; i++)
            {
                double sumU = 0, sumD = 0;
                for (var j = 0; j < Period; j++)
                {
                    var delta = GetSourcePrice(i - j)
                                - GetSourcePrice(i - j - 1);
                    if (delta < 0) sumD -= delta;
                    else sumU += delta;
                }
                double RSI;
                if (sumU == sumD && sumU == 0) RSI = 50;
                else if (sumD == 0) RSI = 100;
                else
                    RSI = 100 - 100.0 / (1 + sumU / sumD);
                seriesRSI.Data.Add(RSI);
            }
        }
Exemplo n.º 18
0
 public void BuildSeries(ChartControl chart)
 {
     var ticker = GetTickerName();
     if (string.IsNullOrEmpty(ticker)) return;
     LoadCMEData(ticker);
 }
Exemplo n.º 19
0
 public void Add(ChartControl chart, Pane ownerPane)
 {
     owner = chart;
     SeriesResult = new List<Series.Series> { /*seriesComment*/ };
     EntitleIndicator();
 }
Exemplo n.º 20
0
        public void BuildSeries(ChartControl chart)
        {
            if (DrawPane != owner.StockPane)
                DrawPane.Title = UniqueName;
            indSeriesRenco.Data.Clear();
            if (SeriesSources.Count == 0) return;
            int dataCount = GetSourceDataCount();
            if (dataCount == 0) return;

            indSeriesRenco.DownFillColor = ColorBarDn;
            indSeriesRenco.UpFillColor = ColorBarUp;
            indSeriesRenco.BarNeutralColor = !TransparentEmptyBricks ? ColorBarEmpty : Color.Empty;
            indSeriesRenco.UpLineColor = ColorOutlineUp;
            indSeriesRenco.DownLineColor = ColorOutlineDn;

            int rencoBrickSize = RencoSize;
            var rencoSizeAbs = (double)DalSpot.Instance.GetAbsValue(chart.Symbol, (float)rencoBrickSize);
            // начальный кирпич
            var startPrice = 0.0;
            var seriesSrc = SeriesSources[0];
            if (seriesSrc is CandlestickSeries)
                startPrice = ((CandlestickSeries)seriesSrc).Data[0].open;
            else
                if (seriesSrc is LineSeries)
                    startPrice = ((LineSeries) seriesSrc).Data[0];
            var startClose = GetSourcePrice(0, 0);

            var rencoBricks = new List<RencoBrick>
                                  {
                                      new RencoBrick {open = startPrice, close = startClose, index = -1}
                                  };

            // классический Ренко - кирпичеги не привязаны ко времени
            // привязка будет ниже
            for (var i = 0; i < dataCount; i++)
            {
                var brickSize = rencoSizeAbs;
                if (BrickSizeAuto)
                    if ((VolatilityType == RencoVolatilityType.ATR && seriesSrc is CandlestickSeries) ||
                        VolatilityType == RencoVolatilityType.Размах)
                        brickSize = GetRencoBrickAutoSizeAbs(rencoSizeAbs, i);

                var lastBrick = rencoBricks[rencoBricks.Count - 1];
                var lastSign = lastBrick.close >= lastBrick.open ? 1 : -1;
                var price = GetSourcePrice(i, 0);

                var deltaClose = (int)((price - lastBrick.close) / brickSize);
                var deltaOpen = (int)((price - lastBrick.open) / brickSize);

                if (deltaClose != 0 && Math.Sign(deltaClose) == lastSign)
                    AddRencoBricks(rencoBricks, i, deltaClose, brickSize, lastBrick.close);
                else
                    if (deltaOpen != 0 && Math.Sign(deltaOpen) != lastSign)
                        AddRencoBricks(rencoBricks, i, deltaOpen, brickSize, lastBrick.open);
            }

            // Ренко в масштабе времени
            // (добивается пустотелыми кирпичами)
            var currentRencoIndex = 0;
            var currentSign = 0;
            float lastClose = 0;
            var candles = owner.StockSeries.Data.Candles;

            for (var i = 0; i < dataCount; i++)
            {
                if (i >= candles.Count) return;
                var candleHasBody = false;
                while (currentRencoIndex < (rencoBricks.Count - 1))
                {
                    if (rencoBricks[currentRencoIndex + 1].index != i) break;
                    candleHasBody = true;
                    currentSign = rencoBricks[currentRencoIndex + 1].close >
                                  rencoBricks[currentRencoIndex + 1].open
                                      ? 1
                                      : -1;
                    currentRencoIndex++;
                }
                var newClose = lastClose + currentSign * RencoSize;
                var candle = new CandleData(lastClose,
                                            Math.Max(newClose, lastClose),
                                            Math.Min(newClose, lastClose),
                                            newClose,
                                            candles[i].timeOpen,
                                            candles[i].timeClose);
                if (!candleHasBody) candle.customColor = Color.Empty;
                indSeriesRenco.Data.Candles.Add(candle);
                lastClose = newClose;
            }
            // поднять по оси У
            var minY = indSeriesRenco.Data.Candles.Min(c => c.close);
            if (minY < 0)
            {
                for (var i = 0; i < indSeriesRenco.Data.Candles.Count; i++)
                {
                    indSeriesRenco.Data.Candles[i].open -= minY;
                    indSeriesRenco.Data.Candles[i].close -= minY;
                    indSeriesRenco.Data.Candles[i].high -= minY;
                    indSeriesRenco.Data.Candles[i].low -= minY;
                }
            }
        }
Exemplo n.º 21
0
 public void Add(ChartControl chart, Pane ownerPane)
 {
     owner = chart;
     indSeriesRenco = new CandlestickSeries(Name) {DownFillColor = ColorBarDn, UpFillColor = ColorBarUp};
     SeriesResult = new List<Series.Series> { indSeriesRenco };
     EntitleIndicator();
 }
Exemplo n.º 22
0
        public void BuildSeries(ChartControl chart)
        {
            SignalLine.Data.Clear();
            MainLine.Data.Clear();
            FastEMALine.Clear();
            SlowEMALine.Clear();
            var start = Math.Max(FastEMA, SlowEMA);
            for (var j = 0; j < start; j++)
            {
                FastEMALine.Add(GetSourcePrice(j));
                SlowEMALine.Add(GetSourcePrice(j));
                SignalLine.Data.Add(0);
                MainLine.Data.Add(0);
            }

            var dataCount = GetSourceDataCount();
            if (dataCount < start) return;
            var i = start;
            var sum = 0.0d;
            while ( i < dataCount)
            {
                // вычисляем главную линию
                // FastEma
                FastEMALine.Add(FastEMALine[i - 1] + (2.0d / (FastEMA + 1) * (GetSourcePrice(i) - FastEMALine[i - 1])));
                // SlowEma
                SlowEMALine.Add(SlowEMALine[i - 1] + (2.0d / (SlowEMA + 1) * (GetSourcePrice(i) - SlowEMALine[i - 1])));
                // сама главная линия
                MainLine.Data.Add(FastEMALine[i] - SlowEMALine[i]);
                // Рассчитываем сигнальную линию
                sum = 0.0d;
                for (var j = 0; j < SignalSMA; j++)
                    sum += (MainLine.Data[i - j]);
                SignalLine.Data.Add(sum / SignalSMA);
                i++;
            }
        }
Exemplo n.º 23
0
 public void Add(ChartControl chart, Pane ownerPane)
 {
     owner = chart;
     // инициализируем индикатор
     spans = new ProjectionSeries(Localizer.GetString("TitleProjections"));
     SeriesResult = new List<Series.Series> { spans };
     EntitleIndicator();
 }
Exemplo n.º 24
0
 public void Add(ChartControl chart, Pane ownerPane)
 {
     owner = chart;
     seriesMargins = new RegionSeries(Localizer.GetString("TitleExtremaBordes")) {CustomAlphaChannel = true};
     seriesExtr = new TrendLineSeries(Localizer.GetString("TitleExtrema"));
     SeriesResult = new List<Series.Series> { seriesMargins, seriesExtr };
     EntitleIndicator();
 }
Exemplo n.º 25
0
        /// <summary>
        /// от двух пар последних точек ЗЗ построить проекции
        /// </summary>
        public void BuildSeries(ChartControl chart)
        {
            spans.data.Clear();
            //spans.ExtendYAxis = ExtendChartBounds;
            // получить точки Зиг-Зага
            var pivots = ZigZag.GetPivots(chart.StockSeries.Data.Candles, ThresholdPercent, ZigZagSourceType);
            if (pivots.Count < 3) return;
            // построить проекции
            var pointA = pivots[pivots.Count - 3];
            var pointB = pivots[pivots.Count - 2];
            var pointC = pivots[pivots.Count - 1];

            var spanA = new ProjectionPair(pointA.a, pointA.b)
                            {
                                HideFarParts = false,
                                Color = pointB.b > pointA.b ? ColorLineLower : ColorLineUpper,
                                ProjectionLength = ProjectionBars,
                                LevelsProj = LevelsProj,
                                Markers = Markers
                            };

            spanA.AddPoint(pointB.a, pointB.b);
            var spanB = new ProjectionPair(pointB.a, pointB.b)
                            {
                                HideFarParts = false,
                                Color = pointB.b < pointA.b ? ColorLineLower : ColorLineUpper,
                                ProjectionLength = ProjectionBars,
                                LevelsProj = LevelsProj,
                                Markers = Markers
                            };
            spanB.AddPoint(pointC.a, pointC.b);
            spans.data.Add(spanA);
            spans.data.Add(spanB);
            // коррекции?
            if (!CorrectionEnabled) return;
            if (correctionBcLength > 0)
            {
                var spanC = new ProjectionPair(pointB.a, pointB.b)
                                {
                                    HideFarParts = false,
                                    Color = pointB.b < pointA.b ? ColorLineLower : ColorLineUpper,
                                    ProjectionLength = CorrectionBcLength,
                                    LevelsCorr = LevelsCorr,
                                    IsExtension = false,
                                    IsCorrection = true,
                                    Markers = Markers
                                };
                spanC.AddPoint(pointC.a, pointC.b);
                spans.data.Add(spanC);
            }
            if (correctionAbLength > 0)
            {
                var spanC = new ProjectionPair(pointA.a, pointA.b)
                {
                    HideFarParts = false,
                    Color = pointB.b < pointA.b ? ColorLineLower : ColorLineUpper,
                    ProjectionLength = CorrectionAbLength,
                    LevelsCorr = LevelsCorr,
                    IsExtension = false,
                    IsCorrection = true,
                    Markers = Markers
                };
                spanC.AddPoint(pointB.a, pointB.b);
                spans.data.Add(spanC);
            }
        }
Exemplo n.º 26
0
        public void BuildSeries(ChartControl chart)
        {
            seriesMargins.data.Clear();
            seriesExtr.data.Clear();
            // нарисовать границы
            if (ShowMarginZones)
            {
                seriesMargins.data.Add(new BarRegion
                                              {
                                                  Color = Color.FromArgb(40, Color.Green),
                                                  UpperBound = 900000,
                                                  LowerBound = (float)margUpper
                                              });
                seriesMargins.data.Add(new BarRegion
                                              {
                                                  Color = Color.FromArgb(40, Color.Maroon),
                                                  UpperBound = (float)margLower,
                                                  LowerBound = -900000
                                              });
            }
            // рисовать палочки экстремумов
            if (!ShowBars) return;
            if (SeriesSources.Count == 0) return;

            var srcCount = GetSourceDataCount();
            srcCount = Math.Min(owner.StockSeries.Data.Count, srcCount);

            if (ExtremumType == ExtremumSearchType.КвазиЭкстремумы)
                BuildQuasiExtremums(srcCount);
            else
                if (ExtremumType == ExtremumSearchType.Классические)
                    BuildClassicExtremums(srcCount);
        }
Exemplo n.º 27
0
 public void Add(ChartControl chart, Pane ownerPane)
 {
     owner = chart;
     // инициализируем индикатор
     seriesRSI = new LineSeries(Name)
     {
         LineColor = LineColor,
         Transparent = true,
         ShiftX = 1,
         DrawShadow = DrawShadow,
         ShadowWidth = ShadowWidth,
         ShadowColor = Color.Gray,
         ShadowAlpha = ShadowAlpha,
     };
     seriesBound = new RegionSeries(Localizer.GetString("TitleRSIBorders")) { DrawAsFrame = true };
     SeriesResult = new List<Series.Series> { seriesRSI, seriesBound };
     EntitleIndicator();
 }
        public void BuildSeries(ChartControl chart)
        {
            seriesTrendLine.data.Clear();
            // актуализировать серии-источники
            ActualizeSeries();
            // по каждой паре серий строить диверы и переводить их Х
            // координаты в масштаб графика (если ТФ отличаются)
            var signs = new Dictionary<int, List<DiverMarker>>();
            foreach (var src in sets)
            {
                if (src.seriesDest == null || src.seriesSrc == null) continue;
                if (src.seriesDest.isDisposed || src.seriesSrc.isDisposed) continue;
                if (src.seriesDest is IPriceQuerySeries == false ||
                    src.seriesSrc is IPriceQuerySeries == false) continue;
                BuildDivers(src, signs);
            }

            // отобразить
            foreach (var pair in signs)
            {
                var markers = pair.Value;
                var index = pair.Key;
                var sign = Math.Sign(markers.Sum(m => m.sign));
                if (sign == 0) sign = markers[0].sign;
                var price = (double)(owner.StockSeries.GetPrice(index) ?? 0);

                var text = string.Join(", ",
                    markers.Select(m => string.Format("{0}:{1}", m.title, m.sign > 0 ? '^' : 'v')));

                var line = new TrendLine
                {
                    LineStyle = TrendLine.TrendLineStyle.СвечнаяСтрелка,
                    LineColor = sign > 0 ? ColorArrowUp : ColorArrowDown,
                    ShapeAlpha = 192,
                    ShapeFillColor = sign > 0 ? ColorArrowUp : ColorArrowDown,
                    Comment = text
                };
                line.AddPoint(index, price - sign * price * 0.01);
                line.AddPoint(index, price);
                seriesTrendLine.data.Add(line);
            }
        }
Exemplo n.º 29
0
        public void Add(ChartControl chart, Pane ownerPane)
        {
            owner = chart;
            // инициализируем индикатор
            mainLine = new TrendLineSeries(Name);

            SeriesResult = new List<Series.Series> { mainLine };
            EntitleIndicator();
        }
Exemplo n.º 30
0
        public void BuildSeries(ChartControl chart)
        {
            mainLine.data.Clear();

            var candles = chart.StockSeries.Data.Candles;
            if (candles == null || candles.Count < 5) return;

            var sar = candles[0].high;
            float h = candles[0].high, l = candles[0].low;
            var trend = -1;
            var trendLength = 0;

            AddLinePoint(0, sar);

            for (var i = 1; i < candles.Count; i++)
            {
                var candle = candles[i];
                if (trend < 0 && candle.high > sar)
                {
                    // разворот
                    trend = 1;
                    sar = candle.low;
                    l = candle.low;
                    h = candle.high;
                    trendLength = 0;
                } else if (trend > 0 && candle.low < sar)
                {
                    // разворот
                    trend = -1;
                    sar = candle.high;
                    l = candle.low;
                    h = candle.high;
                    trendLength = 0;
                }
                else
                {
                    var resultStep = stepDelta * trendLength + step;
                    trendLength++;
                    sar = sar + resultStep * (trend > 0 ? h - sar : l - sar);
                    if (h < candle.high) h = candle.high;
                    if (l > candle.low) l = candle.low;
                }

                AddLinePoint(i, sar);
            }
        }