protected virtual bool CheckAcrossFrames(List <Frame> acrossFrames, AboveBelowDMA trueFor) { foreach (Frame frame in acrossFrames) { IIndicator displaced3x3 = frame.Indicators.First(k => k.Type == IndicatorType.DisplacedMovingAverage && k.ParentOrdinal == 0); double acrossHeight; double barHeight = frame.Bar.highMid - frame.Bar.lowMid; if (trueFor == AboveBelowDMA.Above) { acrossHeight = displaced3x3.Value.Value - frame.Bar.lowMid; } else { acrossHeight = frame.Bar.highMid - displaced3x3.Value.Value; } if ((acrossHeight / barHeight) > _acrossFramesCoefficient) { return(false); } } return(true); }
/// <summary> /// Determines if a list of leaderSides are equal to a specified value. /// </summary> /// <param name="leaderSides">The list of AboveBelowDMA values to examine.</param> /// <param name="trueFor">The AboveBelowDMA side all leaderSides should equal.</param> /// <returns>True if all leader values equal the truefor value. /// False all leader values do not equal the truefor value.</returns> protected virtual bool CheckLeaders(List <AboveBelowDMA> leaderSides, AboveBelowDMA trueFor) { bool result = false; result = leaderSides.TrueForAll(x => x == trueFor); return(result); }
/* * upThrust * traverse >= 10 bars * >= 7 bars have low bid above the 3x3 * >= 5 consecutive bars must have low bid above the 3x3 * sequence may not start with > 3 bars with low bid below 3x3 * if (any of?) top 3 bars of sequence have low bid below 3x3 then lowest low bid of those below the 3x3 must be > .386 ask price * thrust range must be >= (.06 x thrust ReactionPrice) * MACD histogram value of all thrust frames must be > 0 * * downThrust * traverse >= 10 bars * >= 7 bars have low bid above the 3x3 * >= 5 consecutive bars must have low bid above the 3x3 * sequence may not start with > 3 bars with low bid below 3x3 * if (any of?) top 3 bars of sequence have low bid below 3x3 then lowest low bid of those below the 3x3 must be > .386 ask price * thrust range must be >= (.06 x thrust ReactionPrice) * MACD histogram value of all thrust frames must be > 0 * above or below the 3x3? */ #endregion /// <summary> /// Searches the chart for a thrust pattern. /// </summary> /// <param name="chart">Chart object containing at least 20 frames</param> /// <returns>A tradeable thrust object, if found.</returns> protected override Thrust DetectThrust() { Thrust thrust = null; if (_chart.Frames.Count >= 20) { Frame frame; bool upThrustFound = false, downThrustFound = false; short above3x3Count = 0, above3x3Links = 0, below3x3Count = 0, below3x3Links = 0, across3x3Count = 0; Func <short> sequentialAbove3x3Count = () => { return(above3x3Links > 0 ? (short)(above3x3Links + 1) : (short)0); }; Func <short> sequentialBelow3x3Count = () => { return(below3x3Links > 0 ? (short)(below3x3Links + 1) : (short)0); }; AboveBelowDMA previousCandleSide = AboveBelowDMA.Unknown, currentCandleSide = AboveBelowDMA.Unknown; List <AboveBelowDMA> leaderSides = new List <AboveBelowDMA>(); // only need to sniff 20 frames to find thrust // if not in 20 frames, whatever thrust exists has yielded to a consolidation period .. no good short loopCount = 0; while (loopCount < 20) { loopCount++; int i = _chart.Frames.Count - loopCount; frame = _chart.Frames[i]; IPriceBar candle = frame.Bar; IIndicator displaced3x3 = frame.Indicators.First(k => k.Type == IndicatorType.DisplacedMovingAverage && k.ParentOrdinal == 0); if (candle.lowMid >= displaced3x3.Value) { above3x3Count++; if (previousCandleSide == AboveBelowDMA.Above) { above3x3Links++; } currentCandleSide = previousCandleSide = AboveBelowDMA.Above; } else if (candle.highMid <= displaced3x3.Value) { below3x3Count++; if (previousCandleSide == AboveBelowDMA.Below) { below3x3Links++; } currentCandleSide = previousCandleSide = AboveBelowDMA.Below; } else { across3x3Count++; currentCandleSide = previousCandleSide = AboveBelowDMA.Across; } // save the first 3 bar sides if (leaderSides.Count < 3) { leaderSides.Add(currentCandleSide); } // start thrust parsing once 10 bars have been examined if (loopCount > 9) { upThrustFound = sequentialAbove3x3Count() >= 6 && sequentialBelow3x3Count() <= 3 && CheckLeaders(leaderSides, AboveBelowDMA.Above) && !Displaced3x3HasDoubleDip(i, EPatternDirection.Up); downThrustFound = sequentialBelow3x3Count() >= 6 && sequentialAbove3x3Count() <= 3 && CheckLeaders(leaderSides, AboveBelowDMA.Below) && !Displaced3x3HasDoubleDip(i, EPatternDirection.Down); if (upThrustFound || downThrustFound) { EPatternDirection direction = upThrustFound ? EPatternDirection.Up : EPatternDirection.Down; Frame reactionFrame = FindReactionFrame(frame, i, direction); if (reactionFrame != null) { int checkAcrossIndex = GetCheckAcrossIndex(reactionFrame, direction); AboveBelowDMA checkAcrossSide = upThrustFound ? AboveBelowDMA.Above : AboveBelowDMA.Below; if (CheckAcrossFrames(checkAcrossIndex, checkAcrossSide)) { thrust = BuildThrust(reactionFrame, direction); } } break; } } } } return(thrust); }
/* * upThrust * traverse >= 10 bars * >= 7 bars have low bid above the 3x3 * >= 5 consecutive bars must have low bid above the 3x3 * sequence may not start with > 3 bars with low bid below 3x3 * if (any of?) top 3 bars of sequence have low bid below 3x3 then lowest low bid of those below the 3x3 must be > .386 ask price * thrust range must be >= (.06 x thrust ReactionPrice) * MACD histogram value of all thrust frames must be > 0 * * downThrust * traverse >= 10 bars * >= 7 bars have low bid above the 3x3 * >= 5 consecutive bars must have low bid above the 3x3 * sequence may not start with > 3 bars with low bid below 3x3 * if (any of?) top 3 bars of sequence have low bid below 3x3 then lowest low bid of those below the 3x3 must be > .386 ask price * thrust range must be >= (.06 x thrust ReactionPrice) * MACD histogram value of all thrust frames must be > 0 * above or below the 3x3? */ #endregion /// <summary> /// Searches the chart for a thrust pattern. /// </summary> /// <param name="chart">Chart object containing at least 20 frames</param> /// <returns>A tradeable thrust object, if found.</returns> protected override Thrust DetectThrust() { Thrust thrust = null; if (_chart.Frames.Count >= 20) { Frame frame; bool upThrustFound = false, downThrustFound = false; short above3x3Count = 0, below3x3Count = 0, across3x3Count = 0; AboveBelowDMA currentCandleSide = AboveBelowDMA.Unknown; List <AboveBelowDMA> leaderSides = new List <AboveBelowDMA>(); List <Frame> acrossFrames = new List <Frame>(); // only need to sniff 20 frames to find thrust // if not in 20 frames, whatever thrust exists has yielded to a consolidation period .. no good for (int loopCount = 1; true; loopCount++) { int i = _chart.Frames.Count - loopCount; frame = _chart.Frames[i]; IPriceBar candle = frame.Bar; IIndicator displaced3x3 = frame.Indicators.First(k => k.Type == IndicatorType.DisplacedMovingAverage && k.ParentOrdinal == 0); if (candle.lowMid >= displaced3x3.Value) { above3x3Count++; currentCandleSide = AboveBelowDMA.Above; } else if (candle.highMid <= displaced3x3.Value) { below3x3Count++; currentCandleSide = AboveBelowDMA.Below; } else { across3x3Count++; currentCandleSide = AboveBelowDMA.Across; acrossFrames.Add(frame); } // save the first 3 bar sides if (leaderSides.Count < 3) { leaderSides.Add(currentCandleSide); } // start thrust parsing once 10 bars have been examined if (loopCount == 7) { upThrustFound = above3x3Count >= 5 && below3x3Count == 0 && CheckLeaders(leaderSides, AboveBelowDMA.Above) && CheckAcrossFrames(acrossFrames, AboveBelowDMA.Above); downThrustFound = below3x3Count >= 5 && above3x3Count == 0 && CheckLeaders(leaderSides, AboveBelowDMA.Below) && CheckAcrossFrames(acrossFrames, AboveBelowDMA.Below); if (upThrustFound || downThrustFound) { EPatternDirection direction = upThrustFound ? EPatternDirection.Up : EPatternDirection.Down; Frame reactionFrame = FindReactionFrame(frame, i, direction); if (reactionFrame != null) { int checkAcrossIndex = GetCheckAcrossIndex(reactionFrame, direction); AboveBelowDMA checkAcrossSide = upThrustFound ? AboveBelowDMA.Above : AboveBelowDMA.Below; if (CheckAcrossFrames(checkAcrossIndex, checkAcrossSide)) { thrust = BuildThrust(reactionFrame, direction); } } } break; } } } return(thrust); }
/// <summary> /// Checks each frame price bar after the startIndex frame price bar to discover those that cross the 3x3. /// If a bar crosses the 3x3, no more than 0.382*[bar length] may be across the 3x3. /// </summary> /// <param name="reactionIndex"></param> /// <param name="trueFor"></param> /// <returns></returns> protected virtual bool CheckAcrossFrames(int startIndex, AboveBelowDMA trueFor) { IEnumerable <Frame> afterReactionFrames = _chart.Frames.Skip(startIndex + 1); return(CheckAcrossFrames(afterReactionFrames.ToList(), trueFor)); }