#include "sierrachart.h" #include "CandleStickPatternNames.h" /*==================================================================================*/ SCSFExport scsf_WoodieCCITrend2(SCStudyInterfaceRef sc) { SCSubgraphRef Subgraph_CCI = sc.Subgraph[0]; SCSubgraphRef Subgraph_TrendDown = sc.Subgraph[1]; SCSubgraphRef Subgraph_TrendNeutral = sc.Subgraph[2]; SCSubgraphRef Subgraph_TrendUp = sc.Subgraph[3]; SCSubgraphRef Subgraph_HiLevel = sc.Subgraph[4]; SCSubgraphRef Subgraph_LowLevel = sc.Subgraph[5]; SCSubgraphRef Subgraph_Consecutive = sc.Subgraph[6]; SCSubgraphRef Subgraph_LastTrend = sc.Subgraph[7]; SCSubgraphRef Subgraph_WorksheetOutput = sc.Subgraph[8]; SCSubgraphRef Subgraph_ZLR = sc.Subgraph[9]; SCInputRef Input_NumberOfBars = sc.Input[0]; SCInputRef Input_NeutralBars = sc.Input[1]; SCInputRef Input_CCILength = sc.Input[2]; SCInputRef Input_Level = sc.Input[3]; SCInputRef Input_CCIInputData = sc.Input[4]; SCInputRef Input_Version = sc.Input[5]; if(sc.SetDefaults) { sc.GraphName="Woodies CCI Trend"; sc.AutoLoop = 1; Subgraph_TrendDown.Name = "TrendDown"; Subgraph_TrendDown.DrawStyle = DRAWSTYLE_BAR; Subgraph_TrendDown.PrimaryColor = RGB(255,0,0); Subgraph_TrendDown.DrawZeros = false; Subgraph_TrendNeutral.Name = "TrendNeutral"; Subgraph_TrendNeutral.PrimaryColor = RGB(255,255,0); Subgraph_TrendNeutral.DrawStyle = DRAWSTYLE_BAR; Subgraph_TrendNeutral.DrawZeros = false; Subgraph_TrendUp.Name = "TrendUp"; Subgraph_TrendUp.DrawStyle = DRAWSTYLE_BAR; Subgraph_TrendUp.PrimaryColor = RGB(0,0,255); Subgraph_TrendUp.DrawZeros = false; Subgraph_HiLevel.Name = "Hi Level"; Subgraph_HiLevel.DrawStyle = DRAWSTYLE_LINE; Subgraph_HiLevel.PrimaryColor = RGB(0,255,0); Subgraph_HiLevel.DrawZeros = false; Subgraph_LowLevel.Name = "Low Level"; Subgraph_LowLevel.DrawStyle = DRAWSTYLE_LINE; Subgraph_LowLevel.PrimaryColor = RGB(0,255,0); Subgraph_LowLevel.DrawZeros = false; Subgraph_CCI.Name = "CCI"; Subgraph_CCI.DrawStyle = DRAWSTYLE_BAR; Subgraph_CCI.PrimaryColor = RGB(98,98,98); Subgraph_CCI.DrawZeros = false; Subgraph_Consecutive.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Consecutive.DrawZeros = false; Subgraph_LastTrend.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_LastTrend.DrawZeros = false; Subgraph_WorksheetOutput.Name = "Spreadsheet Ouput"; Subgraph_WorksheetOutput.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_WorksheetOutput.PrimaryColor = RGB(0,127,255); Subgraph_WorksheetOutput.DrawZeros = false; Subgraph_ZLR.Name = "ZLR Output"; Subgraph_ZLR.DrawStyle = DRAWSTYLE_POINT; Subgraph_ZLR.PrimaryColor = RGB(255,0,0); Subgraph_ZLR.SecondaryColor = RGB(0,255,0); Subgraph_ZLR.SecondaryColorUsed = 1; Subgraph_ZLR.LineWidth = 3; Subgraph_ZLR.DrawZeros = false; Input_CCILength.Name = "CCI Length"; Input_CCILength.SetInt(14); Input_CCILength.SetIntLimits(1,MAX_STUDY_LENGTH); Input_NumberOfBars.Name = "Number of Bars"; Input_NumberOfBars.SetInt(6); Input_NumberOfBars.SetIntLimits(1,MAX_STUDY_LENGTH); Input_NeutralBars.Name = "Number of Neutral Bars"; Input_NeutralBars.SetInt(5); Input_NeutralBars.SetIntLimits(1,MAX_STUDY_LENGTH); Input_Level.Name = "Level"; Input_Level.SetInt(100); Input_Level.SetIntLimits(1,MAX_STUDY_LENGTH); Input_CCIInputData.Name = "Input Data"; Input_CCIInputData.SetInputDataIndex(SC_HLC_AVG); Input_Version.SetInt(1); return; } //Current number of consecutive conditions CCI > 0 (or CCI < 0 if variable less zero) float& consec = Subgraph_Consecutive[sc.Index]; const float& PrevConsec = Subgraph_Consecutive[sc.Index-1]; float& currTrend= Subgraph_LastTrend[sc.Index]; // -1 - TrendDown; 1 - TrendUp float& lastTrend= Subgraph_LastTrend[sc.Index-1]; const float& currCCI = Subgraph_CCI[sc.Index]; int OccurGreatEdge=0; int OccurLessEdge=0; Subgraph_HiLevel[sc.Index] = (float)Input_Level.GetInt(); Subgraph_LowLevel[sc.Index] = (float)-Input_Level.GetInt(); sc.DataStartIndex= Input_CCILength.GetInt()-1; sc.CCI(sc.BaseData[Input_CCIInputData.GetInputDataIndex()], Subgraph_CCI, Input_CCILength.GetInt(), 0.015f); if(sc.Index == 0) { if(Subgraph_CCI[sc.Index] > 0) consec = 1; else if(Subgraph_CCI[sc.Index] < 0) consec = -1; else consec = 0; } else { if(currCCI > 0) { if(PrevConsec < 0) consec = 1; else consec = PrevConsec + 1; } else if(currCCI < 0) { if(PrevConsec > 0) consec = -1; else consec = PrevConsec - 1; } } for(int i = sc.Index; i>sc.Index-Input_NumberOfBars.GetInt(); i--) { if(Subgraph_CCI[i] > Input_Level.GetInt()) OccurGreatEdge++; else if(Subgraph_CCI[i] < -Input_Level.GetInt()) OccurLessEdge++; } bool trendUp = (currCCI > 0) && ((lastTrend == 1) || ((consec >= Input_NumberOfBars.GetInt()) && (OccurGreatEdge > 0))); bool trendDown = (currCCI < 0) && ((lastTrend == -1) || ((consec <= -Input_NumberOfBars.GetInt() ) && (OccurLessEdge > 0))); //Zero out subgraphs that color the main subgraph. This needs to be done in case one of these conditions is no longer met when a bar is forming. Subgraph_TrendUp[sc.Index] = 0; Subgraph_TrendDown[sc.Index] = 0; Subgraph_TrendNeutral[sc.Index] = 0; Subgraph_WorksheetOutput[sc.Index] = 0; if(trendUp) { Subgraph_TrendUp[sc.Index] = currCCI;//trend up currTrend = 1; Subgraph_WorksheetOutput[sc.Index] = 3; } else if(trendDown) { Subgraph_TrendDown[sc.Index] = currCCI;//trend down currTrend = -1; Subgraph_WorksheetOutput[sc.Index] = 1; } else { currTrend = lastTrend; if ((consec >= Input_NeutralBars.GetInt() && !trendUp) || ( -consec >= Input_NeutralBars.GetInt() && !trendDown) ) Subgraph_TrendNeutral[sc.Index] = currCCI;//trend neutral Subgraph_WorksheetOutput[sc.Index] = 2; } //Calculate the ZLR SCFloatArrayRef ZLRHooks = Subgraph_ZLR.Arrays[0]; // First extra array of ZLR subgraph if ((Subgraph_CCI[sc.Index-1] > Subgraph_CCI[sc.Index-2] && Subgraph_CCI[sc.Index] < Subgraph_CCI[sc.Index-1]) || (ZLRHooks[sc.Index-1] < 0 && Subgraph_CCI[sc.Index] <= Subgraph_CCI[sc.Index-1]) ) { ZLRHooks[sc.Index] = -1; if (ZLRHooks [sc.Index] <0 && Subgraph_CCI [sc.Index] <0) { Subgraph_ZLR[sc.Index] = -200; Subgraph_ZLR.DataColor[sc.Index] = Subgraph_ZLR.PrimaryColor; } else Subgraph_ZLR [sc.Index] = 0; } else if ((Subgraph_CCI[sc.Index-1] < Subgraph_CCI[sc.Index-2] && Subgraph_CCI[sc.Index] > Subgraph_CCI[sc.Index-1]) || (ZLRHooks[sc.Index-1] > 0 && Subgraph_CCI[sc.Index] >= Subgraph_CCI[sc.Index-1]) ) { ZLRHooks[sc.Index] = 1; if (ZLRHooks [sc.Index] >0 && Subgraph_CCI [sc.Index] >0) { Subgraph_ZLR[sc.Index] = 200; Subgraph_ZLR.DataColor[sc.Index] = Subgraph_ZLR.SecondaryColor; } else Subgraph_ZLR [sc.Index] = 0; } else { Subgraph_ZLR[sc.Index] = 0; ZLRHooks[sc.Index] = 0; } } /*============================================================================*/ SCSFExport scsf_CCIPredictor(SCStudyInterfaceRef sc) { SCSubgraphRef CCIProjHigh = sc.Subgraph[0]; SCSubgraphRef CCIProjLow = sc.Subgraph[1]; SCSubgraphRef CCIOutputHigh = sc.Subgraph[2]; SCSubgraphRef CCIOutputLow = sc.Subgraph[3]; SCInputRef CCILength = sc.Input[0]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "CCI Predictor"; sc.AutoLoop = 1; sc.GraphRegion = 1; CCIProjHigh.Name = "CCI Proj High"; CCIProjHigh.DrawStyle = DRAWSTYLE_ARROW_DOWN; CCIProjHigh.PrimaryColor = RGB(255,255,255); CCIProjHigh.LineWidth = 3; CCIProjHigh.DrawZeros = false; CCIProjLow.Name = "CCI Proj Low"; CCIProjLow.DrawStyle = DRAWSTYLE_ARROW_UP; CCIProjLow.PrimaryColor = RGB(255,255,255); CCIProjLow.LineWidth = 3; CCIProjLow.DrawZeros = false; CCILength.Name = "CCI Length"; CCILength.SetInt(14); return; } //CCI High CCIProjHigh.Arrays[0][sc.Index] = sc.HLCAvg[sc.Index]; if (sc.Index == sc.ArraySize - 1 && sc.AreRangeBars()) { float ProjectedRangeHigh=sc.Low[sc.Index]+sc.RangeBarValue; CCIProjHigh.Arrays[0][sc.Index] = ( ProjectedRangeHigh + ProjectedRangeHigh +sc.Low[sc.Index])/3; } sc.CCI(CCIProjHigh.Arrays[0], CCIOutputHigh, sc.Index, CCILength.GetInt(), 0.015f); if (sc.Index == sc.ArraySize - 1) CCIProjHigh[sc.Index] = CCIOutputHigh[sc.Index]; else CCIProjHigh[sc.Index] = 0; //CCI Low CCIProjLow.Arrays[0][sc.Index] = sc.HLCAvg[sc.Index]; if (sc.Index == sc.ArraySize - 1 && sc.AreRangeBars()) { float ProjectedRangeLow=sc.High[sc.Index]-sc.RangeBarValue; CCIProjLow.Arrays[0][sc.Index] = ( ProjectedRangeLow + ProjectedRangeLow +sc.High[sc.Index])/3; } sc.CCI(CCIProjLow.Arrays[0], CCIOutputLow, sc.Index, CCILength.GetInt(), 0.015f); if (sc.Index == sc.ArraySize - 1) CCIProjLow[sc.Index] = CCIOutputLow[sc.Index]; else CCIProjLow[sc.Index] = 0; } /*============================================================================*/ /*==========================================================================*/ // Candle Pattern Finder /*==========================================================================*/ struct s_CandleStickPatternsFinderSettings { int PriceRangeNumberOfBars; double PriceRangeMultiplier; int UseTrendDetection; s_CandleStickPatternsFinderSettings() { // default values PriceRangeNumberOfBars = 100; PriceRangeMultiplier = 0.01; UseTrendDetection = true; } }; // Candle dimensions inline double CandleLength(SCBaseDataRef InData, int index); inline double BodyLength(SCBaseDataRef InData, int index); inline double UpperWickLength(SCBaseDataRef InData, int index); inline double LowerWickLength(SCBaseDataRef InData, int index); // Helper functions int DetermineTrendForCandlestickPatterns(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& PatternsFinderSettings, int index,int num_of_candles); inline bool IsBodyStrong(SCBaseDataRef InData, int index); inline bool IsCandleStrength(SCBaseDataRef InData, int index); inline bool IsDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); inline bool IsBodyStrong(SCBaseDataRef InData, int index); inline bool IsCandleStrength(SCBaseDataRef InData, int index); inline bool IsWhiteCandle(SCBaseDataRef InData, int index); inline bool IsBlackCandle(SCBaseDataRef InData, int index); inline double PercentOfCandleLength(SCBaseDataRef InData, int index, double percent); inline double PercentOfBodyLength(SCBaseDataRef InData, int index, double percent); inline bool IsUpperWickSmall(SCBaseDataRef InData, int index, double percent); inline bool IsLowerWickSmall(SCBaseDataRef InData, int index, double percent); inline bool IsNearEqual(double value1, double value2, SCBaseDataRef InData, int index, double percent); // Formations bool IsHammer(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsHangingMan(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishEngulfing(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishEngulfing(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishEngulfingBodyOnly(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishEngulfingBodyOnly(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsDarkCloudCover(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsPiercingLine(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsMorningStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsEveningStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsMorningDojiStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsEveningDojiStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishAbandonedBaby(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishAbandonedBaby(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsShootingStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsInvertedHammer(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishHarami(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishHarami(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishHaramiCross(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishHaramiCross(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsTweezerTop(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsTweezerBottom(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishBeltHoldLine(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishBeltHoldLine(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsTwoCrows(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsThreeBlackCrows(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishCounterattackLine(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishCounterattackLine(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsThreeInsideUp(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsThreeOutsideUp(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsThreeInsideDown(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsThreeOutsideDown(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsKicker(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsKicking(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsThreeWhiteSoldiers(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsAdvanceBlock(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsDeliberation(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishTriStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishTriStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsUniqueThreeRiverBottom(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishDojiStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishDojiStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishDragonflyDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishDragonflyDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishGravestoneDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishGravestoneDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishLongleggedDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishLongleggedDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishSideBySideWhiteLines(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishSideBySideWhiteLines(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsFallingThreeMethods(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsRisingThreeMethods(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishSeparatingLines(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishSeparatingLines(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsDownsideTasukiGap(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsUpsideTasukiGap(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishThreeLineStrike(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBullishThreeLineStrike(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsDownsideGapThreeMethods(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsUpsideGapThreeMethods(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsOnNeck(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsInNeck(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsBearishThrusting(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); bool IsMatHold(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index); static const int CANDLESTICK_TREND_FLAT = 0; static const int CANDLESTICK_TREND_UP = 1; static const int CANDLESTICK_TREND_DOWN = -1; static const int TREND_FOR_PATTERNS = 8; /***********************************************************************/ SCSFExport scsf_CandleStickPatternsFinder(SCStudyInterfaceRef sc) { SCSubgraphRef Subgraph_Pattern1 = sc.Subgraph[0]; SCSubgraphRef Subgraph_Pattern2 = sc.Subgraph[1]; SCSubgraphRef Subgraph_Pattern3 = sc.Subgraph[2]; SCSubgraphRef Subgraph_Pattern4 = sc.Subgraph[3]; SCSubgraphRef Subgraph_Pattern5 = sc.Subgraph[4]; SCSubgraphRef Subgraph_Pattern6 = sc.Subgraph[5]; SCSubgraphRef Subgraph_TrendUp = sc.Subgraph[6]; SCSubgraphRef Subgraph_TrendDown = sc.Subgraph[7]; SCSubgraphRef Subgraph_TrendForPatterns = sc.Subgraph[TREND_FOR_PATTERNS]; SCInputRef Input_InputPattern1 = sc.Input[0]; SCInputRef Input_InputPattern2 = sc.Input[1]; SCInputRef Input_InputPattern3 = sc.Input[2]; SCInputRef Input_InputPattern4 = sc.Input[3]; SCInputRef Input_InputPattern5 = sc.Input[4]; SCInputRef Input_InputPattern6 = sc.Input[5]; SCInputRef Input_UseNumericValue = sc.Input[6]; SCInputRef Input_Distance = sc.Input[7]; SCInputRef Input_PriceRangeNumberOfBars = sc.Input[8]; SCInputRef Input_PriceRangeMultiplier = sc.Input[9]; SCInputRef Input_TrendDetection = sc.Input[10]; SCInputRef Input_TrendDetectionLength = sc.Input[11]; SCInputRef Input_DisplayText = sc.Input[12]; SCInputRef Input_DisplayAboveCandle = sc.Input[13]; if (sc.SetDefaults) { sc.GraphName="CandleStick Patterns Finder"; sc.StudyDescription="This study looks for candlestick patterns and identifies them on the chart with an abbreviation on the bar where they occur. It uses very advanced logic."; sc.AutoLoop = 1; sc.GraphRegion = 0; Subgraph_Pattern1.Name = "Pattern 1"; Subgraph_Pattern1.DrawStyle = DRAWSTYLE_CUSTOM_TEXT; Subgraph_Pattern1.PrimaryColor = RGB(255, 255, 0); Subgraph_Pattern1.SecondaryColor = RGB(0, 0, 0); Subgraph_Pattern1.SecondaryColorUsed = TRUE; Subgraph_Pattern1.LineWidth = 8; Subgraph_Pattern1.DrawZeros = false; Subgraph_Pattern2.Name = "Pattern 2"; Subgraph_Pattern2.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Pattern2.PrimaryColor = RGB(255, 255, 255); Subgraph_Pattern2.DrawZeros = false; Subgraph_Pattern3.Name = "Pattern 3"; Subgraph_Pattern3.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Pattern3.PrimaryColor = RGB(255, 255, 255); Subgraph_Pattern3.DrawZeros = false; Subgraph_Pattern4.Name = "Pattern 4"; Subgraph_Pattern4.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Pattern4.PrimaryColor = RGB(255, 255, 255); Subgraph_Pattern4.DrawZeros = false; Subgraph_Pattern5.Name = "Pattern 5"; Subgraph_Pattern5.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Pattern5.PrimaryColor = RGB(255, 255, 255); Subgraph_Pattern5.DrawZeros = false; Subgraph_Pattern6.Name = "Pattern 6"; Subgraph_Pattern6.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Pattern6.PrimaryColor = RGB(255, 255, 255); Subgraph_Pattern6.DrawZeros = false; Subgraph_TrendUp.Name = "Trend Up"; Subgraph_TrendUp.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_TrendUp.PrimaryColor = COLOR_GREEN; Subgraph_TrendUp.DrawZeros = false; Subgraph_TrendDown.Name = "Trend Down"; Subgraph_TrendDown.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_TrendDown.PrimaryColor = COLOR_RED; Subgraph_TrendDown.DrawZeros = false; Input_InputPattern1.Name="Pattern 1"; Input_InputPattern1.SetCandleStickPatternIndex(0); Input_InputPattern2.Name="Pattern 2"; Input_InputPattern2.SetCandleStickPatternIndex(0); Input_InputPattern3.Name="Pattern 3"; Input_InputPattern3.SetCandleStickPatternIndex(0); Input_InputPattern4.Name="Pattern 4"; Input_InputPattern4.SetCandleStickPatternIndex(0); Input_InputPattern5.Name="Pattern 5"; Input_InputPattern5.SetCandleStickPatternIndex(0); Input_InputPattern6.Name="Pattern 6"; Input_InputPattern6.SetCandleStickPatternIndex(0); Input_UseNumericValue.Name="Use Numeric Values Instead of Letter Codes"; Input_UseNumericValue.SetYesNo(0); Input_Distance.Name="Distance Between the Codes and the Candle as a Percentage"; Input_Distance.SetInt(5); Input_PriceRangeNumberOfBars.Name="Number of Bars for Price Range Detection (Used for Trend Detection)"; Input_PriceRangeNumberOfBars.SetInt(100); Input_PriceRangeMultiplier.Name="Price Range Multiplier for Determining Value Per Point"; Input_PriceRangeMultiplier.SetFloat(0.01f); Input_TrendDetection.Name = "Use Trend Detection"; Input_TrendDetection.SetYesNo(false); Input_TrendDetectionLength.Name = "Number of Bars Used For Trend Detection"; Input_TrendDetectionLength.SetInt(4); Input_TrendDetectionLength.SetIntLimits(1,MAX_STUDY_LENGTH); Input_DisplayText.Name= "Display Text"; Input_DisplayText.SetYesNo( true); Input_DisplayAboveCandle.Name= "Display Above Candles"; Input_DisplayAboveCandle.SetYesNo(false); return; } // This must always be custom text Subgraph_Pattern1.DrawStyle = DRAWSTYLE_CUSTOM_TEXT; // These must always be ignore Subgraph_Pattern2.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Pattern3.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Pattern4.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Pattern5.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Pattern6.DrawStyle = DRAWSTYLE_IGNORE; int & r_DrawingNumberForLastBar = sc.GetPersistentInt(1); if (sc.IsFullRecalculation) r_DrawingNumberForLastBar = 0; if (Subgraph_Pattern1.LineWidth <= 1) { Subgraph_Pattern1.LineWidth = 8; } const int NumberOfPatternsToDetect = 6; uint32_t PatternToLookFor[NumberOfPatternsToDetect]; PatternToLookFor[0] = Input_InputPattern1.GetCandleStickPatternIndex(); PatternToLookFor[1] = Input_InputPattern2.GetCandleStickPatternIndex(); PatternToLookFor[2] = Input_InputPattern3.GetCandleStickPatternIndex(); PatternToLookFor[3] = Input_InputPattern4.GetCandleStickPatternIndex(); PatternToLookFor[4] = Input_InputPattern5.GetCandleStickPatternIndex(); PatternToLookFor[5] = Input_InputPattern6.GetCandleStickPatternIndex(); s_CandleStickPatternsFinderSettings PatternsFinderSettings; if (Input_PriceRangeNumberOfBars.GetInt()>0) { PatternsFinderSettings.PriceRangeNumberOfBars = Input_PriceRangeNumberOfBars.GetInt(); } if (Input_PriceRangeMultiplier.GetFloat()>0) { PatternsFinderSettings.PriceRangeMultiplier = Input_PriceRangeMultiplier.GetFloat(); } PatternsFinderSettings.UseTrendDetection = Input_TrendDetection.GetYesNo(); bool DisplayNumericValue = (Input_UseNumericValue.GetYesNo() != 0 ); bool PatternDetected = false; bool PatternCodesToDisplay = false; int Direction = DetermineTrendForCandlestickPatterns(sc, PatternsFinderSettings, sc.Index-1,Input_TrendDetectionLength.GetInt()); Subgraph_TrendForPatterns[sc.Index] = (float)Direction; if (Direction == CANDLESTICK_TREND_UP) { Subgraph_TrendUp[sc.Index] = sc.Low[sc.Index]; Subgraph_TrendDown[sc.Index] = 0; } else if (Direction == CANDLESTICK_TREND_DOWN) { Subgraph_TrendUp[sc.Index] = 0; Subgraph_TrendDown[sc.Index] = sc.High[sc.Index]; } else { Subgraph_TrendUp[sc.Index] = 0; Subgraph_TrendDown[sc.Index] = 0; } SCString DisplayTextString; for (int Index = 0; Index < NumberOfPatternsToDetect; Index++) { sc.Subgraph[Index][sc.Index] = 0; PatternDetected = false; switch (PatternToLookFor[Index]) { case 1: PatternDetected = IsHammer(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 2: PatternDetected = IsHangingMan(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 3: PatternDetected = IsBullishEngulfing(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 4: PatternDetected = IsBearishEngulfing(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 5: PatternDetected = IsDarkCloudCover(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 6: PatternDetected = IsPiercingLine(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 7: PatternDetected = IsMorningStar(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 8: PatternDetected = IsEveningStar(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 9: PatternDetected = IsMorningDojiStar(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 10: PatternDetected = IsEveningDojiStar(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 11: PatternDetected = IsBullishAbandonedBaby(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 12: PatternDetected = IsBearishAbandonedBaby(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 13: PatternDetected = IsShootingStar(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 14: PatternDetected = IsInvertedHammer(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 15: PatternDetected = IsBearishHarami(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 16: PatternDetected = IsBullishHarami(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 17: PatternDetected = IsBearishHaramiCross(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 18: PatternDetected = IsBullishHaramiCross(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 19: PatternDetected = IsTweezerTop(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 20: PatternDetected = IsTweezerBottom(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 21: PatternDetected = IsBearishBeltHoldLine(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 22: PatternDetected = IsBullishBeltHoldLine(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 23: PatternDetected = IsTwoCrows(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 24: PatternDetected = IsThreeBlackCrows(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 25: PatternDetected = IsBearishCounterattackLine(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 26: PatternDetected = IsBullishCounterattackLine(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 27: PatternDetected = IsThreeInsideUp(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 28: PatternDetected = IsThreeOutsideUp(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 29: PatternDetected = IsThreeInsideDown(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 30: PatternDetected = IsThreeOutsideDown(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 31: PatternDetected = IsKicker(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 32: PatternDetected = IsKicking(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 33: PatternDetected = IsThreeWhiteSoldiers(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 34: PatternDetected = IsAdvanceBlock(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 35: PatternDetected = IsDeliberation(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 36: PatternDetected = IsBearishTriStar(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 37: PatternDetected = IsBullishTriStar(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 38: PatternDetected = IsUniqueThreeRiverBottom(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 39: PatternDetected = IsBearishDojiStar(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 40: PatternDetected = IsBullishDojiStar(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 41: PatternDetected = IsBearishDragonflyDoji(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 42: PatternDetected = IsBullishDragonflyDoji(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 43: PatternDetected = IsBearishGravestoneDoji(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 44: PatternDetected = IsBullishGravestoneDoji(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 45: PatternDetected = IsBearishLongleggedDoji(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 46: PatternDetected = IsBullishLongleggedDoji(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 47: PatternDetected = IsBearishSideBySideWhiteLines(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 48: PatternDetected = IsBullishSideBySideWhiteLines(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 49: PatternDetected = IsFallingThreeMethods(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 50: PatternDetected = IsRisingThreeMethods(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 51: PatternDetected = IsBearishSeparatingLines(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 52: PatternDetected = IsBullishSeparatingLines(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 53: PatternDetected = IsDownsideTasukiGap(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 54: PatternDetected = IsUpsideTasukiGap(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 55: PatternDetected = IsBearishThreeLineStrike(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 56: PatternDetected = IsBullishThreeLineStrike(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 57: PatternDetected = IsDownsideGapThreeMethods(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 58: PatternDetected = IsUpsideGapThreeMethods(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 59: PatternDetected = IsOnNeck(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 60: PatternDetected = IsInNeck(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 61: PatternDetected = IsBearishThrusting(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 62: PatternDetected = IsMatHold(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 63: PatternDetected = IsDoji(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 64: PatternDetected = IsBullishEngulfingBodyOnly(sc, PatternsFinderSettings, sc.CurrentIndex); break; case 65: PatternDetected = IsBearishEngulfingBodyOnly(sc, PatternsFinderSettings, sc.CurrentIndex); break; } if (PatternDetected) { sc.Subgraph[Index][sc.CurrentIndex] = (float)PatternToLookFor[Index]; if (Input_DisplayText.GetYesNo() && !sc.HideStudy) { SCString DisplayTextStringCopy = DisplayTextString; PatternCodesToDisplay = true; if (DisplayNumericValue) DisplayTextString.Format("%s%.2d%s", DisplayTextStringCopy.GetChars(), PatternToLookFor[Index], "\r\n"); else DisplayTextString.Format("%s%s%s", DisplayTextStringCopy.GetChars(), CandleStickPatternNames[PatternToLookFor[Index]][1], "\r\n"); } } } if (PatternCodesToDisplay && sc.Index < sc.ArraySize -1) { s_UseTool Tool; Tool.ChartNumber = sc.ChartNumber; Tool.DrawingType = DRAWING_TEXT; // Tool.LineNumber; Tool.BeginIndex = sc.CurrentIndex; Tool.Region = sc.GraphRegion; if (Input_DisplayAboveCandle.GetYesNo()) { Tool.BeginValue = sc.High[sc.Index] + ( (sc.High[sc.Index] - sc.Low[sc.Index]) * Input_Distance.GetInt() * 0.01f); Tool.TextAlignment = DT_CENTER | DT_BOTTOM; } else { Tool.BeginValue = sc.Low[sc.Index] - ( (sc.High[sc.Index] - sc.Low[sc.Index]) * Input_Distance.GetInt() * 0.01f); Tool.TextAlignment = DT_CENTER | DT_TOP; } Tool.Color = Subgraph_Pattern1.PrimaryColor; Tool.FontBackColor = Subgraph_Pattern1.SecondaryColor; Tool.FontSize = Subgraph_Pattern1.LineWidth; Tool.FontBold = TRUE; Tool.Text.Format("%s",DisplayTextString.GetChars()); Tool.AddMethod = UTAM_ADD_ALWAYS; sc.UseTool(Tool); } else if(sc.Index == sc.ArraySize -1)//last bar in chart { s_UseTool Tool; Tool.ChartNumber = sc.ChartNumber; Tool.DrawingType = DRAWING_TEXT; if (r_DrawingNumberForLastBar != 0) Tool.LineNumber = r_DrawingNumberForLastBar; Tool.BeginIndex = sc.CurrentIndex; Tool.Region = sc.GraphRegion; if (Input_DisplayAboveCandle.GetYesNo()) { Tool.BeginValue = sc.High[sc.Index] + ( (sc.High[sc.Index] - sc.Low[sc.Index]) * Input_Distance.GetInt() * 0.01f); Tool.TextAlignment = DT_CENTER | DT_BOTTOM; } else { Tool.BeginValue = sc.Low[sc.Index] - ( (sc.High[sc.Index] - sc.Low[sc.Index]) * Input_Distance.GetInt() * 0.01f); Tool.TextAlignment = DT_CENTER | DT_TOP; } Tool.Color = Subgraph_Pattern1.PrimaryColor; Tool.FontBackColor = Subgraph_Pattern1.SecondaryColor; Tool.FontSize = Subgraph_Pattern1.LineWidth; Tool.FontBold = TRUE; if(DisplayTextString.GetLength() == 0) DisplayTextString = " "; Tool.Text.Format("%s",DisplayTextString.GetChars()); Tool.AddMethod = UTAM_ADD_OR_ADJUST; sc.UseTool(Tool); r_DrawingNumberForLastBar = Tool.LineNumber; } return; } /*==========================================================================*/ inline double UpperWickLength(SCBaseDataRef InData, int index) { double upperBoundary = max(InData[SC_LAST][index], InData[SC_OPEN][index]); double upperWickLength = InData[SC_HIGH][index] - upperBoundary; return upperWickLength; } /*==========================================================================*/ inline double LowerWickLength(SCBaseDataRef InData, int index) { double lowerBoundary = min(InData[SC_LAST][index], InData[SC_OPEN][index]); double lowerWickLength = lowerBoundary - InData[SC_LOW][index]; return lowerWickLength; } /*==========================================================================*/ inline double CandleLength(SCBaseDataRef InData, int index) { return InData[SC_HIGH][index]-InData[SC_LOW][index]; } /*==========================================================================*/ inline double BodyLength(SCBaseDataRef InData, int index) { return fabs(InData[SC_OPEN][index] - InData[SC_LAST][index]); } /*==========================================================================*/ inline double PercentOfCandleLength(SCBaseDataRef InData, int index, double percent) { return CandleLength(InData, index) * (percent / 100.0); } /*==========================================================================*/ inline double PercentOfBodyLength(SCBaseDataRef InData, int index, double percent) { return BodyLength(InData, index) * percent / 100.0; } /*==========================================================================*/ const int k_Body_NUM_OF_CANDLES = 5; // number of previous candles to calculate body strength inline bool IsBodyStrong(SCBaseDataRef InData, int index) { // detecting whether candle has a strong body or not bool ret_flag = false; // calculating average length of bodies of last NUM_OF_CANDLES float mov_aver = 0; for (int i = 1; imov_aver) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const int k_Candle_NUM_OF_CANDLES = 5; // number of previous candles to calculate candle strength const double k_CandleStrength_Multiplier = 1.0; inline bool IsCandleStrength(SCBaseDataRef InData, int index) { // detecting whether candle has a strong body or not bool ret_flag = false; // calculating average length of bodies of last NUM_OF_CANDLES float mov_aver = 0; for (int i = 1; i mov_aver*k_CandleStrength_Multiplier) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ int DetermineTrendForCandlestickPatterns(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& PatternsFinderSettings, int index, int num_of_candles) { // detecting trend // index: index of the last candle in trend // num_of_candles: minimum number of candles required const double UptrendPercent = 1.0; const double DowntrendPercent = -1.0; // Using linear regression to estimate the slope SCBaseDataRef InData = sc.BaseData; double sumx = 0.0; double sumy = 0.0; double sumxx = 0.0; double sumyy = 0.0; double sumxy = 0.0; for (int IndexOffset=1; IndexOffset<=num_of_candles;IndexOffset++) { double value = InData[SC_HL_AVG][index-(IndexOffset-1)]; sumx += -IndexOffset; sumy += value; sumxx += IndexOffset*IndexOffset; sumyy += value*value; sumxy += -IndexOffset*value; } double n = double(num_of_candles); double Sxy = n*sumxy-sumx*sumy; double Sxx = n*sumxx-sumx*sumx; double Slope = Sxy/Sxx; // slope value // estimate the value per point: double high=sc.GetHighest(InData[SC_HIGH], index, PatternsFinderSettings.PriceRangeNumberOfBars); double low=sc.GetLowest(InData[SC_LOW], index, PatternsFinderSettings.PriceRangeNumberOfBars); double range = high - low; double valuePerPoint = range * PatternsFinderSettings.PriceRangeMultiplier; // detect trend double CorrectSlope = Slope / valuePerPoint; if (CorrectSlope>UptrendPercent) { return CANDLESTICK_TREND_UP; } else if (CorrectSlopeInData[SC_OPEN][index]; } /*==========================================================================*/ inline bool IsBlackCandle(SCBaseDataRef InData, int index) { return InData[SC_LAST][index] InData[SC_OPEN][index]) { if ((InData[SC_HIGH][index] > InData[SC_HIGH][index - 1]) && (InData[SC_LOW][index] < InData[SC_LOW][index - 1]) && (InData[SC_LAST][index] > InData[SC_OPEN][index - 1]) && (InData[SC_OPEN][index] < InData[SC_LAST][index - 1])) { ret_flag = true; } } } return ret_flag; } /*==========================================================================*/ // Reference: http://www.investopedia.com/terms/b/bearishengulfingp.asp bool IsBearishEngulfing(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // up { if(InData[SC_LAST][index-1] > InData[SC_OPEN][index-1] && InData[SC_LAST][index] < InData[SC_OPEN][index]) { if ((InData[SC_HIGH][index] > InData[SC_HIGH][index - 1]) && (InData[SC_LOW][index] < InData[SC_LOW][index - 1]) && (InData[SC_OPEN][index] > InData[SC_LAST][index - 1]) && (InData[SC_LAST][index] < InData[SC_OPEN][index - 1])) { ret_flag = true; } } } return ret_flag; } /*==========================================================================*/ bool IsBullishEngulfingBodyOnly(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // down { if (InData[SC_LAST][index - 1] < InData[SC_OPEN][index - 1] && InData[SC_LAST][index] > InData[SC_OPEN][index]) { if ((InData[SC_LAST][index] > InData[SC_OPEN][index - 1]) && (InData[SC_OPEN][index] < InData[SC_LAST][index - 1])) { ret_flag = true; } } } return ret_flag; } /*==========================================================================*/ bool IsBearishEngulfingBodyOnly(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // up { if (InData[SC_LAST][index - 1] > InData[SC_OPEN][index - 1] && InData[SC_LAST][index] < InData[SC_OPEN][index]) { if ((InData[SC_OPEN][index] > InData[SC_LAST][index - 1]) && (InData[SC_LAST][index] < InData[SC_OPEN][index - 1])) { ret_flag = true; } } } return ret_flag; } /*==========================================================================*/ const double k_DarkCloudCover_OverlapPercent = 50.0; bool IsDarkCloudCover(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // DARK CLOUD COVER // 1. Uptrend // 2. Strong white body [index-1] // 3. Open [index] is higher then High of candle [index-1] // 4. Close [index] is lower then OVERLAP_PERCENT of white body of candle [index-1] /*1. Market is characterized by an uptrend. 2. We see a long white candlestick in the first day. 3. Then we see a black body characterized by an open above the high of the previous day on the second day. 4. The second black candlestick closes within and below the midpoint of the previous white body.*/ SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if( (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // uptrend && IsWhiteCandle(InData, index-1) // check for white body && IsBodyStrong(InData,index-1) && IsBlackCandle(InData, index) // 0 candle is black && (InData[SC_OPEN][index]>InData[SC_HIGH][index-1]) // open 0 is higher then high of -1 && (InData[SC_LAST][index]<(InData[SC_LAST][index-1]-PercentOfBodyLength(InData, index-1, k_DarkCloudCover_OverlapPercent))) // check for the overlap between white body and black OVERLAP_PERCENT ) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const double k_PiercingLine_OverlapPercent = 50.0; bool IsPiercingLine(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // PIERCING LINE // 1. Downtrend // 2. Strong black body [index-1] // 3. Open [index] less than low of candle [index-1] // 4. Close [index] is higher than white body of candle [index-1] by OverlapPercent SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // downtrend { if (IsBlackCandle(InData, index-1)) // check for black body, -1th candle is black { if (IsWhiteCandle(InData, index) && // 0th candle is white (InData[SC_OPEN][index](InData[SC_OPEN][index-1]-PercentOfBodyLength(InData, index-1, k_PiercingLine_OverlapPercent))) { if(IsBodyStrong(InData,index-1)) // strong body of -1th candle { ret_flag = true; } } } } } return ret_flag; } /*==========================================================================*/ const double k_MorningStar_OverlapPercent = 50.0; bool IsMorningStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // MORNING STAR // 1. Downtrend // 2. Strong black body of candle [index-2] // 3. Any weak body of candle [index-1], but not Doji // 4. Strong white body of candle [index] overlap more then OVERLAP_PERCENT of the body of candle [index-2] /*1. Market is characterized by downtrend. 2. We see a long black candlestick in the first day. 3. Then we see a small body on the second day gapping in the direction of the previous downtrend. 4. Finally we see a white candlestick on the third day*/ SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if( (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) && IsBlackCandle(InData, index-2) && IsBodyStrong(InData,index-2) && (InData[SC_OPEN][index-1] < InData[SC_LOW][index-2])// body of -1 candle below low of -2 candle && (InData[SC_LAST][index-1] < InData[SC_LOW][index-2]) //&& !IsDoji(sc, settings, index-1) // -1 candle is not Doji && !IsBodyStrong(InData,index-1) // body of -1 candle is weak && IsWhiteCandle(InData, index) && IsBodyStrong(InData,index) && (InData[SC_OPEN][index](InData[SC_OPEN][index-2]-PercentOfBodyLength(InData, index, k_MorningStar_OverlapPercent))) // body of the candle 0 overlaps the body of the candle -2 ) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const double k_EveningStar_OverlapPercent = 50.0; bool IsEveningStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // EVENING STAR // 1. Uptrend // 2. Strong white body of candle [index-2] // 3. Any weak body of candle [index-1], but not Doji // 4. Strong black body of candle [index] overlaps more then OVERLAP_PERCENT of body of candle [index-2]. -I have not found any info about overlapping SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // check for uptrend { if(IsWhiteCandle(InData, index-2)) // body of candle -2 is white { if(IsBodyStrong(InData,index-2)) // body of candle -2 is strong { if ((InData[SC_OPEN][index-1] > InData[SC_HIGH][index-2])&& // body of candle -1 higher then maximum. - This line does not correspond to what I found online it should not matter, the gap should be between the bodies. (InData[SC_LAST][index-1] > InData[SC_LOW][index-2]) //&& !IsDoji(sc,settings,index-1) // candle -1 is not Doji ) { if(!IsBodyStrong(InData,index-1)) // body of the candle -1 is weak { if (IsBlackCandle(InData,index) && // body of the candle 0 is black (InData[SC_OPEN][index]>InData[SC_LAST][index-2]) && // body of the candle 0 starts higher then body of candle -2 (InData[SC_LAST][index]<(InData[SC_LAST][index-2]-PercentOfBodyLength(InData, index-2, k_EveningStar_OverlapPercent)))) // body of candle 0 overlaps body of candle -2. Did not find written reference to this, but all images support this. { if (IsBodyStrong(InData,index)) // body of candle 0 is strong { ret_flag = true; } } } } } } } return ret_flag; } /*==========================================================================*/ const double k_MorningDojiStar_OverlapPercent = 50.0; bool IsMorningDojiStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // MORNING DOJI STAR // 1. Downtrend // 2. Strong black body of candle [index-2] // 3. [index-1] candle is Doji. (2nd day is a doji which gaps below the 1st day's close.) // 4. Strong white body of candle [index] overlap more then OVERLAP_PERCENT of body of the candle [index-2] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if( (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // check for downtrend && IsBlackCandle(InData,index-2) // body of the candle -2 is black && IsBodyStrong(InData,index-2) // body of the candle -2 is strong && (InData[SC_HIGH][index-1] < InData[SC_LAST][index-2])// the -1 candle is below the close of candle -2 && IsDoji(sc, settings, index-1) // -1 candle is Doji && IsWhiteCandle(InData,index) // body of the candle 0 is white && (InData[SC_OPEN][index](InData[SC_OPEN][index-2]-PercentOfBodyLength(InData, index-2, k_MorningDojiStar_OverlapPercent)))// body of the candle 0 overlaps body of the candle -2 && IsBodyStrong(InData,index) // body of the candle 0 is strong ) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const double k_EveningDojiStar_OverlapPercent = 50.0; bool IsEveningDojiStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // EVENING DOJI STAR // 1. Uptrend // 2. Strong white body of candle [index-2] // 3. candle [index-1] 2nd day is a doji which gaps above the [index-2] 1st day's close. // 4. Strong black body of candle [index] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if( (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // check for uptrend && IsWhiteCandle(InData, index-2) // body of the -2 candle is white && IsBodyStrong(InData,index-2) // body of th -2 candle is strong && InData[SC_OPEN][index-1] > InData[SC_HIGH][index-2] // body of the -1 candle is higher then maximum of -2 candle && IsDoji(sc, settings, index-1) // -1 candle is Doji && IsBlackCandle(InData, index) // body of the 0 candle is black && InData[SC_OPEN][index]>InData[SC_LAST][index-2] // body of the 0 candle starts higher then body of -2 candle //&&(InData[SC_LAST][index]<(InData[SC_LAST][index-2]-PercentOfBodyLength(InData, index-2, k_EveningDojiStar_OverlapPercent)))) // body of the 0 candle overlaps the body of -2 candle //This is not a requirement && IsBodyStrong(InData,index) // body of candle 0 is strong ) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const double k_BullishAbandonedBaby_OverlapPercent = 50.0; bool IsBullishAbandonedBaby(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH ABNDONED BABY // 1. Downtrend // 2. Strong black body of candle [index-2] // 3. Candle [index-1] - Doji // 4. Strong white body of candle [index] overlaps more then OVERLAP_PERCENT of the body of candle [index-2]. Is not included in web descriptions but is logical. // 5. Gap between -1 and 0 candles, -1 and -2 candles SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // check for downtrend { if(IsBlackCandle(InData, index-2)) // body of candle -2 is black { if(IsBodyStrong(InData,index-2)) // body of the candle -2 is strong { if ((InData[SC_OPEN][index-1] < InData[SC_LOW][index-2]) && // body of the candle -1 is below the minimum of candle -2 IsDoji(sc, settings, index-1)) // -1 candle is Doji { if (IsWhiteCandle(InData, index) && // body of candle 0 is white (InData[SC_OPEN][index](InData[SC_OPEN][index-2]-PercentOfBodyLength(InData, index-2, k_BullishAbandonedBaby_OverlapPercent)))) // body of candle 0 overlaps with body of candle -2 { if (IsBodyStrong(InData,index)) // body of candle 0 is strong { if ((InData[SC_LOW][index-2]>InData[SC_HIGH][index-1]) && // gap between candle -2 and -1 (InData[SC_LOW][index]>InData[SC_HIGH][index-1])) // gap between candle -0 and -1 { ret_flag = true; } } } } } } } return ret_flag; } /*==========================================================================*/ const double k_BearishAbandonedBaby_OverlapPercent = 50.0; bool IsBearishAbandonedBaby(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BEARISH ABNDONED BABY // 1. Uptrend // 2. Strong white body of candle [index-2] // 3. Weak body of candle [index-1] // 4. Candle [index-1] is Doji // 5. Strong black body of candle [index] overlaps more then OVERLAP_PERCENT of body of candle [index-2] // 6. Gap between candle -1 and 0, -1 and 2 candles SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // check for uptrend { if(IsWhiteCandle(InData, index-2)) // body of candle -2 is white { if(IsBodyStrong(InData,index-2)) // body of candle -2 is strong { if ((InData[SC_OPEN][index-1] > InData[SC_HIGH][index-2]) && // body of candle -1 is higher than maximum of candle -2 IsDoji(sc, settings, index-1)) // candle -1 is Doji { if (IsBlackCandle(InData, index) && // body candle 0 is black (InData[SC_OPEN][index]>InData[SC_LAST][index-2]) &&// body of candle 0 starts higher then body of candle -2 (InData[SC_LAST][index]<(InData[SC_LAST][index-2]-PercentOfBodyLength(InData, index-2, k_BearishAbandonedBaby_OverlapPercent)))) // body of candle 0 overlaps body of candle -2 { if (IsBodyStrong(InData,index)) // body of candle 0 is strong { if ((InData[SC_HIGH][index-2](InData[SC_OPEN][index]-InData[SC_LOW][index])) &&((InData[SC_HIGH][index]-InData[SC_LAST][index])>(InData[SC_LAST][index]-InData[SC_LOW][index])) ) { // Upper wick is 3 times longer then the body if(UpperWickLength(InData, index) >= PercentOfBodyLength(InData, index, k_ShootingStar_UpperWickPercent)) { // Lower wick is insignificant if(IsLowerWickSmall(InData, index, k_ShootingStar_LowerWickPercent)) { ret_flag = true; } } } } } return ret_flag; } /*==========================================================================*/ const double k_InvertedHammer_LowerWickPercent = 7.0; const double k_InvertedHammer_UpperWickPercent = 200.0; bool IsInvertedHammer(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // INVERTED HAMMER // 1. Downtrend // 2. Small body of candle [index] is in the lower part of the candle // 3. The upper shadow is no more than two times as long as the body // 4. Lower wick [index] of the candle is either absent or small SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // downtrend { if (!IsBodyStrong(InData,index)) // candle 0 has weak body { // check that body is in the lower part of the candle if (((InData[SC_HIGH][index]-InData[SC_OPEN][index])>(InData[SC_OPEN][index]-InData[SC_LOW][index])) &&((InData[SC_HIGH][index]-InData[SC_LAST][index])>(InData[SC_LAST][index]-InData[SC_LOW][index])) && !IsDoji(sc, settings, index)) // candle is not Doji { // The upper shadow is no more than two times as long as the body. if(UpperWickLength(InData, index)<=PercentOfBodyLength(InData, index, k_InvertedHammer_UpperWickPercent)) { // lower wick is insignificant if(IsLowerWickSmall(InData, index, k_InvertedHammer_LowerWickPercent)) { ret_flag = true; } } } } } return ret_flag; } /*==========================================================================*/ bool IsBearishHarami(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BEARISH HARAMI // 1. Uptrend // 2. Strong body of candle [index-1] // 3. Weak body of candle [index] does not extend beyond the limits of the body of candle [index-1] // 4. Candle [index] is not Doji SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // Uptrend { if (IsBodyStrong(InData,index-1)) // Strong body of candle -1 { if(!IsDoji(sc, settings, index)) // candle 0 is not Doji { if(!IsBodyStrong(InData,index)) // weak body of candle 0 { if(InData[SC_OPEN][index-1] > InData[SC_LAST][index-1]) // part of a check that one body does not extend beyond the limits of the other body { if(InData[SC_OPEN][index] > InData[SC_LAST][index]) // part of a check that one body does not extend beyond the limits of the other body { // body of the candle 0 does not extend beyond the limits of the body of candle -1 if ((InData[SC_OPEN][index-1]>=InData[SC_OPEN][index]) && (InData[SC_LAST][index-1]<=InData[SC_LAST][index])) { ret_flag = true; } } else // part of a check that one body does not extend beyond the limits of the other body { // body of the candle 0 does not extend beyond the limits of the body of candle -1 if ((InData[SC_OPEN][index-1]>=InData[SC_LAST][index]) && (InData[SC_LAST][index-1]<=InData[SC_OPEN][index])) { ret_flag = true; } } } else // part of a check that one body does not extend beyond the limits of the other body { if(InData[SC_OPEN][index] > InData[SC_LAST][index]) // part of a check that one body does not extend beyond the limits of the other body { // body of the candle 0 does not extend beyond the limits of the body of candle -1 if ((InData[SC_LAST][index-1]>=InData[SC_OPEN][index]) && (InData[SC_OPEN][index-1]<=InData[SC_LAST][index])) { ret_flag = true; } } else // part of a check that one body does not extend beyond the limits of the other body { // body of the candle 0 does not extend beyond the limits of the body of candle -1 if ((InData[SC_LAST][index-1]>=InData[SC_LAST][index]) && (InData[SC_OPEN][index-1]<=InData[SC_OPEN][index])) { ret_flag = true; } } } } } } } return ret_flag; } /*==========================================================================*/ bool IsBullishHarami(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH HARAMI // 1. Downtrend // 2. Strong body of candle [index-1] // 3. Weak body of candle [index] does not extend beyond the limits of the body of candle [index-1] // 4. Candle [index] is not Doji SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // downtrend { if (IsBodyStrong(InData,index-1)) // Strong body of candle [index-1] { if(!IsDoji(sc, settings, index)) // candle 0 is not Doji { if(!IsBodyStrong(InData,index)) // weak body of candle 0 { if(InData[SC_OPEN][index-1] > InData[SC_LAST][index-1]) // part of a check that one body does not extend beyond the limits of the other body { if(InData[SC_OPEN][index] > InData[SC_LAST][index]) // part of a check that one body does not extend beyond the limits of the other body { // body of the candle 0 does not extend beyond the limits of the body of candle -1 if ((InData[SC_OPEN][index-1]>=InData[SC_OPEN][index]) && (InData[SC_LAST][index-1]<=InData[SC_LAST][index])) { ret_flag = true; } } else // part of a check that one body does not extend beyond the limits of the other body { // body of the candle 0 does not extend beyond the limits of the body of candle -1 if ((InData[SC_OPEN][index-1]>=InData[SC_LAST][index]) && (InData[SC_LAST][index-1]<=InData[SC_OPEN][index])) { ret_flag = true; } } } else // part of a check that one body does not extend beyond the limits of the other body { if(InData[SC_OPEN][index] >= InData[SC_LAST][index]) // part of a check that one body does not extend beyond the limits of the other body { // body of the candle 0 does not extend beyond the limits of the body of candle -1 if ((InData[SC_LAST][index-1]>=InData[SC_OPEN][index]) && (InData[SC_OPEN][index-1]<=InData[SC_LAST][index])) { ret_flag = true; } } else // part of a check that one body does not extend beyond the limits of the other body { // body of the candle 0 does not extend beyond the limits of the body of candle -1 if ((InData[SC_LAST][index-1]>=InData[SC_LAST][index]) && (InData[SC_OPEN][index-1]<=InData[SC_OPEN][index])) { ret_flag = true; } } } } } } } return ret_flag; } /*==========================================================================*/ bool IsBearishHaramiCross(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BEARISH HARAMI CROSS // 1. Uptrend // 2. Strong body of candle [index-1] // 3. Candle [index] is Doji // 4. Body of candle [index] does not extend beyond the limits of the body of the candle [index-1] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // uptrend { if (IsBodyStrong(InData,index-1)) // strong body of the candle -1 { if(IsDoji(sc, settings, index)) // candle 0 is Doji { if(InData[SC_OPEN][index-1] > InData[SC_LAST][index-1]) // part of a check that one body does not extend beyond the limits of the other body { // body of the candle 0 does not extend beyond the limits of the body of candle -1 if ((InData[SC_OPEN][index-1]>InData[SC_LAST][index]) && (InData[SC_LAST][index-1]=InData[SC_LAST][index]) && (InData[SC_OPEN][index-1]<=InData[SC_LAST][index])) { ret_flag = true; } } } } } return ret_flag; } /*==========================================================================*/ bool IsBullishHaramiCross(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH HARAMI CROSS // 1. Downtrend // 2. Strong body of the candle [index-1] // 3. candle [index] is Doji // 4. Candle [index] does not extend beyond the limits of the body of the candle [index-1] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // Downtrend { if (IsBodyStrong(InData,index-1)) // strong body of the candle -1 { if(IsDoji(sc, settings, index)) // candle 0 is Doji { if(InData[SC_OPEN][index-1] > InData[SC_LAST][index-1]) // part of a check that one body does not extend beyond the limits of the other body { // body of the candle 0 does not extend beyond the limits of the body of candle -1 if ((InData[SC_OPEN][index-1]>InData[SC_LAST][index]) && (InData[SC_LAST][index-1]InData[SC_LAST][index]) && (InData[SC_OPEN][index-1]=InData[SC_LAST][index] && InData[SC_LAST][index]>InData[SC_LAST][index-2] // 3rd day closes above the close of the 1st day. ) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const double k_ThreeBlackCrows_LowerWickPercent= 7.0; bool IsThreeBlackCrows(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // THREE BLACK CROWS // 1. Uptrend // 2. Three consecutive black days with lower closes each day. // 3. Each day opens within the body of the previous day. SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if( (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // uptrend && (IsBlackCandle(InData, index-2) && IsBlackCandle(InData, index-1) && IsBlackCandle(InData, index)) && InData[SC_LAST][index-2]>InData[SC_LAST][index-1] && InData[SC_LAST][index-1]>InData[SC_LAST][index] && InData[SC_OPEN][index-1]<=InData[SC_OPEN][index-2] && InData[SC_OPEN][index-1]>=InData[SC_LAST][index-2] && InData[SC_OPEN][index]<=InData[SC_OPEN][index-1] && InData[SC_OPEN][index]>=InData[SC_LAST][index-1]) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const double k_BearishCounterattackLine_SimularityPercent = 7.0; bool IsBearishCounterattackLine(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BEARISH COUNTERATTACK LINE // 1. Uptrend // 2. The candles [index] and [index-1] are of contrast colors and their close prices are equal //Bearish Counterattack Line //In an uptrending market, a large white candlestick is following by a large black candlestick that opens on a big gap higher and then slumps back during the period to close at the same price as the previous close. The bearish black candlestick needs followup action to the downside to confirm the turn to a downtrend. SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // uptrend { // close prices are equal if(IsNearEqual(InData[SC_LAST][index], InData[SC_LAST][index-1], InData, index, k_BearishCounterattackLine_SimularityPercent)) { // check for the colors contrast if (IsWhiteCandle(InData, index-1) &&IsBodyStrong(InData,index-1)) { if(IsBlackCandle(InData, index) && IsBodyStrong(InData,index)) { ret_flag = true; } } /*else if (IsBlackCandle(InData, index-1)) { if(IsWhiteCandle(InData, index)) { ret_flag = true; } }*/ } } return ret_flag; } /*==========================================================================*/ const double k_BullishCounterattackLine_SimularityPercent = 7.0; bool IsBullishCounterattackLine(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH COUNTERATTACK LINE // 1. Downtrend // 2. The candles [index] and [index-1] are of contrast colors and their close prices are equal //Bullish Counterattack Line //In a downtrending market, a large black candlestick is following by a large white candlestick that opens on a big gap lower and then rallies during the period to close at the same price as the previous close. The bullish white candlestick needs followup action to the upside to confirm the turn to an uptrend. SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // downtrend { // close prices are equal if(IsNearEqual(InData[SC_LAST][index], InData[SC_LAST][index-1], InData, index, k_BullishCounterattackLine_SimularityPercent)) { // check for the colors contrast /*if (IsWhiteCandle(InData, index-1)) { if(IsBlackCandle(InData, index)) { ret_flag = true; } } else*/ if (IsBlackCandle(InData, index-1) && IsBodyStrong(InData,index-1)) { if(IsWhiteCandle(InData, index) && IsBodyStrong(InData,index)) { ret_flag = true; } } } } return ret_flag; } /*==========================================================================*/ bool IsThreeInsideUp(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // THREE INSIDE UP // 1. Downtrend // 2. The candle [index] is white and the close price higher than the close price of the candle [index-1] // 3. The candles [index-2] and [index-3] form Bullish Harami Pattern SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // downtrend { if (IsWhiteCandle(InData,index) && // the candle 0 is white (InData[SC_LAST][index]>InData[SC_LAST][index-1])) // the close price of the candle 0 is higher than the close price of the candle -1 { if(IsBullishHarami(sc,settings,index-1)) { ret_flag = true; } } } return ret_flag; } /*==========================================================================*/ bool IsThreeOutsideUp(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // THREE OUTSIDE UP // 1. Downtrend // 2. The candle [index] is white, and its close price is higher than the close price of the candle [index-1] // 3. Candles [index-2] and [index-3] form Bullish Engulfing Pattern SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // downtrend { if (IsWhiteCandle(InData, index) && // the candle 0 is white (InData[SC_LAST][index]>InData[SC_LAST][index-1])) // CLOSE of the candle 0 is higher than CLOSE of the candle -1 { if(IsBullishEngulfing(sc,settings,index-1)) { ret_flag = true; } } } return ret_flag; } /*==========================================================================*/ bool IsThreeInsideDown(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // THREE INSIDE DOWN // 1. Uptrend // 2. The candle [index] is black, and its close price is lower than the close price of the the candle [index-1] // 3. The candles [index-2] and [index-3] form Bearish Harami Pattern SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // uptrend { if(IsBlackCandle(InData, index) && // the candle 0 is black (InData[SC_LAST][index]=InData[SC_OPEN][index-1])) { // OPEN of the candle -1 inside the body of the candle -2 if ((InData[SC_OPEN][index-1]<=InData[SC_LAST][index-2])&& (InData[SC_OPEN][index-1]>=InData[SC_OPEN][index-2])) { // check for upper wicks if(IsUpperWickSmall(InData, index, k_ThreeWhiteSoldiers_UpperWickPercent) && IsUpperWickSmall(InData, index-1, k_ThreeWhiteSoldiers_UpperWickPercent)&& IsUpperWickSmall(InData, index-2, k_ThreeWhiteSoldiers_UpperWickPercent) ) { ret_flag = true; } } } } } return ret_flag; } /*==========================================================================*/ bool IsAdvanceBlock(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // ADVANCE BLOCK // 1. Uptrend till the candle 0 // 2. The candles [index], [index-1] and [index-2] are white // 3. Opens of candles [index], [index-1] are inside the bodies of the previous candles // 4. The body of the candle [index] is smaller than the body of the candle [index-1], //and the body of the candle [index-1] is smaller than the body of the candle [index-2] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // Uptrend { if (IsWhiteCandle(InData, index) && // the candle 0 is white IsWhiteCandle(InData, index-1) && // the candle -1 is white IsWhiteCandle(InData, index-2)) // the candle -2 is white { // OPEN of the candle 0 is inside the body of the candle -1 if ((InData[SC_OPEN][index]<=InData[SC_LAST][index-1])&& (InData[SC_OPEN][index]>=InData[SC_OPEN][index-1])) { // OPEN of the candle -1 is inside the body of the candle -2 if ((InData[SC_OPEN][index-1]<=InData[SC_LAST][index-2])&& (InData[SC_OPEN][index-1]>=InData[SC_OPEN][index-2])) { // check for the size of the body if(BodyLength(InData,index) < BodyLength(InData, index-1) && BodyLength(InData, index-1) < BodyLength(InData, index-2)) { ret_flag = true; } } } } } return ret_flag; } /*==========================================================================*/ const int k_Deliberation_UpperWickPercent = 7; bool IsDeliberation(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // DELIBERATION // 1. Uptrend till the candle 0 // 2. The candles [index], [index-1] and [index-2] are white // 3. OPENs of the candle [index-1] is inside the body of the previous candle // 4. The candle [index-1] has a strong body // 5. Candle [index] has a weak body SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // uptrend { if (IsWhiteCandle(InData, index) && // Candle 0 is white IsWhiteCandle(InData, index-1) && // Candle -1 is white IsWhiteCandle(InData, index-2)) // Candle -2 is white { // OPEN of the candle 0 is inside of the body of the candle -1 /*if ((InData[SC_OPEN][index]InData[SC_OPEN][index-1]))*/ { // OPEN of the candle -1 is inside of the body of the candle -2 if ((InData[SC_OPEN][index-1]<=InData[SC_LAST][index-2])&& (InData[SC_OPEN][index-1]>=InData[SC_OPEN][index-2])) { // body of the candle -1 is strong if(IsBodyStrong(InData,index-1)) { // candle -1 does not have an upper wick //if (IsUpperWickSmall(InData, index-1, k_Deliberation_UpperWickPercent)) { // body of the candle 0 is weak if(!IsBodyStrong(InData,index)) { ret_flag = true; } } } } } } } return ret_flag; } /*==========================================================================*/ const int k_BearishTriStar_PAST_INDEX = 3; bool IsBearishTriStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BEARISH TRI STAR //1. Market is characterized by uptrend. //2. We see three Dojis on three consecutive days. //3. The second day Doji has a gap above the first and third. SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; // the candle 0 is Doji if((settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) && IsDoji(sc, settings, index) && IsDoji(sc, settings, index-1) && IsDoji(sc, settings, index-2) && (InData[SC_OPEN][index-1] > InData[SC_LAST][index]) && (InData[SC_OPEN][index-1] > InData[SC_LAST][index-2]) ) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const int k_BullishTriStar_PAST_INDEX = 3; bool IsBullishTriStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH TRI STAR //1. Market is characterized by downtrend. //2. Then we see three consecutive Doji. //3. The second day Doji gaps below the first and third. SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; // the candle 0 is Doji if((settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) && IsDoji(sc, settings, index) && IsDoji(sc, settings, index-1) && IsDoji(sc, settings, index-2) && (InData[SC_OPEN][index-1] < InData[SC_LAST][index]) && (InData[SC_OPEN][index-1] < InData[SC_LAST][index-2]) ) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ bool IsUniqueThreeRiverBottom(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // UNIQUE THREE RIVER BOTTOM // 1. Downtrend till the candle [index-2] // 2. The candle [index-2] is black and with a strong body // 3. The candle [index-1] forms HAMMER PATERN // 4. The minimum of the candle [index-1] is smaller than the minimum of the candles [index-2] and [index] // 5. The candle [index] has a weak body that lower than the body of the candle [index-1] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // Downtrend { if(InData[SC_LAST][index-2] InData[SC_HIGH][index-1]) // the body of the candle 0 is higher than the maximum of the candle -1 { // check for the wicks length if (UpperWickLength(InData, index)<=PercentOfCandleLength(InData, index-1, k_BearishDojiStar_UpperWickPercent) && // upper wick of Doji LowerWickLength(InData, index)<=PercentOfCandleLength(InData, index-1, k_BearishDojiStar_LowerWickPercent)) { ret_flag = true; } } } } } } return ret_flag; } /*==========================================================================*/ const double k_BullishDojiStar_LowerWickPercent = 25.0; const double k_BullishDojiStar_UpperWickPercent = 25.0; bool IsBullishDojiStar(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH DOJI STAR // 1. Downtrend // 2. Strong black body of the candle [index-1] // 3. The candle [index] is Doji // 4. The body of the candle [index] is lower than minimum of the candle [index-1] // 5. The wicks of the candle [index] are "not long" SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // check for the downtrend { if(IsBlackCandle(InData, index-1)) // the body of the candle -1 is black { if(IsBodyStrong(InData,index-1)) // the body of the candle -1 is strong { if (IsDoji(sc, settings, index)) // the candle 0 is Doji { if (InData[SC_LAST][index] < InData[SC_LOW][index-1]) // the body of the candle 0 is lower than minimum of the candle -1 { // check for the wicks length if (UpperWickLength(InData, index)<=PercentOfCandleLength(InData, index-1, k_BearishDojiStar_UpperWickPercent) && // upper wick of Doji LowerWickLength(InData, index)<=PercentOfCandleLength(InData, index-1, k_BearishDojiStar_LowerWickPercent)) // lower wick of Doji { ret_flag = true; } } } } } } return ret_flag; } /*==========================================================================*/ const double k_BearishDragonflyDoji_UpperWickPercent = 7.0; bool IsBearishDragonflyDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BEARISH DRAGONFLY DOJI // 1. Uptrend // 2. The candle [index] is Doji // 3. The candle [index] does not have an upper wick // 4. The lower wick of the candle [index] is very long SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // check for the uptrend { if (IsDoji(sc, settings, index)) // the candle 0 is Doji { if (IsUpperWickSmall(InData, index, k_BearishDragonflyDoji_UpperWickPercent)) //the candle 0 does not have an upper wick { // The candle 0 has a long lower wick // // Note: // if body is small and upper wick is small while the candle is // long => the lower wick is long if (IsCandleStrength(InData,index)) { ret_flag = true; } } } } return ret_flag; } /*==========================================================================*/ const double k_BullishDragonflyDoji_UpperWickPercent = 7.0; bool IsBullishDragonflyDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH DRAGONFLY DOJI // 1. Downtrend // 2. The candle [index] is Doji // 3. The candle [index] does not have an upper wick // 4. The lower wick of the candle [index] is very long SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // check for the downtrend { if (IsDoji(sc, settings, index)) // the candle 0 is Doji { if (IsUpperWickSmall(InData, index, k_BullishDragonflyDoji_UpperWickPercent)) //the candle 0 does not have an upper wick { // The candle 0 has a long lower wick // // Note: // if body is small and upper wick is small while the candle is // long => the lower wick is long if (IsCandleStrength(InData,index)) { ret_flag = true; } } } } return ret_flag; } /*==========================================================================*/ const double k_BearishGravestoneDoji_LowerWickPercent = 7.0; bool IsBearishGravestoneDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BEARISH GRAVESTONE DOJI // 1. Uptrend // 2. The candle [index-1] has a white body // 3. The candle [index] is Doji // 4. The lower wick of the candle [index] is insignificant // 5. Upper wick of the candle [index] is very long // 6. OPEN of the candle [index] is higher than the maximum of the candle [index-1] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // check for the uptrend { if(IsWhiteCandle(InData, index-1)) // the body of the candle -1 is white { if (IsDoji(sc, settings, index)) // the candle [index] is Doji { // lower wick of the candle 0 is insignificant if (IsLowerWickSmall(InData, index, k_BearishGravestoneDoji_LowerWickPercent)) { // upper wick of the candle 0 is long (please, note that it's Doji, so there is no body) if (IsCandleStrength(InData,index)) { // OPEN of the candle 0 is higher than the maximum of the candle -1 if(InData[SC_OPEN][index] > InData[SC_HIGH][index-1]) { ret_flag = true; } } } } } } return ret_flag; } /*==========================================================================*/ const double k_BullishGravestoneDoji_LowerWickPercent = 7; bool IsBullishGravestoneDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH GRAVESTONE DOJI // 1. Downtrend // 2. The candle [index-1] has a black body // 3. The candle [index] is Doji // 4. The candle [index] does not have a lower wick // 5. The upper wick of the candle [index] is very long // 6. Absence of the gap between the candles [index] and [index-1] is necessary SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // check for the downtrend { if(IsBlackCandle(InData, index-1)) // the body of the candle -1 is black { if (IsDoji(sc, settings,index)) // the candle 0 is Doji { // candle 0 does not have a lower wick if (IsLowerWickSmall(InData, index, k_BullishGravestoneDoji_LowerWickPercent)) { // candle 0 has a long upper wick // // Note: // if body is small and lower wick is small and the candle is // long => the lower wick is long // (please, note that it's Doji, so there is no body) if (IsCandleStrength(InData,index)) { // check for the absence of the gap if (InData[SC_LOW][index-1] InData[SC_HIGH][index-1]) { // the wicks of the candle 0 are nearly the same if (abs(LowerWickLength(InData, index) - UpperWickLength(InData, index))< PercentOfCandleLength(InData, index, k_BearishLongleggedDoji_SimularityPercent)) { ret_flag = true; } } } } } return ret_flag; } /*==========================================================================*/ const double k_BullishLongleggedDoji_SimularityPercent = 10.0; bool IsBullishLongleggedDoji(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH LONGLEGGED DOJI // 1. Downtrend // 2. The candle [index] is Doji // 3. The candle [index] is long // 4. The wicks of the candle [index] are nearly the same // 5. The body of the candle [index] is lower than the minimum of the candle [index-1] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // check for the downtrend { if (IsDoji(sc, settings, index)) // the candle 0 is Doji { // The candle 0 is long if (IsCandleStrength(InData,index)) { // the body of the candle 0 is lower than the minimum of the candle -1 if (max(InData[SC_LAST][index], InData[SC_OPEN][index]) < InData[SC_LOW][index-1]) { // the wicks of the candle 0 are nearly the same if (abs(LowerWickLength(InData, index) - UpperWickLength(InData, index))< PercentOfCandleLength(InData, index, k_BullishLongleggedDoji_SimularityPercent)) { ret_flag = true; } } } } } return ret_flag; } /*==========================================================================*/ //const int k_BearishSideBySideWhiteLines_TrendArea = 3; const int k_BearishSideBySideWhiteLines_PAST_INDEX = 3; const double k_BearishSideBySideWhiteLines_OpenSimularityPercent = 14.0; const double k_BearishSideBySideWhiteLines_CandleSimularityPercent = 14.0; bool IsBearishSideBySideWhiteLines(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BEARISH SIDE-BY-SIDE WHITE LINES // 1. Downtrend // 2. The candles [index], [index-1] are white // 3. The candle [index-2] is black // 4. The maximum of the candle [index-1] is lower than the minimum of the candle [index-2] // 5. Open prices and the sizes of the candles [index-1] and [index] are ALMOST the same /* 1. 1st day is a black day. 2. 2nd day is a white day which gaps below the 1st day's open. 3. 3rd day is a white day about the same size as the 2nd day, opening at about the same price.*/ SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // check for the downtrend { if (IsWhiteCandle(InData, index) && // the candle 0 is white IsWhiteCandle(InData, index-1) && // the candle -1 is white IsBlackCandle(InData, index-2)) // the candle -2 is black { // the candle -2 is higher than the candle -1 with a gap if (InData[SC_LOW][index-2] > InData[SC_HIGH][index-1]) { // compare of the OPENS of the candles 0 and -1 if (IsNearEqual(InData[SC_OPEN][index-1], InData[SC_OPEN][index], InData, index, k_BearishSideBySideWhiteLines_OpenSimularityPercent)) { // compare of the length of the candles 0 and -1 if (IsNearEqual(CandleLength(InData,index), CandleLength(InData, index-1), InData, index, k_BearishSideBySideWhiteLines_CandleSimularityPercent)) { ret_flag = true; } } } } } return ret_flag; } /*==========================================================================*/ //const int k_BullishSideBySideWhiteLines_TrendArea = 3; const int k_BullishSideBySideWhiteLines_PAST_INDEX = 3; const double k_BullishSideBySideWhiteLines_OpenSimularityPercent = 7.0; const double k_BullishSideBySideWhiteLines_CandleSimularityPercent = 7.0; bool IsBullishSideBySideWhiteLines(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH SIDE-BY-SIDE WHITE LINES // 1. Uptrend // 2. The candles [index], [index-1] and [index-2] are white // 3. Maximum of the candle [index-2] is lower than minimum of the candle [index-1] // 4. Open prices and the sizes of the candles [index-1] and [index] are ALMOST the same /* 1. Market is characterized by uptrend. 2. We see a white candlestick in the first day. 3. Then we see another white candlestick on the second day with an upward gap. 4. Finally, we see a white candlestick on the third day characterized by the same body length and whose closing price is equal to the close of the second day and a new high is established.*/ SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if( (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // check for the uptrend && IsWhiteCandle(InData, index) && IsWhiteCandle(InData, index-1) && IsWhiteCandle(InData, index-2) && (InData[SC_LOW][index-1] > InData[SC_HIGH][index-2]) && (IsNearEqual(InData[SC_LAST][index-1], InData[SC_LAST][index], InData, index, k_BullishSideBySideWhiteLines_OpenSimularityPercent)) && (IsNearEqual(InData[SC_OPEN][index-1], InData[SC_OPEN][index], InData, index, k_BullishSideBySideWhiteLines_OpenSimularityPercent)) && (InData[SC_HIGH][index] > InData[SC_HIGH][index-1]) ) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const int k_FallingThreeMethods_PAST_INDEX = 3; const double k_FallingThreeMethods_CandleCloseClosenessPercent = 30.0; bool IsFallingThreeMethods(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // FALLING THREE METHODS SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; // 1. Market is characterized by downtrend. // 2. We see a long black candlestick in the first day. // 3. We then see three small real bodies defining a brief uptrend on the second, third, and fourth days. However these bodies stay within the range of the first day. // 4. Finally we see a long black candlestick on the fifth day opening near the previous day’s close and also closing below the close of the initial day to define a new low. if( (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) && IsBodyStrong(InData,index-4) && IsBlackCandle(InData, index-4) //&& IsWhiteCandle(InData, index-1) //&& IsWhiteCandle(InData, index-2) //&& IsWhiteCandle(InData, index-3) && !IsBodyStrong(InData,index-1) && !IsBodyStrong(InData,index-2) && !IsBodyStrong(InData,index-3) && (InData[SC_OHLC_AVG][index-3] < InData[SC_OHLC_AVG][index-2]) && (InData[SC_OHLC_AVG][index-2] < InData[SC_OHLC_AVG][index-1]) && (InData[SC_HIGH][index-3] < InData[SC_HIGH][index-4]) && (InData[SC_HIGH][index-2] < InData[SC_HIGH][index-4]) && (InData[SC_HIGH][index-1] < InData[SC_HIGH][index-4]) && (InData[SC_LOW][index-3] > InData[SC_LOW][index-4]) && (InData[SC_LOW][index-2] > InData[SC_LOW][index-4]) && (InData[SC_LOW][index-1] > InData[SC_LOW][index-4]) && IsBodyStrong(InData,index) && IsBlackCandle(InData, index) && (IsNearEqual(InData[SC_OPEN][index], InData[SC_LAST][index-1], InData, index, k_FallingThreeMethods_CandleCloseClosenessPercent)) && (InData[SC_LAST][index] < InData[SC_LAST][index-4]) ) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const int k_RisingThreeMethods_PAST_INDEX = 3; bool IsRisingThreeMethods(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // RISING THREE METHODS // . Market is characterized by downtrend. // 1. 1st day is a long white day. // 2. Three small body candlesticks follow the 1st day. Each trends downward and closes within the range of the 1st day. // 3. The last day is a long white day and closes above the 1st day's close. SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if( (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) && IsBodyStrong(InData,index-4) && IsWhiteCandle(InData, index-4) && !IsBodyStrong(InData,index-1) && !IsBodyStrong(InData,index-2) && !IsBodyStrong(InData,index-3) && (InData[SC_OHLC_AVG][index-3] > InData[SC_OHLC_AVG][index-2]) && (InData[SC_OHLC_AVG][index-2] > InData[SC_OHLC_AVG][index-1]) && (InData[SC_HIGH][index-3] <= InData[SC_HIGH][index-4]) && (InData[SC_HIGH][index-2] <= InData[SC_HIGH][index-4]) && (InData[SC_HIGH][index-1] <= InData[SC_HIGH][index-4]) && (InData[SC_LOW][index-3] >= InData[SC_LOW][index-4]) && (InData[SC_LOW][index-2] >= InData[SC_LOW][index-4]) && (InData[SC_LOW][index-1] >= InData[SC_LOW][index-4]) && IsBodyStrong(InData,index) && IsWhiteCandle(InData, index) && (InData[SC_LAST][index] > InData[SC_LAST][index-4]) ) { ret_flag = true; } return ret_flag; } /*==========================================================================*/ const double k_BearishSeparatingLines_SimularityPercent = 5.0; bool IsBearishSeparatingLines(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BEARISH SEPARATING LINE // 1. Downtrend // 2. The candles [index] and [index-1] are of contrast colors and their open prices are equal SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if( settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // downtrend { // OPENs are equal if(IsNearEqual(InData[SC_OPEN][index], InData[SC_OPEN][index-1], InData, index, k_BearishSeparatingLines_SimularityPercent)) { // check for the colors contrast bool colorIndex0 = IsWhiteCandle(InData, index); bool colorIndex1 = IsWhiteCandle(InData, index-1); ret_flag = (colorIndex1!=colorIndex0); } } return ret_flag; } /*==========================================================================*/ const double k_BullishSeparatingLines_SimularityPercent = 5.0; bool IsBullishSeparatingLines(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH SEPARATING LINE // 1. Uptrend // 2. The candles [index] and [index-1] are of contrast colors and their open prices are equal SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // uptrend { // OPENs are equal if(IsNearEqual(InData[SC_OPEN][index], InData[SC_OPEN][index-1], InData, index, k_BullishSeparatingLines_SimularityPercent)) { // check for the colors contrast // check for the colors contrast bool colorIndex0 = IsWhiteCandle(InData, index); bool colorIndex1 = IsWhiteCandle(InData, index-1); ret_flag = (colorIndex1!=colorIndex0); } } return ret_flag; } /*==========================================================================*/ bool IsDownsideTasukiGap(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // DOWNSIDE TASUKI GAP // 1. Downtrend // 2. The candle [index] is white and its open price is inside the body of the candle [index-1] // 3. The candles [index-1] and [index-2] are black with strong bodies // 4. There is a gap between the candles [index-1] and [index-2] // 5. CLOSE of the candle [index] is in the gap between the candles [index-1] and [index-2] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // downtrend { if(IsWhiteCandle(InData, index) && // the candle 0 is white IsBlackCandle(InData, index-1) && // the candle -1 is black IsBlackCandle(InData, index-2)) // the candle -2 is black { if(IsBodyStrong(InData, index-1)) // the body of the candle -1 is strong { if(IsBodyStrong(InData, index-2)) // the body of the candle -2 is strong { if (InData[SC_LOW][index-2] > InData[SC_HIGH][index-1]) // a gap between the candles -1 and -2 { // OPEN of the candle 0 is inside the body of the candle -1 if ((InData[SC_OPEN][index] > InData[SC_LAST][index-1]) && (InData[SC_OPEN][index] < InData[SC_OPEN][index-1])) { // CLOSE of the candle 0 is higher than maximum of the candle -1 and lower than the minimum of the candle -2 if ((InData[SC_LAST][index]>InData[SC_HIGH][index-1]) && (InData[SC_LAST][index] InData[SC_OPEN][index-1]) && (InData[SC_OPEN][index] < InData[SC_LAST][index-1])) { // CLOSE of the candle 0 is lower than minimum of the candle -1 and higher than the maximum of the candle -2 if ((InData[SC_LAST][index]>InData[SC_HIGH][index-2]) && (InData[SC_LAST][index]InData[SC_OPEN][index-3]) { ret_flag = true; } } } } } } } return ret_flag; } /*==========================================================================*/ bool IsBullishThreeLineStrike(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // BULLISH THREE LINE STRIKE // 1. Uptrend // 2. The candle [index] is black with a strong body // 3. The candles [index-1], [index-2] and [index-3] are white with strong bodies // 4. OPEN of the candle [index] is higher than CLOSE of the candle [index-1] // 5. CLOSE of the candle [index] is lower than OPEN of the candle [index-3] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // uptrend { if (IsBlackCandle(InData, index) && // the candle 0 is black IsWhiteCandle(InData, index-1) && // the candle -1 is white IsWhiteCandle(InData, index-2) && // the candle -2 is white IsWhiteCandle(InData, index-3)) // the candle -3 is white { if(IsBodyStrong(InData, index-1)) // the body of the candle -1 is strong { if(IsBodyStrong(InData, index-2)) // the body of the candle -2 is strong { if(IsBodyStrong(InData, index-3)) // the body of the candle -3 is strong { // OPEN of the candle 0 is higher than CLOSE of the candle -1 if(InData[SC_OPEN][index] > InData[SC_LAST][index-1]) { // CLOSE of the candle 0 is lower than OPEN of the candle -3 if(InData[SC_LAST][index] InData[SC_HIGH][index-1]) // a gap between the candles -1 and -2 { // OPEN of the candle 0 is inside the body of the candle -1 if ((InData[SC_OPEN][index] > InData[SC_LAST][index-1]) && (InData[SC_OPEN][index] < InData[SC_OPEN][index-1])) { // CLOSE of the candle 0 is higher than minimum of the candle -2 if(InData[SC_LAST][index]>InData[SC_LOW][index-2]) { ret_flag = true; } } } } } } } return ret_flag; } /*==========================================================================*/ bool IsUpsideGapThreeMethods(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // UPSIDE GAP THREE METHODS // 1. Uptrend // 2. The candle [index] is black and its OPEN is inside the body of the candle [index-1] // 3. The candles [index-1] and [index-2] are white with a strong bodies // 4. There is a gap between the candles [index-1] and [index-2] // 5. The body of the candle [index] closes the gap between the candles [index-1] and [index-2] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if( settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) // uptrend { if (IsBlackCandle(InData, index) && // the candle 0 is black IsWhiteCandle(InData, index-1) && // the candle -1 is white IsWhiteCandle(InData, index-2)) // the candle -2 is white { if(IsBodyStrong(InData, index-1)) // the body of the candle -1 is strong { if(IsBodyStrong(InData, index-2)) // the body of the candle -1 is strong { if (InData[SC_HIGH][index-2] < InData[SC_LOW][index-1]) // a gap between the candles -1 and -2 { // OPEN of the candle 0 is inside the body of the candle -1 if ((InData[SC_OPEN][index] > InData[SC_OPEN][index-1]) && (InData[SC_OPEN][index] < InData[SC_LAST][index-1])) { // CLOSE of the candle 0 is lower than maximum of the candle -2 if(InData[SC_LAST][index] InData[SC_OPEN][index]) && (InData[SC_LAST][index] >= InData[SC_LAST][index-1])) { // CLOSE of the candle 0 is equal the CLOSE of the candle -1 if(IsNearEqual(InData[SC_LAST][index], InData[SC_LAST][index-1], InData, index, k_InNeck_SimularityPercent)) { ret_flag = true; } // CLOSE of the candle 0 is a little bit higher or equal the CLOSE of the candle -1 else if((InData[SC_LAST][index]-InData[SC_LAST][index-1])< PercentOfCandleLength(InData, index, k_InNeck_SimularityPercent)) { ret_flag = true; } } } } } } return ret_flag; } /*==========================================================================*/ const double BearishThrusting_SignificantlyLowerPercent = 10.0; bool IsBearishThrusting(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // Bearish Thrusting // 1. Downtrend // 2. Candle [index-1] is black // 3. Candle [index] is white // 4. OPEN of the candle [index] SIGNIFICANTLY lower the minimum of the candle [index-1] // 5. CLOSE of the candle [index] is higher than the CLOSE of candle [index-1], but lower than the middle of body of candle [index-1] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if(settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_DOWN) // downtrend { if(IsBlackCandle(InData, index-1)) // candle -1 is black { if(IsWhiteCandle(InData, index)) // candle 0 is white { // OPEN of candle 0 is SIGNIFICANTLY lower than the minimum of candle -1 if ((InData[SC_LOW][index-1] > InData[SC_OPEN][index]) && (InData[SC_LOW][index-1]-InData[SC_OPEN][index])> PercentOfCandleLength(InData, index, BearishThrusting_SignificantlyLowerPercent)) { // CLOSE of candle 0 is higher than the CLOSE of -1, but lower than the middle of body of the candle -1 if ((InData[SC_LAST][index] > InData[SC_LAST][index-1]) && (InData[SC_LAST][index] < (InData[SC_LAST][index-1]+(InData[SC_OPEN][index-1]-InData[SC_LAST][index-1])/2))) { ret_flag = true; } } } } } return ret_flag; } /*==========================================================================*/ const int k_MatHold_PAST_INDEX = 3; bool IsMatHold(SCStudyInterfaceRef sc, const s_CandleStickPatternsFinderSettings& settings, int index) { // MAT HOLD // 1. Candle [index] is white with strong body // 2. OPEN of th candle [index] is higher than CLOSE of candle [index-1] // 3. Candles [index-1] and [index-2] has weak bodies // 4. CLOSE of candle [index-2] is higher than the CLOSE of candle [index-1] // 5. Candle [index-X] has strong white body (where X is from 3 to PAST_INDEX+1) // 6. CLOSE of candle [index] is higher than CLOSE of candle [index-X] // 7. Uptrend till candle [index-X] // 8. Candles [index-Y] has weak bodies (where Y is from 1 to X-1) // 9. CLOSE of candle [index-Y] is higher than CLOSE of [index-Y-1] (where Y is from 1 to X-1) // 10. Minimum of candle [index-Y+1] is higher than maximum of candle [index-Y] SCBaseDataRef InData = sc.BaseData; bool ret_flag = false; if (IsWhiteCandle(InData, index) && // candle 0 is white (InData[SC_OPEN][index] > InData[SC_LAST][index-1])) // OPEN of candle 0 is higher than CLOSE of -1 { if (IsBodyStrong(InData,index)) // body of the candle 0 is strong { if (InData[SC_LAST][index-2] > InData[SC_LAST][index-1]) // CLOSE of candle -2 is higher than CLOSE of candle -1 { // bodies of candles -1 and -2 are weak if ((!IsBodyStrong(InData,index-1)) && (!IsBodyStrong(InData,index-2))) { int X = 0; // searching for a strong white body for (int i =3;i<(k_MatHold_PAST_INDEX+2);i++) { if (IsBodyStrong(InData,index-i) && IsWhiteCandle(InData, index-i)) { // CLOSE of candle 0 is higher than CLOSE of candle -X if(InData[SC_LAST][index] > InData[SC_LAST][index-i]) { // found candle -X X = i; } break; } } if (X!=0) { // uptrend till candle -Õ if (settings.UseTrendDetection == false || sc.Subgraph[TREND_FOR_PATTERNS][index] == CANDLESTICK_TREND_UP) { // Minimum of candle [index-Y+1] is higher than maximum of candle [index-Y]; candle [index-Y+1] is black if((InData[SC_LOW][index-X+1] > InData[SC_HIGH][index-X]) && IsBlackCandle(InData, index-X+1)) { ret_flag = true; // checking the candles between two white candles if ((IsBodyStrong(InData,index-1)) || // check if body is strong (InData[SC_HIGH][index-1] > InData[SC_HIGH][index-X]) || // check if maximum is higher than maximum of candle -Õ (InData[SC_LOW][index-1] < InData[SC_LOW][index-X])) // check if minimum is lower than minimum of candle -Õ { ret_flag = false; } else { for (int i = 2;i Input_HighestCCILevelforLong.GetFloat()) continue; if(CCI[index] < 0) continue; if(SidewinderColors[index] == SW_TREND_FLAT) continue; if(HooksConditions[index] <= 0) continue; // check Chopzone SCFloatArrayRef ChopzoneAVG = Subgraph_ChopzoneAverage; sc.WeightedMovingAverage(ChopzoneOutput,ChopzoneAVG,index,Input_ChopzoneLength.GetInt()); float ChopzoneAVGval = ChopzoneAVG[index]; if (ChopzoneAVG[index] >= Input_ChopzoneThreshhold.GetFloat()) { ZLRLongTrade = true; } if(!ZLRLongTrade) continue; } else if(CCITrendColor[index] == CCI_TREND_DOWN_COLOR) // trend is DOWN { if(CCIDiff > Input_HighestCCIDifferenceforShort.GetFloat()) continue; if(CCI[index] < Input_LowestCCILevelforShort.GetFloat()) continue; if(CCI[index] >= 0) continue; if(SidewinderColors[index] == SW_TREND_FLAT) continue; if(HooksConditions[index] >= 0) continue; // check Chopzone SCFloatArrayRef ChopzoneAVG = Subgraph_ChopzoneAverage; sc.WeightedMovingAverage(ChopzoneOutput,ChopzoneAVG,index,Input_ChopzoneLength.GetInt()); if (ChopzoneAVG[index] <= -1 * Input_ChopzoneThreshhold.GetFloat()) { ZLRShortTrade = true; } if(!ZLRShortTrade) continue; } else continue; // put values to arrays s_UseTool Tool; Tool.Clear(); // reset tool structure for our next use Tool.ChartNumber = sc.ChartNumber; Tool.DrawingType = DRAWING_TEXT; Tool.Region = sc.GraphRegion; Tool.DrawingType = DRAWING_TEXT; Tool.ReverseTextColor = 0; Tool.Text = "ZLR"; Tool.BeginDateTime = sc.BaseDateTimeIn[index]; Tool.LineNumber = UniqueID; Tool.FontSize = 8; Tool.AddMethod = UTAM_ADD_ALWAYS; if(sc.GetBarHasClosedStatus(index)==BHCS_BAR_HAS_NOT_CLOSED) { Tool.LineNumber = LastBarUniqueID; } if(ZLRLongTrade) { Subgraph_LongTrade[index] = -200; Tool.BeginValue = -200; Tool.Color = Subgraph_LongTrade.PrimaryColor; Tool.TextAlignment = DT_CENTER | DT_BOTTOM; sc.UseTool(Tool); if (Input_AlertNumber.GetAlertSoundNumber() > 0) sc.SetAlert(Input_AlertNumber.GetAlertSoundNumber() - 1, "Long Trade" ); } if(ZLRShortTrade) { Subgraph_ShortTrade[index] = 200; Tool.BeginValue = 200; Tool.Color = Subgraph_ShortTrade.PrimaryColor; Tool.TextAlignment = DT_CENTER | DT_TOP; sc.UseTool(Tool); if (Input_AlertNumber.GetAlertSoundNumber() > 0) sc.SetAlert(Input_AlertNumber.GetAlertSoundNumber() - 1, "Short Trade"); } } } /*==========================================================================*/ SCSFExport scsf_ChopZone(SCStudyInterfaceRef sc) { SCSubgraphRef Subgraph_Czi1 = sc.Subgraph[0]; SCSubgraphRef Subgraph_Czi2 = sc.Subgraph[1]; SCSubgraphRef Subgraph_OutWorksheets = sc.Subgraph[2]; SCSubgraphRef Subgraph_Ema = sc.Subgraph[3]; SCSubgraphRef Subgraph_ColorControl3 = sc.Subgraph[4]; SCSubgraphRef Subgraph_ColorControl4 = sc.Subgraph[5]; SCInputRef Input_InputData = sc.Input[0]; SCInputRef Input_PosCzi1 = sc.Input[2]; SCInputRef Input_PosCzi2 = sc.Input[3]; SCInputRef Input_EmaLength = sc.Input[5]; SCInputRef Input_TickValue = sc.Input[6]; if(sc.SetDefaults) { sc.GraphName = "Chop Zone"; sc.StudyDescription = "Chop Zone"; sc.AutoLoop = 1; Subgraph_Czi1.Name = "CZI Top"; Subgraph_Czi1.DrawStyle = DRAWSTYLE_LINE; Subgraph_Czi1.LineWidth = 2; Subgraph_Czi1.PrimaryColor = RGB(255,255,0); Subgraph_Czi1.SecondaryColor = RGB(170,255,85); Subgraph_Czi1.SecondaryColorUsed = true; Subgraph_Czi1.DrawZeros = false; Subgraph_Czi2.Name = "CZI Bottom"; Subgraph_Czi2.DrawStyle = DRAWSTYLE_LINE; Subgraph_Czi2.LineWidth = 2; Subgraph_Czi2.PrimaryColor = RGB(85,255,170); Subgraph_Czi2.SecondaryColor = RGB(0,255,255); Subgraph_Czi2.SecondaryColorUsed = true; Subgraph_Czi2.DrawZeros = false; Subgraph_OutWorksheets.Name = "Output for Spreadsheets"; Subgraph_OutWorksheets.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_OutWorksheets.PrimaryColor = RGB(255,255,255); Subgraph_OutWorksheets.DrawZeros = false; Subgraph_ColorControl3.Name = "Down Colors 1 & 2"; Subgraph_ColorControl3.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_ColorControl3.PrimaryColor = RGB(213,170,0); Subgraph_ColorControl3.SecondaryColor = RGB(170,85,0); Subgraph_ColorControl3.SecondaryColorUsed = true; Subgraph_ColorControl3.DrawZeros = false; Subgraph_ColorControl4.Name = "Down Color 3"; Subgraph_ColorControl4.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_ColorControl4.PrimaryColor = RGB(128,0,0); Subgraph_ColorControl4.DrawZeros = false; Input_InputData.Name = "Input Data"; Input_InputData.SetInputDataIndex(SC_LAST); Input_PosCzi1.Name = "Y Pos CZI 1"; Input_PosCzi1.SetFloat(100.0f); Input_PosCzi2.Name = "Y Pos CZI 2"; Input_PosCzi2.SetFloat(-100.0f); Input_EmaLength.Name = "EMA Length"; Input_EmaLength.SetInt(34); Input_EmaLength.SetIntLimits(1,MAX_STUDY_LENGTH); Input_TickValue.Name = "Tick Value (Enter number to override default)"; Input_TickValue.SetFloat(0.0f); return; } if (Subgraph_Czi1.PrimaryColor == RGB(255,255,0) && Subgraph_Czi1.SecondaryColor == RGB(0,255,255)) { Subgraph_Czi1.PrimaryColor = RGB(255,255,0); Subgraph_Czi1.SecondaryColor = RGB(170,255,85); Subgraph_Czi2.PrimaryColor = RGB(85,255,170); Subgraph_Czi2.SecondaryColor = RGB(0,255,255); Subgraph_ColorControl3.PrimaryColor = RGB(213,170,0); Subgraph_ColorControl3.SecondaryColor = RGB(170,85,0); Subgraph_ColorControl4.PrimaryColor = RGB(128,0,0); } float inTickSize = sc.TickSize; if(Input_TickValue.GetFloat() != 0) inTickSize = Input_TickValue.GetFloat(); float &PriorTickSize = sc.GetPersistentFloat(1); if(PriorTickSize != inTickSize) { sc.UpdateStartIndex = 0; PriorTickSize = inTickSize; } // Colors COLORREF ColorLevel = Subgraph_Czi1.PrimaryColor; COLORREF ColorUp1 = Subgraph_Czi1.SecondaryColor; COLORREF ColorUp2 = Subgraph_Czi2.PrimaryColor; COLORREF ColorUp3 = Subgraph_Czi2.SecondaryColor; COLORREF ColorDown1 = Subgraph_ColorControl3.PrimaryColor; COLORREF ColorDown2 = Subgraph_ColorControl3.SecondaryColor; COLORREF ColorDown3 = Subgraph_ColorControl4.PrimaryColor; sc.DataStartIndex = Input_EmaLength.GetInt(); int pos = sc.Index; sc.ExponentialMovAvg(sc.BaseData[Input_InputData.GetInputDataIndex()], Subgraph_Ema, pos, Input_EmaLength.GetInt()); int TickDifference = sc.Round((sc.BaseData[Input_InputData.GetInputDataIndex()][pos] - Subgraph_Ema[pos])/inTickSize); Subgraph_Czi1[pos] = Input_PosCzi1.GetFloat(); Subgraph_Czi2[pos] = Input_PosCzi2.GetFloat(); /* cyan Woodies CZI >= 5 dark green Woodies CZI >= 4 And Woodies CZI < 5 light green Woodies CZI >= 3 And Woodies CZI < 4 lime Woodies CZI > 1 And Woodies CZI < 3 yellow -1 <= (Woodies CZI) <= 1 light orange Woodies CZI > -3 And Woodies CZI < -1 dark orange Woodies CZI > -4 And Woodies CZI <= -3 light red Woodies CZI > -5 And Woodies CZI <= -4 brown <=-5 */ if (TickDifference <= 1 && TickDifference >= -1) Subgraph_Czi1.DataColor[pos] = Subgraph_Czi2.DataColor[pos] = ColorLevel; else if (TickDifference > 1 && TickDifference < 3) Subgraph_Czi1.DataColor[pos] = Subgraph_Czi2.DataColor[pos] = ColorUp1; else if (TickDifference >= 3 && TickDifference < 4) Subgraph_Czi1.DataColor[pos] = Subgraph_Czi2.DataColor[pos] = ColorUp2; else if (TickDifference >= 4) Subgraph_Czi1.DataColor[pos] = Subgraph_Czi2.DataColor[pos] = ColorUp3; else if (TickDifference < -1 && TickDifference > -3) Subgraph_Czi1.DataColor[pos] = Subgraph_Czi2.DataColor[pos] = ColorDown1; else if (TickDifference <= -3 && TickDifference > -4) Subgraph_Czi1.DataColor[pos] = Subgraph_Czi2.DataColor[pos] = ColorDown2; else if (TickDifference <= -4) Subgraph_Czi1.DataColor[pos] = Subgraph_Czi2.DataColor[pos] = ColorDown3; // for worksheets Subgraph_OutWorksheets[pos] = (float)TickDifference; } /***********************************************************************/ SCSFExport scsf_StochBands(SCStudyInterfaceRef sc) { SCSubgraphRef Subgraph_SubgraphK = sc.Subgraph[0]; SCSubgraphRef Subgraph_SubgraphD = sc.Subgraph[1]; SCSubgraphRef Subgraph_SubgraphK2 = sc.Subgraph[2]; SCSubgraphRef Subgraph_SubgraphD2 = sc.Subgraph[3]; SCSubgraphRef Subgraph_SubgraphBackgroundCalcForStoch1 = sc.Subgraph[8]; SCSubgraphRef Subgraph_SubgraphBackgroundCalcForStoch2 = sc.Subgraph[9]; SCInputRef Input_InputDataType = sc.Input[0]; SCInputRef Input_InputMAType = sc.Input[1]; SCInputRef Input_InputLength = sc.Input[2]; SCInputRef Input_InputK = sc.Input[3]; SCInputRef Input_InputD = sc.Input[4]; SCInputRef Input_InputLength2 = sc.Input[5]; SCInputRef Input_InputK2 = sc.Input[6]; SCInputRef Input_InputD2 = sc.Input[7]; if (sc.SetDefaults) { sc.GraphName = "Stochastic Bands"; sc.StudyDescription = "Stochastic Bands"; sc.AutoLoop = 1; Subgraph_SubgraphK.Name = "K"; Subgraph_SubgraphK.DrawStyle = DRAWSTYLE_LINE; Subgraph_SubgraphK.LineWidth = 2; Subgraph_SubgraphK.PrimaryColor = RGB(0, 200, 0); Subgraph_SubgraphK.SecondaryColor = RGB(0, 200, 0); Subgraph_SubgraphK.SecondaryColorUsed = 1; Subgraph_SubgraphK.DrawZeros = true; Subgraph_SubgraphD.Name = "D"; Subgraph_SubgraphD.DrawStyle = DRAWSTYLE_LINE; Subgraph_SubgraphD.LineWidth = 2; Subgraph_SubgraphD.PrimaryColor = RGB(0, 200, 0); Subgraph_SubgraphD.SecondaryColor = RGB(0, 200, 0); Subgraph_SubgraphD.SecondaryColorUsed = 1; Subgraph_SubgraphD.DrawZeros = true; Subgraph_SubgraphK2.Name = "K2"; Subgraph_SubgraphK2.DrawStyle = DRAWSTYLE_LINE; Subgraph_SubgraphK2.LineWidth = 2; Subgraph_SubgraphK2.PrimaryColor = RGB(0, 200, 0); Subgraph_SubgraphK2.SecondaryColor = RGB(0, 200, 0); Subgraph_SubgraphK2.SecondaryColorUsed = 1; Subgraph_SubgraphK2.DrawZeros = true; Subgraph_SubgraphD2.Name = "D2"; Subgraph_SubgraphD2.DrawStyle = DRAWSTYLE_LINE; Subgraph_SubgraphD2.LineWidth = 2; Subgraph_SubgraphD2.PrimaryColor = RGB(0, 200, 0); Subgraph_SubgraphD2.SecondaryColor = RGB(0, 200, 0); Subgraph_SubgraphD2.SecondaryColorUsed = 1; Subgraph_SubgraphD2.DrawZeros = true; Input_InputDataType.Name = "Input Data"; Input_InputDataType.SetInputDataIndex(SC_HL_AVG); Input_InputMAType.Name = "Moving Average Type"; Input_InputMAType.SetMovAvgType(MOVAVGTYPE_SIMPLE); Input_InputLength.Name = "Length"; Input_InputLength.SetInt(7); Input_InputK.Name = "K"; Input_InputK.SetInt(3); Input_InputD.Name = "D"; Input_InputD.SetInt(3); Input_InputLength2.Name = "Length2"; Input_InputLength2.SetInt(21); Input_InputK2.Name = "K2"; Input_InputK2.SetInt(10); Input_InputD2.Name = "D2"; Input_InputD2.SetInt(4); sc.DataStartIndex = 50; return; } if (sc.Index < 1) return; int Length = Input_InputLength.GetInt(); int K = Input_InputK.GetInt(); int D = Input_InputD.GetInt(); int Length2 = Input_InputLength2.GetInt(); int K2 = Input_InputK2.GetInt(); int D2 = Input_InputD2.GetInt(); int DataIndex = Input_InputDataType.GetInputDataIndex(); int MAType = Input_InputMAType.GetMovAvgType(); // First Stochastic sc.Stochastic(sc.BaseDataIn[DataIndex], sc.BaseDataIn[DataIndex], sc.BaseDataIn[DataIndex], Subgraph_SubgraphBackgroundCalcForStoch1, sc.Index, Length, K, D, MAType); float sk = Subgraph_SubgraphBackgroundCalcForStoch1.Arrays[0][sc.Index]; float sd = Subgraph_SubgraphBackgroundCalcForStoch1.Arrays[1][sc.Index]; // Second Stochastic sc.Stochastic(sc.BaseDataIn[DataIndex], sc.BaseDataIn[DataIndex], sc.BaseDataIn[DataIndex], Subgraph_SubgraphBackgroundCalcForStoch2, sc.Index, Length2, K2, D2, MAType); float sk2 = Subgraph_SubgraphBackgroundCalcForStoch2.Arrays[0][sc.Index]; float sd2 = Subgraph_SubgraphBackgroundCalcForStoch2.Arrays[1][sc.Index]; Subgraph_SubgraphK[sc.Index] = sk; Subgraph_SubgraphD[sc.Index] = sd; if (sk > sd) { Subgraph_SubgraphK.DataColor[sc.Index] = Subgraph_SubgraphK.PrimaryColor; Subgraph_SubgraphD.DataColor[sc.Index] = Subgraph_SubgraphD.PrimaryColor; } else { Subgraph_SubgraphK.DataColor[sc.Index] = Subgraph_SubgraphK.SecondaryColor; Subgraph_SubgraphD.DataColor[sc.Index] = Subgraph_SubgraphD.SecondaryColor; } Subgraph_SubgraphK2[sc.Index] = sk2; Subgraph_SubgraphD2[sc.Index] = sd2; if (sk2 > sd2) { Subgraph_SubgraphK2.DataColor[sc.Index] = Subgraph_SubgraphK2.PrimaryColor; Subgraph_SubgraphD2.DataColor[sc.Index] = Subgraph_SubgraphD2.PrimaryColor; } else { Subgraph_SubgraphK2.DataColor[sc.Index] = Subgraph_SubgraphK2.SecondaryColor; Subgraph_SubgraphD2.DataColor[sc.Index] = Subgraph_SubgraphD2.SecondaryColor; } } /***********************************************************************/ SCSFExport scsf_BLine(SCStudyInterfaceRef sc) { SCSubgraphRef Subgraph_Baseline = sc.Subgraph[0]; SCSubgraphRef Subgraph_Oversold = sc.Subgraph[1]; SCSubgraphRef Subgraph_Overbought = sc.Subgraph[2]; SCSubgraphRef Subgraph_BackgroundCalcForStoch = sc.Subgraph[5]; SCInputRef Input_MATypeSimple = sc.Input[0]; SCInputRef Input_Length = sc.Input[1]; SCInputRef Input_K = sc.Input[2]; SCInputRef Input_D = sc.Input[3]; SCInputRef Input_UseHL = sc.Input[4]; if (sc.SetDefaults) { sc.GraphName = "Buffys B-Line"; sc.StudyDescription = "Buffys B-Line"; sc.AutoLoop = 1; Subgraph_Baseline.Name = "Baseline"; Subgraph_Baseline.DrawStyle=DRAWSTYLE_LINE; Subgraph_Baseline.PrimaryColor=RGB(255,255,255); Subgraph_Oversold.Name = "Oversold"; Subgraph_Oversold.DrawStyle=DRAWSTYLE_POINT; Subgraph_Oversold.PrimaryColor=RGB(0,255,0); Subgraph_Overbought.Name = "Overbought"; Subgraph_Overbought.DrawStyle=DRAWSTYLE_POINT; Subgraph_Overbought.PrimaryColor=RGB(255,0,0); Input_MATypeSimple.Name = "MA Type: Use Simple instead of Ensign Exponential"; Input_MATypeSimple.SetYesNo(false); Input_Length.Name = "Length"; Input_Length.SetInt(21); Input_K.Name = "K"; Input_K.SetInt(10); Input_D.Name = "D"; Input_D.SetInt(4); Input_UseHL.Name = "Use HL Average Instead of Close"; Input_UseHL.SetYesNo(false); sc.DataStartIndex = 50; return; } int Length = Input_Length.GetInt(); int K = Input_K.GetInt(); int D = Input_D.GetInt(); int DataIndex = SC_LAST; if (Input_UseHL.GetBoolean()) DataIndex = SC_HL_AVG; sc.Stochastic(sc.BaseDataIn[DataIndex], sc.BaseDataIn[DataIndex], sc.BaseDataIn[DataIndex],Subgraph_BackgroundCalcForStoch, sc.Index, Length, K, D, MOVAVGTYPE_SIMPLE); float FastK = Subgraph_BackgroundCalcForStoch[sc.Index]; int skArrayIndex, sdArrayIndex; if (Input_MATypeSimple.GetBoolean()) { skArrayIndex = 0; sdArrayIndex = 1; } else { skArrayIndex = 2; sdArrayIndex = 3; } float PriorStochasticK, PriorStochasticD; if (sc.Index) { PriorStochasticK = Subgraph_BackgroundCalcForStoch.Arrays[skArrayIndex][sc.Index-1]; PriorStochasticD = Subgraph_BackgroundCalcForStoch.Arrays[sdArrayIndex][sc.Index-1]; } else PriorStochasticK = PriorStochasticD = sc.BaseDataIn[DataIndex][0]; if (Input_MATypeSimple.GetBoolean() == false) { // Calculate Ensign Exponential Moving Average float temp = Subgraph_BackgroundCalcForStoch.Arrays[2][sc.Index] = (FastK-PriorStochasticK)/K + PriorStochasticK; Subgraph_BackgroundCalcForStoch.Arrays[3][sc.Index] = (temp-PriorStochasticD)/D + PriorStochasticD; } float sk = Subgraph_BackgroundCalcForStoch.Arrays[skArrayIndex][sc.Index]; float sd = Subgraph_BackgroundCalcForStoch.Arrays[sdArrayIndex][sc.Index]; Subgraph_Baseline[sc.Index] = sk; if(sk>=80) Subgraph_Oversold[sc.Index] = sk; else if (sk <= 20) Subgraph_Overbought[sc.Index] = sk; } /***********************************************************************/ SCSFExport scsf_BuffyMALines(SCStudyInterfaceRef sc) { SCSubgraphRef Subgraph_SMA1 = sc.Subgraph[0]; SCSubgraphRef Subgraph_SMA2 = sc.Subgraph[1]; SCSubgraphRef Subgraph_WMA1 = sc.Subgraph[2]; SCSubgraphRef Subgraph_WMA2 = sc.Subgraph[3]; SCSubgraphRef Subgraph_BackgroundCalcForWMA1 = sc.Subgraph[6]; SCSubgraphRef Subgraph_BackgroundCalcForWMA2 = sc.Subgraph[7]; SCSubgraphRef Subgraph_BackgroundCalcForSMA1 = sc.Subgraph[8]; SCSubgraphRef Subgraph_BackgroundCalcForSMA2 = sc.Subgraph[9]; SCInputRef Input_SMA1DataInput = sc.Input[0]; SCInputRef Input_SMA1Length = sc.Input[1]; SCInputRef Input_SMA2DataInput = sc.Input[2]; SCInputRef Input_SMA2Length = sc.Input[3]; SCInputRef Input_WMA1DataInput = sc.Input[4]; SCInputRef Input_WMA1Length = sc.Input[5]; SCInputRef Input_WMA2DataInput = sc.Input[6]; SCInputRef Input_WMA2Length = sc.Input[7]; if (sc.SetDefaults) { sc.GraphName = "Buffy's MA Lines"; sc.StudyDescription = "Buffy's MA Lines"; sc.AutoLoop = 1; Subgraph_SMA1.Name = "SMA1Dn"; Subgraph_SMA1.DrawStyle = DRAWSTYLE_STAIR_STEP; Subgraph_SMA1.LineWidth = 5; Subgraph_SMA1.PrimaryColor = RGB(0, 0, 255); Subgraph_SMA1.DrawZeros = false; Subgraph_SMA2.Name = "SMA2Up"; Subgraph_SMA2.DrawStyle = DRAWSTYLE_STAIR_STEP; Subgraph_SMA2.LineWidth = 5; Subgraph_SMA2.PrimaryColor = RGB(255, 255, 0); Subgraph_SMA2.DrawZeros = false; Subgraph_WMA1.Name = "WMA1Up"; Subgraph_WMA1.DrawStyle = DRAWSTYLE_STAIR_STEP; Subgraph_WMA1.LineWidth = 2; Subgraph_WMA1.PrimaryColor = RGB(0, 0, 0); Subgraph_WMA1.DrawZeros = false; Subgraph_WMA2.Name = "WMA2Dn"; Subgraph_WMA2.DrawStyle = DRAWSTYLE_STAIR_STEP; Subgraph_WMA2.LineWidth = 2; Subgraph_WMA2.PrimaryColor = RGB(0, 0, 0); Subgraph_WMA2.DrawZeros = false; Input_SMA1DataInput.Name = "SMA1 Input Data"; Input_SMA1DataInput.SetInputDataIndex(SC_HIGH); Input_SMA1Length.Name = "SMA1 Length"; Input_SMA1Length.SetInt(12); Input_SMA1Length.SetIntLimits(1, MAX_STUDY_LENGTH); Input_SMA2DataInput.Name = "SMA2 Input Data"; Input_SMA2DataInput.SetInputDataIndex(SC_LOW); Input_SMA2Length.Name = "SMA2 Length"; Input_SMA2Length.SetInt(12); Input_SMA2Length.SetIntLimits(1, MAX_STUDY_LENGTH); Input_WMA1DataInput.Name = "WMA1 Input Data"; Input_WMA1DataInput.SetInputDataIndex(SC_HIGH); Input_WMA1Length.Name = "WMA1 (Rounded To Tick): Length"; Input_WMA1Length.SetInt(6); Input_WMA1Length.SetIntLimits(1, MAX_STUDY_LENGTH); Input_WMA2DataInput.Name = "WMA2 Input Data"; Input_WMA2DataInput.SetInputDataIndex(SC_LOW); Input_WMA2Length.Name = "WMA2 (Rounded To Tick): Length"; Input_WMA2Length.SetInt(6); Input_WMA2Length.SetIntLimits(1, MAX_STUDY_LENGTH); sc.DataStartIndex = 10; return; } sc.SimpleMovAvg(sc.BaseDataIn[Input_SMA1DataInput.GetInputDataIndex()], Subgraph_BackgroundCalcForSMA1, sc.Index, Input_SMA1Length.GetInt()); sc.SimpleMovAvg(sc.BaseDataIn[Input_SMA2DataInput.GetInputDataIndex()], Subgraph_BackgroundCalcForSMA2, sc.Index, Input_SMA2Length.GetInt()); sc.WeightedMovingAverage(sc.BaseDataIn[Input_WMA1DataInput.GetInputDataIndex()], Subgraph_BackgroundCalcForWMA1, sc.Index, Input_WMA1Length.GetInt()); sc.WeightedMovingAverage(sc.BaseDataIn[Input_WMA2DataInput.GetInputDataIndex()], Subgraph_BackgroundCalcForWMA2, sc.Index, Input_WMA2Length.GetInt()); if (sc.Index < 10) return; // nothing else to do // If Falling, Show High SMA if (Subgraph_BackgroundCalcForSMA1[sc.Index-1] >= Subgraph_BackgroundCalcForSMA1[sc.Index]) Subgraph_SMA1[sc.Index] = Subgraph_BackgroundCalcForSMA1[sc.Index]; // If Rising, Show Low SMA if (Subgraph_BackgroundCalcForSMA2[sc.Index-1] <= Subgraph_BackgroundCalcForSMA2[sc.Index]) Subgraph_SMA2[sc.Index] = Subgraph_BackgroundCalcForSMA2[sc.Index]; // If Falling, Show High WMA if (Subgraph_BackgroundCalcForWMA1[sc.Index-1] >= Subgraph_BackgroundCalcForWMA1[sc.Index]) Subgraph_WMA1[sc.Index] = (float)sc.RoundToTickSize(Subgraph_BackgroundCalcForWMA1[sc.Index], sc.TickSize); // If Rising, Show Low WMA if (Subgraph_BackgroundCalcForWMA2[sc.Index-1] <= Subgraph_BackgroundCalcForWMA2[sc.Index]) Subgraph_WMA2[sc.Index] = (float)sc.RoundToTickSize(Subgraph_BackgroundCalcForWMA2[sc.Index], sc.TickSize); } /***************************************************************/ SCSFExport scsf_AutomaticTrendlines(SCStudyInterfaceRef sc) { SCSubgraphRef Subgraph_UpTrendline = sc.Subgraph[0]; SCSubgraphRef Subgraph_DownTrendline = sc.Subgraph[1]; SCInputRef Input_LengthInput = sc.Input[0]; SCInputRef Input_SkipLastBars = sc.Input[1]; SCInputRef Input_ShowTrendlineUp = sc.Input[3]; SCInputRef Input_ShowTrendlineDown = sc.Input[4]; SCInputRef Input_NewBarsBeforeAdjust = sc.Input[5]; SCInputRef Input_ForwardProjectAutoTrendLines = sc.Input[6]; SCInputRef Input_VersionUpdate = sc.Input[7]; SCInputRef Input_InputDataHigh = sc.Input[8]; SCInputRef Input_InputDataLow = sc.Input[9]; if (sc.SetDefaults) { sc.GraphName = "Automatic Trendlines"; sc.GraphRegion = 0; sc.AutoLoop = 0; sc.ValueFormat = VALUEFORMAT_INHERITED; // initialize subgraphs Subgraph_UpTrendline.Name = "Up Trendline"; Subgraph_UpTrendline.PrimaryColor = RGB(0, 128, 255); Subgraph_UpTrendline.LineWidth = 2; Subgraph_UpTrendline.DrawZeros = false; Subgraph_DownTrendline.Name = "Down Trendline"; Subgraph_DownTrendline.PrimaryColor = RGB(0, 128, 255); Subgraph_DownTrendline.LineWidth = 2; Subgraph_DownTrendline.DrawZeros = false; // Number of bars to use when determining the trendline Input_LengthInput.Name = "Length"; Input_LengthInput.SetInt(50); Input_LengthInput.SetIntLimits(2,MAX_STUDY_LENGTH); // Number of bars back from the end to begin consideration for the trendline. This allows the user to have the most recent X bars ignored when determining the trendline Input_SkipLastBars.Name = "Skip Last N Bars"; Input_SkipLastBars.SetInt(0); Input_SkipLastBars.SetIntLimits(0,MAX_STUDY_LENGTH); Input_ShowTrendlineUp.Name = "Show Up Trendline"; Input_ShowTrendlineUp.SetYesNo(1); Input_ShowTrendlineDown.Name = "Show Down Trendline"; Input_ShowTrendlineDown.SetYesNo(1); Input_NewBarsBeforeAdjust.Name = "Number Of New Bars Before Auto-Adjustment"; Input_NewBarsBeforeAdjust.SetInt(5); Input_NewBarsBeforeAdjust.SetIntLimits(0,MAX_STUDY_LENGTH); Input_ForwardProjectAutoTrendLines.Name = "Forward Project Automatic Trendlines"; Input_ForwardProjectAutoTrendLines.SetYesNo(1); Input_InputDataHigh.Name = "Input Data High"; Input_InputDataHigh.SetInputDataIndex(SC_HIGH); Input_InputDataLow.Name = "Input Data Low"; Input_InputDataLow.SetInputDataIndex(SC_LOW); // version update Input_VersionUpdate.SetInt(2); return; } if (Input_VersionUpdate.GetInt() < 1) { Input_ForwardProjectAutoTrendLines.SetYesNo(1); Input_VersionUpdate.SetInt(1); } if (Input_VersionUpdate.GetInt() < 2) { Input_InputDataHigh.SetInputDataIndex(SC_HIGH); Input_InputDataLow.SetInputDataIndex(SC_LOW); } int& UpLineIndex1 = sc.GetPersistentInt(1); int& UpLineIndex2 = sc.GetPersistentInt(2); int& DownLineIndex1 = sc.GetPersistentInt(3); int& DownLineIndex2 = sc.GetPersistentInt(4); int& PrevIndex = sc.GetPersistentInt(5); float& UpLine_A = sc.GetPersistentFloat(1); float& UpLine_B = sc.GetPersistentFloat(2); float& DownLine_A = sc.GetPersistentFloat(3); float& DownLine_B = sc.GetPersistentFloat(4); int NumberOfExtendedElements = 0; if(Input_ForwardProjectAutoTrendLines.GetYesNo() != 0) { NumberOfExtendedElements = 10 ; Subgraph_UpTrendline.ExtendedArrayElementsToGraph = 10; Subgraph_DownTrendline.ExtendedArrayElementsToGraph = 10; } else { NumberOfExtendedElements = 0; Subgraph_UpTrendline.ExtendedArrayElementsToGraph = 0; Subgraph_DownTrendline.ExtendedArrayElementsToGraph = 0; } // set index from which study will look back int LastIndex = sc.ArraySize - 1; int LastExtendedIndex = LastIndex + NumberOfExtendedElements; int StartIndex = LastIndex - Input_SkipLastBars.GetInt(); SCFloatArrayRef Highs = sc.BaseData[Input_InputDataHigh.GetInputDataIndex()]; SCFloatArrayRef Lows = sc.BaseData[Input_InputDataLow.GetInputDataIndex()]; if(sc.UpdateStartIndex == 0) { // on initial calculation set PrevIndex to last index in array // StartIndex already set to correct value PrevIndex = sc.ArraySize-1; UpLineIndex1 = 0; UpLineIndex2 = 0; DownLineIndex1 = 0; DownLineIndex2 = 0; PrevIndex = -1; } else { // set initial value of variable or adjust on replay if(PrevIndex == -1 || PrevIndex > LastIndex) PrevIndex = LastIndex; // perform adjust only after specified number of new bars were added int BarIndexDifference = LastIndex - PrevIndex; // if we should readjust trendline on each bar's changing then // do not any additional check if(Input_NewBarsBeforeAdjust.GetInt() > 0) { // if NewBarsBeforeAdjust greater then 0 then // we should readjust trendline only when Nth bar will be closed // so if we should readjust at 3rd bar we should wait when 3rd bar will be closed and then readjust trendlines if ((BarIndexDifference < Input_NewBarsBeforeAdjust.GetInt())) { // we shouldn't readjust trendline // Only extend it to the last bar if(UpLineIndex2 < LastExtendedIndex || DownLineIndex2 < LastExtendedIndex) { if(UpLineIndex2 > 0) { for(int Index=UpLineIndex1; Index<=LastExtendedIndex; Index++ ) Subgraph_UpTrendline[Index] = (float)(UpLine_A*Index + UpLine_B); UpLineIndex2 = LastExtendedIndex; } if(DownLineIndex2 > 0) { for(int Index=DownLineIndex1; Index<=LastExtendedIndex; Index++ ) Subgraph_DownTrendline[Index] = (float)(DownLine_A*Index + DownLine_B); DownLineIndex2 = LastExtendedIndex; } } // Exit. Do not readjust trendlines return; } } // update previous index and StartIndex to re-adjust PrevIndex = LastIndex; StartIndex = LastIndex - Input_SkipLastBars.GetInt(); } if(Input_ShowTrendlineUp.GetYesNo() == 0 && Input_ShowTrendlineDown.GetYesNo() == 0) return; if(StartIndex < Input_LengthInput.GetInt()) return; int StartIndex1 = StartIndex; int LastIndex1 = StartIndex - Input_LengthInput.GetInt(); bool TLDrawn = false; // the variables which describe trendline equality double K = 0; double A = 0; double B = 0; // calculate UP trendlines if(Input_ShowTrendlineUp.GetYesNo() != 0) { // find LowestLow Index int LowestLowIndex1 = StartIndex1; int LowestLowIndex2 = -1; for(int Index=StartIndex1; Index >= LastIndex1; Index--) { if(Lows[Index] < Lows[LowestLowIndex1]) LowestLowIndex1 = Index; } // set second lowest low index as first lowest low + min trend line length LowestLowIndex2 = LowestLowIndex1; // search second LowestLow while(!TLDrawn) { // create new region where search lowest low int StartIndex2 = LowestLowIndex2 + 1; int LastIndex2 = StartIndex; if(StartIndex2 > LastIndex2) { TLDrawn = false; break; } LowestLowIndex2 = StartIndex2; for(int Index = StartIndex2; Index <= LastIndex2; Index++) { if(Lows[Index] < Lows[LowestLowIndex2]) LowestLowIndex2 = Index; } // check if the line does not cross any other bars // calculate trendline between Low on Index1 and Low on Index2 // A and B - these are coefficients of line equation K = (double)(LowestLowIndex2 - LowestLowIndex1); A = 0; B = 0; if(K != 0) { A = (Lows[LowestLowIndex2] - Lows[LowestLowIndex1])/K; B = Lows[LowestLowIndex1] - A * LowestLowIndex1; } // check if any of the bar between Index2 and Index1 cross the trendline TLDrawn = true; for(int Index=StartIndex1; Index >= LastIndex1; Index--) { // don't check former bars if(Index == LowestLowIndex2 || Index == LowestLowIndex1) continue; double TLValue = A*Index + B; if(TLValue > Lows[Index]) { TLDrawn = false; break; } } } // clean previous trendline for(int Index=UpLineIndex1; Index <= LastExtendedIndex; Index++) Subgraph_UpTrendline[Index] = 0; UpLineIndex1 = 0; UpLineIndex2 = 0; // draw trendline if it was found if(TLDrawn) { // We found correct trend line. Draw it Subgraph_UpTrendline[LowestLowIndex1] = Lows[LowestLowIndex1]; // fill all elements for(int Index=LowestLowIndex1+1; Index<=LastExtendedIndex; Index++ ) Subgraph_UpTrendline[Index] = (float)(A*Index + B); // save indexes in order to fast clean last drawn trendline UpLineIndex1 = LowestLowIndex1; UpLineIndex2 = LastExtendedIndex; UpLine_A = (float)A; UpLine_B = (float)B; } } // calculate down trendlines TLDrawn = false; if(Input_ShowTrendlineDown.GetYesNo() != 0) { // find LowestLow Index int HighestHighIndex1 = StartIndex1; int HighestHighIndex2 = -1; for(int Index=StartIndex1; Index >= LastIndex1; Index--) { if(Highs[Index] > Highs[HighestHighIndex1]) HighestHighIndex1 = Index; } // set second lowest low index as first lowest low + min trend line length HighestHighIndex2 = HighestHighIndex1; // search second LowestLow while(!TLDrawn) { // create new region where search lowest low int StartIndex2 = HighestHighIndex2 + 1; int LastIndex2 = StartIndex; if(StartIndex2 > LastIndex2) { TLDrawn = false; break; } HighestHighIndex2 = StartIndex2; for(int Index=StartIndex2; Index <= LastIndex2; Index++) { if(Highs[Index] > Highs[HighestHighIndex2]) HighestHighIndex2 = Index; } // check if the line does not cross any other bars // calculate trendline between Low on Index1 and Low on Index2 // A and B - these are coefficients of line equation K = (double)(HighestHighIndex2 - HighestHighIndex1); A = 0; B = 0; if(K != 0) { A = (Highs[HighestHighIndex2] - Highs[HighestHighIndex1])/K; B = Highs[HighestHighIndex1] - A * HighestHighIndex1; } // check if any of the bar between Index2 and Index1 cross the trendline TLDrawn = true; for(int Index=StartIndex1; Index >= LastIndex1; Index--) { // do not check former bars if(Index == HighestHighIndex2 || Index == HighestHighIndex1) continue; double TLValue = A*Index + B; if(TLValue < Highs[Index]) { TLDrawn = false; break; } } } // clean previous trendline for(int Index=DownLineIndex1; Index<=LastExtendedIndex; Index++) Subgraph_DownTrendline[Index] = 0; DownLineIndex1 = 0; DownLineIndex2 = 0; // draw trendline if it was found if(TLDrawn) { // We found correct trend line. Draw it Subgraph_DownTrendline[HighestHighIndex1] = Highs[HighestHighIndex1]; // fill all elements for(int Index=HighestHighIndex1+1; Index <= LastExtendedIndex; Index++ ) Subgraph_DownTrendline[Index] = (float)(A*Index + B); // save indexes in order to fast clean last drawn trendline DownLineIndex1 = HighestHighIndex1; DownLineIndex2 = LastExtendedIndex; DownLine_A = (float)A; DownLine_B = (float)B; } } } /***************************************************************/ // // Enhanced Renko Custom Chart // inline int RenkoFillHigh(SCStudyInterfaceRef sc, int32_t BaseGraphIndex, int32_t& RenkoIndex, float price, bool swap) { SCSubgraphRef Open = sc.Subgraph[SC_OPEN]; SCSubgraphRef High = sc.Subgraph[SC_HIGH]; SCSubgraphRef Low = sc.Subgraph[SC_LOW]; SCSubgraphRef Close = sc.Subgraph[SC_LAST]; SCSubgraphRef RenkoOpen = sc.Subgraph[SC_RENKO_OPEN]; float& brickSize = sc.GetPersistentFloat(1); float& renkoHigh = sc.GetPersistentFloat(2); float& renkoLow = sc.GetPersistentFloat(3); int& barComplete = sc.GetPersistentInt(2); int numBarsAdded = 0; if (barComplete) { // if outside range, then start with previous bar close else use passed value float openValue = (price > renkoHigh || price < renkoLow) ? Close[RenkoIndex] : price; // add new bar, but keep the renko limits sc.AddElements(1); numBarsAdded++; RenkoIndex++; sc.DateTimeOut[RenkoIndex] = sc.BaseDateTimeIn[BaseGraphIndex]; Open[RenkoIndex] = openValue; High[RenkoIndex] = openValue; Low[RenkoIndex] = openValue; Close[RenkoIndex] = openValue; barComplete = false; } if (sc.FormattedEvaluate(price, sc.BaseGraphValueFormat, LESS_OPERATOR, renkoHigh, sc.BaseGraphValueFormat)) { if (price > High[RenkoIndex]) High[RenkoIndex] = price; Close[RenkoIndex] = price; sc.CalculateOHLCAverages(RenkoIndex); return numBarsAdded; } // check the range to see if exceeded, and fill gap while (sc.FormattedEvaluate(price, sc.BaseGraphValueFormat, GREATER_OPERATOR, renkoHigh, sc.BaseGraphValueFormat)) { // close current bar High[RenkoIndex] = renkoHigh; Close[RenkoIndex] = renkoHigh; RenkoOpen[RenkoIndex] = max(renkoHigh - brickSize, Low[RenkoIndex]); if (swap) { float temp = Open[RenkoIndex]; Open[RenkoIndex] = RenkoOpen[RenkoIndex]; RenkoOpen[RenkoIndex] = temp; } sc.CalculateOHLCAverages(RenkoIndex); // add new bar sc.AddElements(1); numBarsAdded++; RenkoIndex++; sc.DateTimeOut[RenkoIndex] = sc.BaseDateTimeIn[BaseGraphIndex]; Open[RenkoIndex] = renkoHigh; High[RenkoIndex] = renkoHigh; Low[RenkoIndex] = renkoHigh; Close[RenkoIndex] = renkoHigh; sc.CalculateOHLCAverages(RenkoIndex); renkoHigh += brickSize; renkoLow = renkoHigh - 3.0f * brickSize; if (numBarsAdded >= 500) { sc.AddMessageToLog("Renko Chart Enhanced study: Error due to either data error or Brick Size too small. Stopping processing and skipping to next input bar. Try increasing the Brick Size.", 1); Close[RenkoIndex] = price; High[RenkoIndex] = price; renkoHigh = price; renkoLow = price - 3.0f * brickSize; } } // when done, bar can be complete or not if (sc.FormattedEvaluate(price, sc.BaseGraphValueFormat, EQUAL_OPERATOR, renkoHigh, sc.BaseGraphValueFormat)) { High[RenkoIndex] = price; Close[RenkoIndex] = price; RenkoOpen[RenkoIndex] = max(renkoHigh - brickSize, Low[RenkoIndex]); if (swap) { float temp = Open[RenkoIndex]; Open[RenkoIndex] = RenkoOpen[RenkoIndex]; RenkoOpen[RenkoIndex] = temp; } sc.CalculateOHLCAverages(RenkoIndex); renkoHigh += brickSize; renkoLow = renkoHigh - 3.0f * brickSize; barComplete = true; } else { Close[RenkoIndex] = price; sc.CalculateOHLCAverages(RenkoIndex); barComplete = false; } return numBarsAdded; } inline int RenkoFillLow(SCStudyInterfaceRef sc, int32_t BaseGraphIndex, int32_t& RenkoIndex, float price, bool swap) { SCSubgraphRef Open = sc.Subgraph[SC_OPEN]; SCSubgraphRef High = sc.Subgraph[SC_HIGH]; SCSubgraphRef Low = sc.Subgraph[SC_LOW]; SCSubgraphRef Close = sc.Subgraph[SC_LAST]; SCSubgraphRef RenkoOpen = sc.Subgraph[SC_RENKO_OPEN]; float& brickSize = sc.GetPersistentFloat(1); float& renkoHigh = sc.GetPersistentFloat(2); float& renkoLow = sc.GetPersistentFloat(3); int& barComplete = sc.GetPersistentInt(2); int NumberOfBarsAdded = 0; if (barComplete) { // if outside range, then start with previous bar close else use passed value float openValue = (price > renkoHigh || price < renkoLow) ? Close[RenkoIndex] : price; // add new bar, but keep the renko limits sc.AddElements(1); NumberOfBarsAdded++; RenkoIndex++; sc.DateTimeOut[RenkoIndex] = sc.BaseDateTimeIn[BaseGraphIndex]; Open[RenkoIndex] = openValue; High[RenkoIndex] = openValue; Low[RenkoIndex] = openValue; Close[RenkoIndex] = openValue; sc.CalculateOHLCAverages(RenkoIndex); barComplete = false; } if (sc.FormattedEvaluate(price, sc.BaseGraphValueFormat, GREATER_OPERATOR, renkoLow, sc.BaseGraphValueFormat)) { if (price < Low[RenkoIndex]) Low[RenkoIndex] = price; Close[RenkoIndex] = price; sc.CalculateOHLCAverages(RenkoIndex); return NumberOfBarsAdded; } // check the range to see if exceeded, and fill gap while (sc.FormattedEvaluate(price, sc.BaseGraphValueFormat, LESS_OPERATOR, renkoLow, sc.BaseGraphValueFormat)) { // close current bar Low[RenkoIndex] = renkoLow; Close[RenkoIndex] = renkoLow; RenkoOpen[RenkoIndex] = min(renkoLow + brickSize, High[RenkoIndex]); if (swap) { float temp = Open[RenkoIndex]; Open[RenkoIndex] = RenkoOpen[RenkoIndex]; RenkoOpen[RenkoIndex] = temp; } sc.CalculateOHLCAverages(RenkoIndex); // add new bar sc.AddElements(1); NumberOfBarsAdded++; RenkoIndex++; sc.DateTimeOut[RenkoIndex] = sc.BaseDateTimeIn[BaseGraphIndex]; Open[RenkoIndex] = renkoLow; High[RenkoIndex] = renkoLow; Low[RenkoIndex] = renkoLow; Close[RenkoIndex] = renkoLow; sc.CalculateOHLCAverages(RenkoIndex); renkoLow -= brickSize; renkoHigh = renkoLow + 3.0f * brickSize; if (NumberOfBarsAdded >= 500) { sc.AddMessageToLog("Renko Chart Enhanced study: Error due to either data error or Brick Size too small. Stopping processing and skipping to next input bar. Try increasing the Brick Size.", 1); Close[RenkoIndex] = price; Low[RenkoIndex] = price; renkoLow = price; renkoHigh = price + 3.0f * brickSize; } } // when done, bar can be complete or not if (sc.FormattedEvaluate(price, sc.BaseGraphValueFormat, EQUAL_OPERATOR, renkoLow, sc.BaseGraphValueFormat)) { Low[RenkoIndex] = price; Close[RenkoIndex] = price; RenkoOpen[RenkoIndex] = min(renkoLow + brickSize, High[RenkoIndex]); if (swap) { float temp = Open[RenkoIndex]; Open[RenkoIndex] = RenkoOpen[RenkoIndex]; RenkoOpen[RenkoIndex] = temp; } sc.CalculateOHLCAverages(RenkoIndex); renkoLow -= brickSize; renkoHigh = renkoLow + 3.0f * brickSize; barComplete = true; } else { Close[RenkoIndex] = price; sc.CalculateOHLCAverages(RenkoIndex); barComplete = false; } return NumberOfBarsAdded; } /*==========================================================================*/ inline int RenkoFill(SCStudyInterfaceRef sc, int32_t BaseGraphIndex, int32_t& RenkoIndex, float price, bool swap) { int numBarsAdded = 0; numBarsAdded += RenkoFillHigh(sc, BaseGraphIndex, RenkoIndex, price, swap); numBarsAdded += RenkoFillLow(sc, BaseGraphIndex, RenkoIndex, price, swap); return numBarsAdded; } /*==========================================================================*/ SCSFExport scsf_RenkoChartEnhanced(SCStudyInterfaceRef sc) { // Input references SCInputRef Input_brickSizeTicks = sc.Input[0]; SCInputRef Input_alignToBrickSize = sc.Input[1]; SCInputRef Input_showRealOpen = sc.Input[2]; SCInputRef Input_fillSessionGap = sc.Input[3]; // Base data references SCFloatArrayRef Array_iOpen = sc.BaseDataIn[SC_OPEN]; SCFloatArrayRef Array_iHigh = sc.BaseDataIn[SC_HIGH]; SCFloatArrayRef Array_iLow = sc.BaseDataIn[SC_LOW]; SCFloatArrayRef Array_iClose = sc.BaseDataIn[SC_LAST]; SCFloatArrayRef Array_iVolume = sc.BaseDataIn[SC_VOLUME]; SCFloatArrayRef Array_iNumTrades = sc.BaseDataIn[SC_NUM_TRADES]; SCFloatArrayRef Array_iBidVol = sc.BaseDataIn[SC_BIDVOL]; SCFloatArrayRef Array_iAskVol = sc.BaseDataIn[SC_ASKVOL]; SCFloatArrayRef Array_iUpTickVol = sc.BaseDataIn[SC_UPVOL]; SCFloatArrayRef Array_iDownTickVol = sc.BaseDataIn[SC_DOWNVOL]; SCFloatArrayRef Array_iBidTrades = sc.BaseDataIn[SC_BIDNT]; SCFloatArrayRef Array_iAskTrades = sc.BaseDataIn[SC_ASKNT]; SCFloatArrayRef Array_iBidAskDiffMax = sc.BaseDataIn[SC_ASKBID_DIFF_HIGH]; SCFloatArrayRef Array_iBidAskDiffMin = sc.BaseDataIn[SC_ASKBID_DIFF_LOW]; SCFloatArrayRef Array_iUpDownTickDiffMax = sc.BaseDataIn[SC_ASKBID_NUM_TRADES_DIFF_HIGH]; SCFloatArrayRef Array_iUpDownTickDiffMin = sc.BaseDataIn[SC_ASKBID_NUM_TRADES_DIFF_LOW]; // Output bar references SCSubgraphRef Subgraph_Open = sc.Subgraph[SC_OPEN]; SCSubgraphRef Subgraph_High = sc.Subgraph[SC_HIGH]; SCSubgraphRef Subgraph_Low = sc.Subgraph[SC_LOW]; SCSubgraphRef Subgraph_Close = sc.Subgraph[SC_LAST]; SCSubgraphRef Subgraph_Volume = sc.Subgraph[SC_VOLUME]; SCSubgraphRef Subgraph_NumTrades = sc.Subgraph[SC_NUM_TRADES]; SCSubgraphRef Subgraph_OHLCAvg = sc.Subgraph[SC_OHLC_AVG]; SCSubgraphRef Subgraph_HLCAvg = sc.Subgraph[SC_HLC_AVG]; SCSubgraphRef Subgraph_HLAvg = sc.Subgraph[SC_HL_AVG]; SCSubgraphRef Subgraph_BidVol = sc.Subgraph[SC_BIDVOL]; SCSubgraphRef Subgraph_AskVol = sc.Subgraph[SC_ASKVOL]; SCSubgraphRef Subgraph_UpTickVol = sc.Subgraph[SC_UPVOL]; SCSubgraphRef Subgraph_DownTickVol = sc.Subgraph[SC_DOWNVOL]; SCSubgraphRef Subgraph_BidTrades = sc.Subgraph[SC_BIDNT]; SCSubgraphRef Subgraph_AskTrades = sc.Subgraph[SC_ASKNT]; SCSubgraphRef Subgraph_BidAskDiffMax = sc.Subgraph[SC_ASKBID_DIFF_HIGH]; SCSubgraphRef Subgraph_BidAskDiffMin = sc.Subgraph[SC_ASKBID_DIFF_LOW]; SCSubgraphRef Subgraph_UpDownTickDiffMax = sc.Subgraph[SC_ASKBID_NUM_TRADES_DIFF_HIGH]; SCSubgraphRef Subgraph_UpDownTickDiffMin = sc.Subgraph[SC_ASKBID_NUM_TRADES_DIFF_LOW]; SCSubgraphRef Subgraph_RenkoOpen = sc.Subgraph[SC_RENKO_OPEN]; // Renko Open or True Open based on input value // Set configuration variables if (sc.SetDefaults) { // Set the defaults sc.GraphName = "Renko Chart Enhanced (unsupported)"; sc.StudyDescription = "Enhanced Renko custom chart."; sc.IsCustomChart = 1; sc.GraphRegion = 0; sc.StandardChartHeader = 1; sc.GraphUsesChartColors= true; sc.GraphDrawType = GDT_RENKO_BRICK_WITH_WICKS; sc.AutoLoop = 0; sc.ValueFormat = VALUEFORMAT_INHERITED; sc.MaintainAdditionalChartDataArrays = 1; // Inputs Input_brickSizeTicks.Name = "Brick Size In Ticks"; Input_brickSizeTicks.SetInt(4); Input_brickSizeTicks.SetIntLimits(1,MAX_STUDY_LENGTH); Input_alignToBrickSize.Name = "Align To Brick Size"; Input_alignToBrickSize.SetYesNo(1); Input_showRealOpen.Name = "Show Real Open (vs Renko Open)"; Input_showRealOpen.SetYesNo(0); Input_fillSessionGap.Name = "Fill Session Gap"; Input_fillSessionGap.SetYesNo(0); // Subgraphs Subgraph_Open.Name = "Open"; Subgraph_Open.DrawStyle = DRAWSTYLE_LINE; Subgraph_Open.PrimaryColor = RGB(0, 255, 0); Subgraph_Open.SecondaryColorUsed = true; Subgraph_Open.SecondaryColor = RGB(0, 255, 0); Subgraph_Open.DrawZeros = false; Subgraph_High.Name = "High"; Subgraph_High.DrawStyle = DRAWSTYLE_LINE; Subgraph_High.PrimaryColor = RGB(0, 128, 0); Subgraph_High.DrawZeros = false; Subgraph_Low.Name = "Low"; Subgraph_Low.DrawStyle = DRAWSTYLE_LINE; Subgraph_Low.PrimaryColor = RGB(255,0,0); Subgraph_Low.SecondaryColor = RGB(255,0,0); Subgraph_Low.SecondaryColorUsed = true; Subgraph_Low.DrawZeros = false; Subgraph_Close.Name = "Close"; Subgraph_Close.DrawStyle = DRAWSTYLE_LINE; Subgraph_Close.PrimaryColor = RGB(128, 0, 0); Subgraph_Close.DrawZeros = false; Subgraph_Volume.Name = "Volume"; Subgraph_Volume.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_Volume.PrimaryColor = RGB(255,0,0); Subgraph_Volume.DrawZeros = false; Subgraph_NumTrades.Name = "# of Trades"; Subgraph_NumTrades.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_NumTrades.PrimaryColor = RGB(0,0,255); Subgraph_NumTrades.DrawZeros = false; Subgraph_OHLCAvg.Name = "OHLC Avg"; Subgraph_OHLCAvg.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_OHLCAvg.PrimaryColor = RGB(127,0,255); Subgraph_OHLCAvg.DrawZeros = false; Subgraph_HLCAvg.Name = "HLC Avg"; Subgraph_HLCAvg.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_HLCAvg.PrimaryColor = RGB(0,255,255); Subgraph_HLCAvg.DrawZeros = false; Subgraph_HLAvg.Name = "HL Avg"; Subgraph_HLAvg.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_HLAvg.PrimaryColor = RGB(0,127,255); Subgraph_HLAvg.DrawZeros = false; Subgraph_BidVol.Name = "Bid Vol"; Subgraph_BidVol.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_BidVol.PrimaryColor = RGB(0,255,0); Subgraph_BidVol.DrawZeros = false; Subgraph_AskVol.Name = "Ask Vol"; Subgraph_AskVol.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_AskVol.PrimaryColor = RGB(0,255,0); Subgraph_AskVol.DrawZeros = false; Subgraph_UpTickVol.Name = "Up Tick Vol"; Subgraph_UpTickVol.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_UpTickVol.PrimaryColor = RGB(0,255,0); Subgraph_UpTickVol.DrawZeros = false; Subgraph_DownTickVol.Name = "Down Tick Vol"; Subgraph_DownTickVol.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_DownTickVol.PrimaryColor = RGB(0,255,0); Subgraph_DownTickVol.DrawZeros = false; Subgraph_BidTrades.Name = "Bid Trades"; Subgraph_BidTrades.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_BidTrades.PrimaryColor = RGB(0,255,0); Subgraph_BidTrades.DrawZeros = false; Subgraph_AskTrades.Name = "Ask Trades"; Subgraph_AskTrades.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_AskTrades.PrimaryColor = RGB(0,255,0); Subgraph_AskTrades.DrawZeros = false; // BidAskDiffMax.Name = "BidAskDiffMax"; // BidAskDiffMax.DrawStyle = DRAWSTYLE_IGNORE; // BidAskDiffMin.Name = "BidAskDiffMin"; // BidAskDiffMin.DrawStyle = DRAWSTYLE_IGNORE; // UpDownTickDiffMax.Name = "UpDownTickDiffMax"; // UpDownTickDiffMax.DrawStyle = DRAWSTYLE_IGNORE; // UpDownTickDiffMin.Name = "UpDownTickDiffMin"; // UpDownTickDiffMin.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_RenkoOpen.Name = "Renko/True Open"; Subgraph_RenkoOpen.DrawStyle = DRAWSTYLE_IGNORE; Subgraph_RenkoOpen.PrimaryColor = RGB(0,255,0); Subgraph_RenkoOpen.DrawZeros = false; return; } // refs to persistent vars float& brickSize = sc.GetPersistentFloat(1); // brickSize in terms of price float& renkoHigh = sc.GetPersistentFloat(2); float& renkoLow = sc.GetPersistentFloat(3); int& lastIndex = sc.GetPersistentInt(1); int& barComplete = sc.GetPersistentInt(2); SCDateTime& nextSessionStart = sc.GetPersistentSCDateTime(1); // track previous value of cumulative fields float& lastHigh = sc.GetPersistentFloat(4); float& lastLow = sc.GetPersistentFloat(5); float& lastVolume = sc.GetPersistentFloat(6); float& lastNumTrades = sc.GetPersistentFloat(7); float& lastBidVol = sc.GetPersistentFloat(8); float& lastAskVol = sc.GetPersistentFloat(9); float& lastUpTickVol = sc.GetPersistentFloat(10); float& lastDownTickVol = sc.GetPersistentFloat(11); float& lastBidTrades = sc.GetPersistentFloat(12); float& lastAskTrades = sc.GetPersistentFloat(13); if (sc.UpdateStartIndex == 0) { sc.ResizeArrays(0); sc.ValueFormat = sc.BaseGraphValueFormat; sc.GraphName.Format("%s Renko - BarSize: %i", sc.GetStudyName(0).GetChars(), Input_brickSizeTicks.GetInt()); Subgraph_RenkoOpen.Name = !Input_showRealOpen.GetYesNo() ? "True Open" : "Renko Open"; // init state brickSize = sc.RoundToTickSize(Input_brickSizeTicks.GetInt() * sc.TickSize, sc.TickSize); lastIndex = -1; barComplete = false; } int32_t RenkoIndex = sc.OutArraySize - 1; for (int32_t BaseGraphIndex = sc.UpdateStartIndex; BaseGraphIndex < sc.ArraySize; BaseGraphIndex++) { bool newInputBar = BaseGraphIndex != lastIndex; // if same bar and no new ticks, then continue if (!newInputBar && Array_iNumTrades[BaseGraphIndex] == lastNumTrades) continue; if (newInputBar) { // zero out last values lastVolume = 0; lastNumTrades = 0; lastBidVol = 0; lastAskVol = 0; lastUpTickVol = 0; lastDownTickVol = 0; lastBidTrades = 0; lastAskTrades = 0; } int numBarsAdded = 0; bool swap = !Input_showRealOpen.GetYesNo(); // starting new bar at session boundary ensures same bars, regardless of first date loaded in chart if (newInputBar && (BaseGraphIndex == 0 || sc.BaseDateTimeIn[BaseGraphIndex] >= nextSessionStart)) { nextSessionStart = sc.GetTradingDayStartDateTimeOfBar(sc.BaseDateTimeIn[BaseGraphIndex]) + 1*DAYS; if (BaseGraphIndex != 0) { if (Input_fillSessionGap.GetYesNo()) { // these bars do not contribute to bars added for volume distribution RenkoFill(sc, BaseGraphIndex, RenkoIndex, Array_iOpen[BaseGraphIndex], swap); } // close and adjust current bar if any if (!barComplete) { Subgraph_RenkoOpen[RenkoIndex] = Subgraph_Close[RenkoIndex-1]; // do not know if up or down bar if (swap) { float temp = Subgraph_Open[RenkoIndex]; Subgraph_Open[RenkoIndex] = Subgraph_RenkoOpen[RenkoIndex]; Subgraph_RenkoOpen[RenkoIndex] = temp; } sc.CalculateOHLCAverages(RenkoIndex); } } // start new bar for session sc.AddElements(1); RenkoIndex++; numBarsAdded++; sc.DateTimeOut[RenkoIndex] = sc.BaseDateTimeIn[BaseGraphIndex]; Subgraph_Open[RenkoIndex] = Array_iOpen[BaseGraphIndex]; Subgraph_High[RenkoIndex] = Array_iOpen[BaseGraphIndex]; Subgraph_Low[RenkoIndex] = Array_iOpen[BaseGraphIndex]; Subgraph_Close[RenkoIndex] = Array_iOpen[BaseGraphIndex]; sc.CalculateOHLCAverages(RenkoIndex); // adjust renko limits to align first brick of session to natural alignment float mod = !Input_alignToBrickSize.GetYesNo() ? brickSize : sc.RoundToTickSize(fmod(Subgraph_Close[RenkoIndex], brickSize), sc.TickSize); float mid = sc.FormattedEvaluate(mod, sc.BaseGraphValueFormat, EQUAL_OPERATOR, brickSize, sc.BaseGraphValueFormat) ? Subgraph_Close[RenkoIndex] : Subgraph_Close[RenkoIndex] - mod; renkoHigh = mid + brickSize; renkoLow = mid - brickSize; barComplete = false; // continue to process the bar } if (newInputBar) { if (sc.NumberOfTradesPerBar == 1) { // for tick bars, max of one bar added for volume purposes (i.e. gap) numBarsAdded = RenkoFill(sc, BaseGraphIndex, RenkoIndex, Array_iClose[BaseGraphIndex], swap); if (numBarsAdded > 1) numBarsAdded = 1; } else { // open price does not contribute to number of bars added for volume purposes (i.e. gap) numBarsAdded = RenkoFill(sc, BaseGraphIndex, RenkoIndex, Array_iOpen[BaseGraphIndex], swap); if (numBarsAdded > 1) numBarsAdded = 1; if (Array_iClose[BaseGraphIndex] > Array_iOpen[BaseGraphIndex]) { numBarsAdded += RenkoFillLow(sc, BaseGraphIndex, RenkoIndex, Array_iLow[BaseGraphIndex], swap); numBarsAdded += RenkoFillHigh(sc, BaseGraphIndex, RenkoIndex, Array_iHigh[BaseGraphIndex], swap); } else { numBarsAdded += RenkoFillHigh(sc, BaseGraphIndex, RenkoIndex, Array_iHigh[BaseGraphIndex], swap); numBarsAdded += RenkoFillLow(sc, BaseGraphIndex, RenkoIndex, Array_iLow[BaseGraphIndex], swap); } numBarsAdded += RenkoFill(sc, BaseGraphIndex, RenkoIndex, Array_iClose[BaseGraphIndex], swap); } } else { if (Array_iClose[BaseGraphIndex] > Array_iOpen[BaseGraphIndex]) { if (Array_iLow[BaseGraphIndex] != lastLow) numBarsAdded += RenkoFillLow(sc, BaseGraphIndex, RenkoIndex, Array_iLow[BaseGraphIndex], swap); if (Array_iHigh[BaseGraphIndex] != lastHigh) numBarsAdded += RenkoFillHigh(sc, BaseGraphIndex, RenkoIndex, Array_iHigh[BaseGraphIndex], swap); } else { if (Array_iHigh[BaseGraphIndex] != lastHigh) numBarsAdded += RenkoFillHigh(sc, BaseGraphIndex, RenkoIndex, Array_iHigh[BaseGraphIndex], swap); if (Array_iLow[BaseGraphIndex] != lastLow) numBarsAdded += RenkoFillLow(sc, BaseGraphIndex, RenkoIndex, Array_iLow[BaseGraphIndex], swap); } numBarsAdded += RenkoFill(sc, BaseGraphIndex, RenkoIndex, Array_iClose[BaseGraphIndex], swap); } bool HaveBidAskDiff = sc.BaseDataIn.GetArraySize() >= SC_ASKBID_DIFF_LOW+1; if (HaveBidAskDiff) { // BidAskDiff is not distributed, only updated on last bar float value; value = max(Subgraph_AskVol[RenkoIndex] - Subgraph_BidVol[RenkoIndex], Array_iBidAskDiffMax[BaseGraphIndex]); if (numBarsAdded > 0 || value > Subgraph_BidAskDiffMax[RenkoIndex]) Subgraph_BidAskDiffMax[RenkoIndex] = value; value = min(Subgraph_AskVol[RenkoIndex] - Subgraph_BidVol[RenkoIndex], Array_iBidAskDiffMin[BaseGraphIndex]); if (numBarsAdded > 0 || value < Subgraph_BidAskDiffMin[RenkoIndex]) Subgraph_BidAskDiffMin[RenkoIndex] = value; value = max(Subgraph_AskTrades[RenkoIndex] - Subgraph_BidTrades[RenkoIndex], Array_iUpDownTickDiffMax[BaseGraphIndex]); if (numBarsAdded > 0 || value > Subgraph_UpDownTickDiffMax[RenkoIndex]) Subgraph_UpDownTickDiffMax[RenkoIndex] = value; value = min(Subgraph_AskTrades[RenkoIndex] - Subgraph_BidTrades[RenkoIndex], Array_iUpDownTickDiffMin[BaseGraphIndex]); if (numBarsAdded > 0 || value < Subgraph_UpDownTickDiffMin[RenkoIndex]) Subgraph_UpDownTickDiffMin[RenkoIndex] = value; } if (numBarsAdded <= 1) { Subgraph_Volume[RenkoIndex] += (Array_iVolume[BaseGraphIndex] - lastVolume); Subgraph_NumTrades[RenkoIndex] += (Array_iNumTrades[BaseGraphIndex] - lastNumTrades); Subgraph_BidVol[RenkoIndex] += (Array_iBidVol[BaseGraphIndex] - lastBidVol); Subgraph_AskVol[RenkoIndex] += (Array_iAskVol[BaseGraphIndex] - lastAskVol); Subgraph_UpTickVol[RenkoIndex] += (Array_iUpTickVol[BaseGraphIndex] - lastUpTickVol); Subgraph_DownTickVol[RenkoIndex] += (Array_iDownTickVol[BaseGraphIndex] - lastDownTickVol); Subgraph_BidTrades[RenkoIndex] += (Array_iBidTrades[BaseGraphIndex] - lastBidTrades); Subgraph_AskTrades[RenkoIndex] += (Array_iAskTrades[BaseGraphIndex] - lastAskTrades); } else { // split volume across bars added, with mod allocated to last bar Subgraph_Volume[RenkoIndex] = (Array_iVolume[BaseGraphIndex] - lastVolume); Subgraph_NumTrades[RenkoIndex] = (Array_iNumTrades[BaseGraphIndex] - lastNumTrades); Subgraph_BidVol[RenkoIndex] = (Array_iBidVol[BaseGraphIndex] - lastBidVol); Subgraph_AskVol[RenkoIndex] = (Array_iAskVol[BaseGraphIndex] - lastAskVol); Subgraph_UpTickVol[RenkoIndex] = (Array_iUpTickVol[BaseGraphIndex] - lastUpTickVol); Subgraph_DownTickVol[RenkoIndex] = (Array_iDownTickVol[BaseGraphIndex] - lastDownTickVol); Subgraph_BidTrades[RenkoIndex] = (Array_iBidTrades[BaseGraphIndex] - lastBidTrades); Subgraph_AskTrades[RenkoIndex] = (Array_iAskTrades[BaseGraphIndex] - lastAskTrades); int VolumeAllocation = (int)Subgraph_Volume[RenkoIndex] / numBarsAdded; int NumTradesAllocation = (int)Subgraph_NumTrades[RenkoIndex] / numBarsAdded; int BidVolAllocation = (int)Subgraph_BidVol[RenkoIndex] / numBarsAdded; int AskVolAllocation = (int)Subgraph_AskVol[RenkoIndex] / numBarsAdded; int UpTickVolAllocation = (int)Subgraph_UpTickVol[RenkoIndex] / numBarsAdded; int DownTickVolAllocation = (int)Subgraph_DownTickVol[RenkoIndex] / numBarsAdded; int BidTradesAllocation = (int)Subgraph_BidTrades[RenkoIndex] / numBarsAdded; int AskTradesAllocation = (int)Subgraph_AskTrades[RenkoIndex] / numBarsAdded; for (int32_t VolumeUpdateIndex = RenkoIndex - numBarsAdded + 1; VolumeUpdateIndex < RenkoIndex; VolumeUpdateIndex++) { Subgraph_Volume[VolumeUpdateIndex] = (float)VolumeAllocation; Subgraph_NumTrades[VolumeUpdateIndex] = (float)NumTradesAllocation; if (!HaveBidAskDiff) { Subgraph_BidVol[VolumeUpdateIndex] = (float)BidVolAllocation; Subgraph_AskVol[VolumeUpdateIndex] = (float)AskVolAllocation; } Subgraph_UpTickVol[VolumeUpdateIndex] = (float)UpTickVolAllocation; Subgraph_DownTickVol[VolumeUpdateIndex] = (float)DownTickVolAllocation; Subgraph_BidTrades[VolumeUpdateIndex] = (float)BidTradesAllocation; Subgraph_AskTrades[VolumeUpdateIndex] = (float)AskTradesAllocation; Subgraph_Volume[RenkoIndex] -= VolumeAllocation; Subgraph_NumTrades[RenkoIndex] -= NumTradesAllocation; if (!HaveBidAskDiff) { Subgraph_BidVol[RenkoIndex] -= BidVolAllocation; Subgraph_AskVol[RenkoIndex] -= AskVolAllocation; } Subgraph_UpTickVol[RenkoIndex] -= UpTickVolAllocation; Subgraph_DownTickVol[RenkoIndex] -= DownTickVolAllocation; Subgraph_BidTrades[RenkoIndex] -= BidTradesAllocation; Subgraph_AskTrades[RenkoIndex] -= AskTradesAllocation; } } // save last values lastIndex = BaseGraphIndex; lastLow = Array_iLow[BaseGraphIndex]; lastHigh = Array_iHigh[BaseGraphIndex]; lastVolume = Array_iVolume[BaseGraphIndex]; lastNumTrades = Array_iNumTrades[BaseGraphIndex]; lastBidVol = Array_iBidVol[BaseGraphIndex]; lastAskVol = Array_iAskVol[BaseGraphIndex]; lastUpTickVol = Array_iUpTickVol[BaseGraphIndex]; lastDownTickVol = Array_iDownTickVol[BaseGraphIndex]; lastBidTrades = Array_iBidTrades[BaseGraphIndex]; lastAskTrades = Array_iAskTrades[BaseGraphIndex]; } } /*==========================================================================*/