Semi-Cup Pattern Detection

Modified on 2011/03/25 12:05 by Administrator — Categorized as: TASCIndicators


In the April 2011 issue of TASC magazine, Dr. Siligardos presented an algorithm to detect cups (as in "cup and handle") early in their formation. As such he called the pattern a "semi-cup". As described in the associated Traders' Tip, we modified the algorithm and added the classes below to the TASCIndicator library.

Note! Although Semi-Cup Pattern Detection is included in the TASCIndicators component, it is not an indicator. You must employ the classes (as shown by the examples) by manual programming.


A Semicup object is created for each peak in the Peak.Series. The enumeration defines the status of a Semicup object, primarily during its formation.

public enum CupStatus { Search, SemiCupDetected, Duplicate, LevelExceeded, Failure, FormingCup }

SearchSemicup has not yet been detected for the associated peak.
SemiCupDetectedA Semicup has been detected for the associated peak.
DuplicateSemicup is considered a duplicate of another detected Semicup. (Not currently used)
LevelExceededThe peak level has been exceeded, and therefore a Semicup will not be associated with this peak.
FailureThe Semicup failed by closing lower than the previous lowest level of the cup. After a Failure, the Semicup goes back into Search mode, which most often results in a new cup being detected almost immediately.
FormingCupThe Semicup is determined to be "successful" by closing higher than the L2 box level. No further updates occur after a FormingCup status.


Semicups is the container of all Semicups, each of which is associated with a peak in the PeakBar.Series. By instantiating SemiCups, all Semicup objects are created and these may then be accessed from the Cups Dictionary (see Cups member below).

public SemiCups(WealthScript ws, int minBars, DataSeries pkBarSer)

wsAn instance of the WealthScript object. Pass this.
minBarsThe minimum number of bars spanned by a Semicup. For example, if a peak occurs on bar number 100, and minBars is 20, an associated Semicup cannot be detected prior to bar 120.
pkBarSerEach Semicup is associated with a peak in the PeakBar.Series. Pass a PeakBar DataSeries.

ActiveSemiCups(int bar)

For backtesting: returns a list of "active" SemiCups, which are SemiCups that have achieved CupStatus.SemiCupDetected as least once, but then can have any status including CupStatus.Search thereafter. SemiCups are returned in this list up to and including the bar declared Inactive or FormingCup. See SemiCup.Status for the CupStatus of a SemiCup at each bar.

public List<SemiCup> ActiveSemiCups(int bar)


Member of SemiCups. Draw displays the detection grid, semi-cup curve, and failure/success arrows on the current chart.

public void Draw()


Member of SemiCups. PkBarList is simply a convenient integer list of peak bars for the PeakBar.Series passed to SemiCups. A Semicup is associated with each item in this list and can be used as the key to the Cups Dictionary (below).

public IList<int> PkBarList = new List<int>();


Member of SemiCups. Cups is a Dictionary of SemiCups. Iterate through Cups using foreach (KeyValuePair kvp in semiCups.Cups) or by identifying a particular peak from the PkBarList. Note: in the 2011.4.0.1 version of TASCIndicators, some peak bars are not added to the list if the chance of creating an essentially "duplicate" SemiCup is high. Use the .ContainsKey() method to determine if a peak bar exists in Cups.

public Dictionary<int, SemiCup> Cups


Semicup is an object associated with each PeakBar. You are not required to instantiate Semicup objects - this is done by the Semicups class. Instead, you will be interested only the properties of a Semicup, as defined below.

public SemiCup(WealthScript ww, int B0, int B5, DataSeries lnClose, DataSeries momentum, IList<int> pbL)


Property of SemiCup. Contains a list of bar numbers on which this instance was detected as a Semicup. If the list is empty, a Semicup was never detected for the associated PeakBar. The first bar in the list is the first detection.

public List<int> SemiCupBars


Property of SemiCup. Contains a list of bar numbers on which this Semicup "failed" by creating a new low in the formation. On the following bar, this Semicup instance may or may not be "detected" again. If the list is empty, the Semicup never failed following the first detection.

public List<int> FailureBars


For backtesting provides the ability to know the CupStatus for every bar between StartBar and BarInactive, inclusive.

public Dictionary<int, CupStatus> Status


For detection purposes, SemiCups are divided into 6 levels (5 equal boxes), 0 to 5, inclusive. Level 0 is the base and Level 5 is the top of the SemiCup. After a SemiCup is detected, if price crosses Level 2, it is assumed a Cup pattern is forming and the SemiCup is frozen.

For backtesting, the Level method provides the ability to return specific levels of a SemiCup formation as of a specified bar. Levels change after a SemiCup is detected and then fails. The bar passed to the method should be in the range StartBar, InactiveBar.

public double Level(int bar, int level)


Property of SemiCup. The Active status is false if this SemiCup has a) achieved a CupStatus.FormingCup, or, b) has no possibility of achieving CupStatus.SemiCupDetected. Use this property for Scans to determine which SemiCup objects are still active. Do not use this property for backtesting and instead use the SemiCupBars and FailureBars to determine the status of the SemiCup on a given bar.

public bool Active


Property of SemiCup. This is the starting peak bar (left-most bar) of the SemiCup formation.

public int StartBar


Property of SemiCup. This is the bar on which the Semicup has become inactive, i.e., Active = false.

public int BarInactive


See TASCApr2011
Also see Semi-Cup Trading System