Beispiel #1
0
        /// <summary>True if a break-out to the 'high' side is detected</summary>
        private bool IsBreakOutInternal(Monic trend, List <Peak> peaks, bool high)
        {
            // A break-out is when the latest candle is significantly above the upper trend line
            // or below the lower trend line and showing signs of going further. Also, the preceding candles
            // must be below the trend line.

            // No trend, no break-out
            if (trend == null)
            {
                return(false);
            }

            // The latest candle must be in the break-out direction
            var sign   = high ? +1 : -1;
            var latest = Instrument.Latest;

            if (latest.Sign != sign)
            {
                return(false);
            }

            // The price must be beyond the trend by a significant amount
            var price_threshold = trend.F(0.0) + sign * Instrument.MCS;

            if (Math.Sign(latest.Close - price_threshold) != sign)
            {
                return(false);
            }

            // Only the latest few candles can be beyond the trend line
            // and all must be in the direction of the break out.
            if (peaks[0].Index < -2)
            {
                // Allow the last two candles to be part of the break out
                foreach (var c in Instrument.CandleRange(peaks[0].Index, -2))
                {
                    // If more than half the candle is beyond the trend line, not a breakout
                    var ratio = sign * Instrument.Compare(c, trend, false);
                    if (ratio > 0)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Beispiel #2
0
        /// <summary>Determine a measure of trend strength</summary>
        private double TrendStrength(Monic trend, List <Peak> peaks, bool high)
        {
            if (trend == null)
            {
                return(0.0);
            }

            // Trend strength has to be a measure of how often price approached the trend line
            // and bounced off. Candles miles away from the trend line don't count, only consider
            // candles that span or are within a tolerance range of the trend line.
            var above = 0.0; var below = 0.0; var count = 0;
            var threshold = ConfirmTrend * Instrument.MCS;

            foreach (var c in Instrument.CandleRange(peaks.Back().Index, Instrument.IdxLast - WindowSize))
            {
                var p = trend.F(c.Index + Instrument.IdxFirst);
                if (c.High < p - threshold)
                {
                    continue;
                }
                if (c.Low > p + threshold)
                {
                    continue;
                }
                above += Math.Max(0, c.High - p);
                below += Math.Max(0, p - c.Low);
                ++count;
            }

            // There must be some candles contributing
            var total = above + below;

            if (total == 0)
            {
                return(0.0);
            }

            // Return the proportion of above to below
            var strength = (high ? +1 : -1) * (below - above) / total;

            // Weight the strength based on the number of candles that contribute
            var weighted_count = Maths.Sigmoid(count, 6);

            return(strength * weighted_count);
        }
Beispiel #3
0
 [Test] public void FromLinearRegression()
 {
     {
         var pts = new v2[]
         {
             new v2(0, 15),
             new v2(1, 13),
             new v2(2, 10),
             new v2(3, 7),
             new v2(4, 4),
             new v2(5, 1),
         };
         var m = Monic.FromLinearRegression(pts);
         //Assert.True(Math_.FEql(m.A, 0.689393937587738));
         //Assert.True(Math_.FEql(m.B, -6.10151338577271));
     }
     {
         var pts = new v2[]
         {
             new v2(0, 15),
             new v2(1, 13),
             new v2(2, 10),
             new v2(3, 7),
             new v2(4, 4),
             new v2(5, 1),
             new v2(6, 5),
             new v2(7, 8),
             new v2(8, 13),
             new v2(9, 19),
         };
         var q = Quadratic.FromLinearRegression(pts);
         Assert.True(Math_.FEql((float)q.A, 0.689394f));
         Assert.True(Math_.FEql((float)q.B, -6.10151672f));
         Assert.True(Math_.FEql((float)q.C, 17.3090973f));
     }
 }
Beispiel #4
0
        /// <summary>Return a polynomial approximation of the indicator values or null if no decent approximation could be made. 'order' is polynomial order (i.e. 1 or 2)</summary>
        public Extrapolation Extrapolate(int order, int history_count, Idx?idx_ = null, int series = 0)
        {
            var idx = idx_ ?? IdxLast;

            // Get the points to fit too
            var range  = Instrument.IndexRange(idx - history_count, idx);
            var points = range
                         .Where(x => Maths.IsFinite(Source[series][(int)(x - IdxFirst)]))
                         .Select(x => new v2((float)x, (float)Source[series][(int)(x - IdxFirst)]))
                         .ToArray();

            // Require a minimum number of points
            if (points.Length <= order)
            {
                return(null);
            }

            // Create a curve using linear regression
            var curve = (IPolynomial)null;

            switch (order)
            {
            default: throw new Exception("Unsupported polynomial order");

            case 2: curve = Quadratic.FromLinearRegression(points); break;

            case 1: curve = Monic.FromLinearRegression(points); break;
            }

            // Measure the confidence in the fit.
            // Map the error range to [0,+1], where > 0.5 is "good"
            var rms  = Math.Sqrt(points.Sum(x => Maths.Sqr(x.y - curve.F(x.x))));
            var conf = 1.0 - Maths.Sigmoid(rms, Instrument.MCS * 0.2);

            return(new Extrapolation(curve, conf));
        }
Beispiel #5
0
        // Notes:
        //  - price is trending up if the lows are getting higher
        //  - price is trending down if the highs are getting lower
        //  - trend is unknown otherwise
        //  - Break outs can be detected by comparing two sets of price peaks

        /// <summary>Find the highs and lows of the price</summary>
        /// <param name="instr">The instrument to find peaks in</param>
        /// <param name="iend">The last candle, i.e. look backwards from here</param>
        public PricePeaks(Instrument instr, Idx iend, int window_size = 5)
        {
            Instrument   = instr;
            WindowSize   = window_size;
            ConfirmTrend = 0.5;
            Beg          = iend;
            End          = iend;
            Highs        = new List <Peak>();
            Lows         = new List <Peak>();

            #region Find peaks
            {
                var threshold = ConfirmTrend * Instrument.MCS;
                var corr_hi   = new Correlation();
                var corr_lo   = new Correlation();

                // The last high/low encountered
                var hi = (Peak)null;
                var lo = (Peak)null;

                var done_hi = false;
                var done_lo = false;

                // Iterate through the peaks
                foreach (var pk in FindPeaks(iend))
                {
                    // Save the first peak as it might be a break out
                    if (FirstPeak == null)
                    {
                        FirstPeak = pk;
                        continue;
                    }

                    var last  = pk.High ? hi        : lo;
                    var peaks = pk.High ? Highs     : Lows;
                    var corr  = pk.High ? corr_hi   : corr_lo;
                    var trend = pk.High ? TrendHigh : TrendLow;
                    var done  = pk.High ? done_hi   : done_lo;

                    // First peak encountered?
                    if (last == null)
                    {
                        // Just save the peak
                        corr.Add(pk.Index, pk.Price);
                        peaks.Add(pk);
                    }
                    // The trend has not been broken
                    else if (!done)
                    {
                        // Second peak encountered
                        if (trend == null)
                        {
                            // Form a trend line between the peaks
                            if (pk.High)
                            {
                                TrendHigh = Monic.FromPoints(pk.Index, pk.Price, last.Index, last.Price);
                            }
                            else
                            {
                                TrendLow = Monic.FromPoints(pk.Index, pk.Price, last.Index, last.Price);
                            }
                            corr.Add(pk.Index, pk.Price);
                            peaks.Add(pk);
                        }
                        // 3+ peak encountered, confirm trend strength
                        else
                        {
                            // Get the predicted value from the trend line
                            var p = trend.F(pk.Index);
                            if (Math.Abs(p - pk.Price) < threshold)
                            {
                                // If within tolerance, the trend is confirmed
                                corr.Add(pk.Index, pk.Price);
                                if (pk.High)
                                {
                                    TrendHigh = corr.LinearRegression;
                                }
                                else
                                {
                                    TrendLow = corr.LinearRegression;
                                }
                                peaks.Add(pk);
                            }
                            else
                            {
                                if (pk.High)
                                {
                                    done_hi = true;
                                }
                                else
                                {
                                    done_lo = true;
                                }

                                // Otherwise, if the trend does not have 3 points, it is rejected
                                if (peaks.Count < 3)
                                {
                                    if (pk.High)
                                    {
                                        TrendHigh = null;
                                    }
                                    else
                                    {
                                        TrendLow = null;
                                    }
                                }
                            }
                        }
                    }

                    // Save the peak as last
                    if (pk.High)
                    {
                        hi = pk;
                    }
                    else
                    {
                        lo = pk;
                    }

                    // If the high and low trends are done, break the loop
                    if (done_hi && done_lo)
                    {
                        break;
                    }
                }
            }
            #endregion
        }