Untitled

 avatar
unknown
plain_text
10 months ago
13 kB
14
Indexable
using System;
using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None, IsOverlay = true)]
    public class BeQSimpleZigZag : Indicator
    {
        [Parameter("Depth", DefaultValue = 21, Group = "ZigZag")]
        public int Depth { get; set; }

        [Parameter("Deviation", DefaultValue = 5, Group = "ZigZag")]
        public int Deviation { get; set; }

        [Parameter(DefaultValue = 3, Group = "ZigZag")]
        public int BackStep { get; set; }

        [Parameter("Long", DefaultValue = 26, Group = "MACD")]
        public int MACD_Long { get; set; }

        [Parameter("Short", DefaultValue = 12, Group = "MACD")]
        public int MACD_Short { get; set; }

        [Parameter("Signal", DefaultValue = 9, Group = "MACD")]
        public int MACD_Signal { get; set; }

        [Output("ZigZag", Color = Colors.OrangeRed)]
        public IndicatorDataSeries Result { get; set; }

        [Output("Fibo50", Color = Colors.Gray, PlotType = PlotType.Line, Thickness = 2)]
        public IndicatorDataSeries Fibo50 { get; set; }
        [Output("Fibo62", Color = Colors.Silver, PlotType = PlotType.Line, Thickness = 2)]
        public IndicatorDataSeries Fibo62 { get; set; }
        [Output("Fibo88", Color = Colors.Brown, PlotType = PlotType.Line, Thickness = 2)]
        public IndicatorDataSeries Fibo88 { get; set; }
        [Output("Fibo96", Color = Colors.Blue, PlotType = PlotType.Line, Thickness = 2)]
        public IndicatorDataSeries Fibo96 { get; set; }
        [Output("Fibo126", Color = Colors.Red, PlotType = PlotType.Line, Thickness = 2)]
        public IndicatorDataSeries Fibo126 { get; set; }
        [Output("Fibo144", Color = Colors.DarkOrange, PlotType = PlotType.Line, Thickness = 2)]
        public IndicatorDataSeries Fibo144 { get; set; }

        // ... Các DataSeries phụ khác ...
        public IndicatorDataSeries MacdValue { get; set; }
        public IndicatorDataSeries MacdSignal { get; set; }
        public IndicatorDataSeries SwingOpenTimeIndex { get; set; }

        private double _lastLow, _lastHigh, _low, _high, _point, _currentLow, _currentHigh;
        private int _lastHighIndex, _lastLowIndex, _type;
        private MacdCrossOver _macd;
        public IndicatorDataSeries HighZigZags;
        public IndicatorDataSeries LowZigZags;

        // Thêm để lưu swing trước đó cho Fibo
        private int _prevSwingIndex = -1;
        private double _prevSwingPrice = double.NaN;

        protected override void Initialize()
        {
            HighZigZags = CreateDataSeries();
            LowZigZags = CreateDataSeries();
            MacdValue = CreateDataSeries();
            MacdSignal = CreateDataSeries();
            SwingOpenTimeIndex = CreateDataSeries();
            Fibo50 = CreateDataSeries();
            Fibo62 = CreateDataSeries();
            Fibo88 = CreateDataSeries();
            Fibo96 = CreateDataSeries();
            Fibo126 = CreateDataSeries();
            Fibo144 = CreateDataSeries();
            _point = Symbol.TickSize;
            _macd = Indicators.MacdCrossOver(MACD_Long, MACD_Short, MACD_Signal);

            // Đặt mặc định tất cả fibo về NaN
            for (int i = 0; i < MarketSeries.Close.Count; i++)
            {
                Fibo50[i] = double.NaN;
                Fibo62[i] = double.NaN;
                Fibo88[i] = double.NaN;
                Fibo96[i] = double.NaN;
                Fibo126[i] = double.NaN;
                Fibo144[i] = double.NaN;
            }
        }


        public override void Calculate(int index)
        {
            // ... Code ZigZag cũ giữ nguyên ...
            if (index < Depth) return;

            _currentLow = Functions.Minimum(MarketSeries.Low, Depth);

            if (Math.Abs(_currentLow - _lastLow) < double.Epsilon)
                _currentLow = 0.0;
            else
            {
                _lastLow = _currentLow;

                if ((MarketSeries.Low[index] - _currentLow) > (Deviation * _point))
                    _currentLow = 0.0;
                else
                {
                    for (int i = 1; i <= BackStep; i++)
                    {
                        if (Math.Abs(LowZigZags[index - i]) > double.Epsilon && LowZigZags[index - i] > _currentLow)
                            LowZigZags[index - i] = 0.0;
                    }
                }
            }

            if (Math.Abs(MarketSeries.Low[index] - _currentLow) < double.Epsilon)
                LowZigZags[index] = _currentLow;
            else
                LowZigZags[index] = 0.0;

            _currentHigh = MarketSeries.High.Maximum(Depth);

            if (Math.Abs(_currentHigh - _lastHigh) < double.Epsilon)
                _currentHigh = 0.0;
            else
            {
                _lastHigh = _currentHigh;

                if ((_currentHigh - MarketSeries.High[index]) > (Deviation * _point))
                    _currentHigh = 0.0;
                else
                {
                    for (int i = 1; i <= BackStep; i++)
                    {
                        if (Math.Abs(HighZigZags[index - i]) > double.Epsilon && HighZigZags[index - i] < _currentHigh)
                            HighZigZags[index - i] = 0.0;
                    }
                }
            }

            if (Math.Abs(MarketSeries.High[index] - _currentHigh) < double.Epsilon)
                HighZigZags[index] = _currentHigh;
            else
                HighZigZags[index] = 0.0;

            bool newSwing = false;
            double thisSwing = double.NaN;

            switch (_type)
            {
                case 0:
                    if (Math.Abs(_low) < double.Epsilon && Math.Abs(_high) < double.Epsilon)
                    {
                        if (Math.Abs(HighZigZags[index]) > double.Epsilon)
                        {
                            _high = MarketSeries.High[index];
                            _lastHighIndex = index;
                            _type = -1;
                            Result[index] = _high;
                            thisSwing = _high;
                            newSwing = true;
                        }
                        if (Math.Abs(LowZigZags[index]) > double.Epsilon)
                        {
                            _low = MarketSeries.Low[index];
                            _lastLowIndex = index;
                            _type = 1;
                            Result[index] = _low;
                            thisSwing = _low;
                            newSwing = true;
                        }
                    }
                    break;
                case 1:
                    if (Math.Abs(LowZigZags[index]) > double.Epsilon && LowZigZags[index] < _low && Math.Abs(HighZigZags[index]) < double.Epsilon)
                    {
                        Result[_lastLowIndex] = double.NaN;
                        _lastLowIndex = index;
                        _low = LowZigZags[index];
                        Result[index] = _low;
                        thisSwing = _low;
                        newSwing = true;
                    }
                    if (Math.Abs(HighZigZags[index]) > double.Epsilon && Math.Abs(LowZigZags[index]) < double.Epsilon)
                    {
                        _high = HighZigZags[index];
                        _lastHighIndex = index;
                        Result[index] = _high;
                        thisSwing = _high;
                        newSwing = true;
                        _type = -1;
                    }
                    break;
                case -1:
                    if (Math.Abs(HighZigZags[index]) > double.Epsilon && HighZigZags[index] > _high && Math.Abs(LowZigZags[index]) < double.Epsilon)
                    {
                        Result[_lastHighIndex] = double.NaN;
                        _lastHighIndex = index;
                        _high = HighZigZags[index];
                        Result[index] = _high;
                        thisSwing = _high;
                        newSwing = true;
                    }
                    if (Math.Abs(LowZigZags[index]) > double.Epsilon && Math.Abs(HighZigZags[index]) <= double.Epsilon)
                    {
                        _low = LowZigZags[index];
                        _lastLowIndex = index;
                        Result[index] = _low;
                        thisSwing = _low;
                        newSwing = true;
                        _type = 1;
                    }
                    break;
            }

            // ========= VẼ FIBO CHO SWING CẶP MỚI =========
            if (newSwing && !double.IsNaN(thisSwing) && _prevSwingIndex != -1)
            {
                double swingStart = _prevSwingPrice;
                double swingEnd = thisSwing;
                double[] fiboPercents = { 0.5, 0.62, 0.88, 0.96, 1.26, 1.44 };

                for (int i = _prevSwingIndex; i <= index; i++)
                {
                    Fibo50[i] = swingStart + (swingEnd - swingStart) * fiboPercents[0];
                    Fibo62[i] = swingStart + (swingEnd - swingStart) * fiboPercents[1];
                    Fibo88[i] = swingStart + (swingEnd - swingStart) * fiboPercents[2];
                    Fibo96[i] = swingStart + (swingEnd - swingStart) * fiboPercents[3];
                    Fibo126[i] = swingStart + (swingEnd - swingStart) * fiboPercents[4];
                    Fibo144[i] = swingStart + (swingEnd - swingStart) * fiboPercents[5];
                }
            }


            if (newSwing && !double.IsNaN(thisSwing))
            {
                _prevSwingIndex = index;
                _prevSwingPrice = thisSwing;
            }

            // CHỈ vẽ đường ngang khi đã xác định xong toàn bộ swing (ở cây nến cuối cùng)
            if (index == MarketSeries.Close.Count - 1)
            {
                double[] fiboPercents = { 0.5, 0.62, 0.88, 0.96, 1.26, 1.44 };
                Colors[] fiboColors = { Colors.Gray, Colors.Silver, Colors.Brown, Colors.Blue, Colors.Red, Colors.DarkOrange };
                string[] fiboLabels = { "Fibo50", "Fibo62", "Fibo88", "Fibo96", "Fibo126", "Fibo144" };

                int delta = 2; // Độ dài đường ngang

                ChartObjects.RemoveAllObjects();

                // 1. Lấy tất cả swing
                var swings = new System.Collections.Generic.List<int>();
                for (int i = 0; i < Result.Count; i++)
                    if (!double.IsNaN(Result[i]))
                        swings.Add(i);

                // 2. Vẽ đường ngang swing như cũ
                for (int i = 0; i < swings.Count; i++)
                {
                    int idx = swings[i];
                    Print("idx: ", idx);
                    int startIndex = Math.Max(0, idx - delta);
                    int endIndex = Math.Min(MarketSeries.Close.Count - 1, idx + delta);
                    string lineName = "ShortLine_" + idx;
                    ChartObjects.DrawLine(
                        lineName,
                        Bars.OpenTimes[startIndex], Result[idx],
                        Bars.OpenTimes[endIndex], Result[idx],
                        Colors.LimeGreen,
                        2,
                        LineStyle.Lines
                    );
                }

                // 3. Vẽ fibo cho từng cặp swing liên tiếp
                for (int k = 0; k < swings.Count - 1; k++)
                {
                    int from = swings[k];
                    int to = swings[k + 1];
                    double swingStart = Result[from];
                    double swingEnd = Result[to];
                    Print("swingStart: ", swingStart);
                    Print("swingEnd: ", swingEnd);
                    // Đoạn fibo chỉ vẽ gần swing bắt đầu
                    int fiboStartIndex = Math.Max(0, from - delta);
                    int fiboEndIndex = Math.Min(MarketSeries.Close.Count - 1, from + delta);

                    for (int f = 0; f < fiboPercents.Length; f++)
                    {
                        double fiboValue = swingStart + (swingEnd - swingStart) * fiboPercents[f];

                        // Đặt tên không bị trùng lặp!
                        string fiboLineName = $"{fiboLabels[f]}_{from}_{to}";

                        ChartObjects.DrawLine(
                            fiboLineName,
                            Bars.OpenTimes[fiboStartIndex], fiboValue,
                            Bars.OpenTimes[fiboEndIndex], fiboValue,
                            fiboColors[f],
                            2,
                            LineStyle.Lines
                        );
                    }
                }
            }

        }
    }
}
Editor is loading...
Leave a Comment