//+------------------------------------------------------------------+ //| Candle Patterns.mq4 | //| Copyright © 2008, sx ted | //| tedhirsch@talktalk.net | //| 2008.12.16 | //| Purpose..: Visual and Audio alerts when reversal or continuation | //| candle patterns occur. | //| Based On.: Many many thanks to: | //| 1) Japanese Candlesticks http://www.candlesticker.com | //| 2) CandleCode by Victor Likhovidov, references to be | //| found at http://www.forexschool.ru | //| Thank you: Big thank you CodersGuru at http://www.forex-tsd.com | //| for coding the gSpeak() function so as to have audio | //| signals. | //| Setup....: Place files into the following subdirectories: | //| Candle Patterns.mq4 into "\experts\indicators", | //| Candle Patterns.csv into "\experts\files", | //| Candle Patterns.rtd into "\experts\files", | //| Symbols_.csv into "\experts\files", | //| gSpeak.mqh into "\experts\include", | //| speak.dll into "\experts\libraries", | //| candle patterns.tpl into "\templates". | //| Close and then re-start MetaTrader for it to find the | //| new files. | //| Select "Indicators" -> "Custom" -> "Candle Patterns". | //| The "Custom Indicator" window is displayed, select | //| "Common" and enable "Allow DLL imports". | //| "Inputs" are described in file "Candle Patterns.rtd", | //| alternatively right click on the chart and select | //| "candle patterns.tpl" from "Templates". | //| Note 1...: While testing, the indicator has not yet encountered | //| patterns comprised of four or five candles, please let| //| me know on which broker's chart and time frame seen | //| and publish it on the forum as a .GIF image would be | //| super. | //| Note 2...: Delete the Candle Patterns indicator from the chart | //| before changing the period. | //+------------------------------------------------------------------+ #property copyright "Copyright © 2008, sx ted" #property link "tedhirsch@talktalk.net" //+------------------------------------------------------------------+ //| indicator setup | //+------------------------------------------------------------------+ #property indicator_chart_window #property indicator_buffers 2 // helps improve memory //+------------------------------------------------------------------+ //| EX4 imports | //+------------------------------------------------------------------+ #include <gSpeak.mqh> //+------------------------------------------------------------------+ //| input parameters: | //+-----------0---+----1----+----2----+----3]------------------------+ extern int MaxBarsToScanForPatterns = 1; // 0: display visible patterns only // 1: display pattern of bar 1 only // >1: display patterns up to MaxBars extern bool ConfirmPattern = true; extern bool MoveTextOneRowDown = true; extern bool AudioON = true; extern color ColorSingleCandle = Aqua; extern color ColorMultiCandles = DeepSkyBlue; extern color AlternateColorSingleCandle = Yellow; extern color AlternateColorMultiCandles = Gold; extern color ColorArrowDown = DarkOrange; extern color ColorArrowUp = Lime; extern color ColorText = LemonChiffon; extern int VerticalTextAdjustX = 1; // adjust co-ord x of vertical text extern int VerticalTextFontSize = 8; // for zoom level 3 extern int TrendMA_Period = 13; // Averaging period for calculation extern int TrendMA_Shift = 15; // Shift relative to the current bar // to compare the averages so as to // determine the trend //+------------------------------------------------------------------+ //| defines | //+------------------------------------------------------------------+ #define CALC_ALL -9 // calculate all flag #define MAX_CANDLES 5 // max candles in a pattern #define ERR_0 0.00001 // avoid divide by zero factor //-------------------------------------------------------------------- Candle and shadow sizes: #define CandleBodyCount 0 // Candle Body Count if size > 0 #define CandleBodyTotal 1 // Candle Body aggregate #define SmallCandleBody 2 // Candle Body Small (top threshold) #define LongCandleBody 3 // Candle Body Long (bottom threshold) #define UpperShadowCount 4 // Upper Shadow Count if size > 0 #define UpperShadowTotal 5 // Upper Shadow aggregate #define SmallUpperShadow 6 // Upper Shadow Small (top threshold) #define LongUpperShadow 7 // Upper Shadow Long (bottom threshold) #define BottomShadowCount 8 // Lower Shadow Count if size > 0 #define BottomShadowTotal 9 // Lower Shadow aggregate #define SmallBottomShadow 10 // Lower Shadow Small (top threshold) #define LongBottomShadow 11 // Lower Shadow Long (bottom threshold) #define SIZE_CNT 12 // array dSize count of elements #define LT_FACTOR 0.31 // Lower Threshold Factor //-------------------------------------------------------------------- Base Candles: #define FourPriceDoji 0 // 0 #define Umbrella_1 1 // 1 #define Umbrella_2 2 // 2 #define Doji 3 // 3 #define DojiSN 4 // 4 Doji with small/normal legs #define DojiSNL 5 // 5 Doji with all kinds of legs #define InvertedUmbrella_6 6 // 6 #define InvertedUmbrella_7 7 // 7 #define LongLeggedDoji_8 8 // 8 #define LongLeggedDoji_9 9 // 9 #define SmallBlackCandle 10 // A #define HighWave 11 // B #define BlackSpinningTop 12 // C #define BlackCandle 13 // D #define BlackCandleDay4LadderBottom 14 // E #define BlackDay3ConcealBabySwallow 15 // F #define BlackMarubozu 16 // G #define BlackOpeningMarubozu 17 // H #define BlackOpeningMarubozuLongshadow 18 // I #define BlackClosingMarubozu 19 // J #define LongBlackCandle 20 // K #define SmallWhiteCandle 21 // L #define WhiteSpinningTop 22 // M #define WhiteCandle 23 // N #define WhiteMarubozu 24 // O #define WhiteClosingMarubozu 25 // P #define WhiteOpeningMarubozu 26 // Q #define LongWhiteCandle 27 // R #define BlackHammerOrHangingMan 28 // S #define WhiteHammerOrHangingMan 29 // T #define InvertedUmbrella_U 30 // U #define InvertedUmbrella_V 31 // V #define BlackInvertedHammerOrStar 32 // W #define WhiteInvertedHammerOrStar 33 // X //-------------------------------------------------------------------- sPattern: specs & name #define P_DISPLAY 0 // Display flag: 1=Display, 0=Hide #define P_TYP 1 // pattern Type: R=Reversal, C=Continuation, X=Reversal/Continuation #define P_REE 2 // pattern Relevance: D=Bearish, U=Bullish, I=Indecision #define P_PRV 3 // Previous trend: D=Bearish, U=Bullish X=N/A #define P_NUM 4 // Number of candles #define P_CHK 5 // confirmation Check: refer to ConfirmPattern para #define P_LEN 6 // Length of name #define P_NAM 7 // pattern Name //-------------------------------------------------------------------- arrow shapes: #define C_DN "ê" // -22 was 234 for identifying font "Wingdings" character Arrow Down #define C_UP "é" // -23 was 233 for identifying font "Wingdings" character Arrow Up //-------------------------------------------------------------------- Text to Audio: #define M_BUY "Buy" #define M_DN "Pattern confirmed down" #define M_REV_DN "Pattern confirmed reverse down" #define M_REV_UP "Pattern confirmed reverse up" #define M_UP "Pattern confirmed up" #define M_SELL "Sell" #define M_NULL "" //-------------------------------------------------------------------- Trade Type: #define TT_BUY 0 // Buy #define TT_SELL 1 // Sell #define TT_NO_PATTERN -1 // No Pattern found #define TT_WAIT -2 // cater for Reversal/Continuation and wait for confirmation //-------------------------------------------------------------------- font: #define V_TXT_FONT_SIZE 8 // original font size used while scaling vertical text //+------------------------------------------------------------------+ //| global variables to program: | //+------------------------------------------------------------------+ bool bAlternateColorMulti, bAlternateColorSingle, TrendDn, TrendUp; datetime tPreviousTime; double dSize[SIZE_CNT], // candle sizes dPipsFactor, // price to pips conversion factor O[MAX_CANDLES], // Open H[MAX_CANDLES], // High L[MAX_CANDLES], // Low C[MAX_CANDLES], // Close B[MAX_CANDLES], // candle body bottom T[MAX_CANDLES]; // candle body top int candle[MAX_CANDLES], // candle code iBarsToScan, iPattern, // candle Pattern number iPeriod, iScaleAdjustX, // used for vertical text alignment iScaleAdjustX_MN, // PERIOD MN1 basis for pro rata calc iScaleAdjustY, iVeryNear, iVerySmallBody; string sBoxObj, sMsg, sAudio, sPRV, // Previous Trend Confirmation arrow sREE, // Relevance Confirmation arrow sSymbol; /*-------------------------------------------------------------------- Base Candles: Dec,Base candle code number , p,c, b , u, l */ int iBaseCandle[96][2]={ 0,FourPriceDoji, // 0,0,000,00,00 3,Umbrella_1, // 0,0,000,00,11 4,InvertedUmbrella_U, // 0,0,000,01,00 5,Doji, // 0,0,000,01,01 6,DojiSN, // 0,0,000,01,10 7,DojiSNL, // 0,0,000,01,11 8,InvertedUmbrella_V, // 0,0,000,10,00 9,DojiSN, // 0,0,000,10,01 10,DojiSN, // 0,0,000,10,10 11,DojiSNL, // 0,0,000,10,11 12,InvertedUmbrella_6, // 0,0,000,11,00 13,DojiSNL, // 0,0,000,11,01 14,DojiSNL, // 0,0,000,11,10 15,LongLeggedDoji_8, // 0,0,000,11,11 19,Umbrella_2, // 0,0,001,00,11 21,DojiSN, // 0,0,001,01,01 22,DojiSN, // 0,0,001,01,10 23,DojiSNL, // 0,0,001,01,11 25,DojiSN, // 0,0,001,10,01 26,DojiSN, // 0,0,001,10,10 27,DojiSNL, // 0,0,001,10,11 28,InvertedUmbrella_7, // 0,0,001,11,00 29,DojiSNL, // 0,0,001,11,01 30,DojiSNL, // 0,0,001,11,10 31,LongLeggedDoji_9, // 0,0,001,11,11 39,HighWave, // 0,0,010,01,11 43,HighWave, // 0,0,010,10,11 45,HighWave, // 0,0,010,11,01 46,HighWave, // 0,0,010,11,10 47,HighWave, // 0,0,010,11,11 56,BlackCandleDay4LadderBottom, // 0,0,011,10,00 60,BlackDay3ConcealBabySwallow, // 0,0,011,11,00 64,BlackMarubozu, // 0,0,100,00,00 65,BlackOpeningMarubozu, // 0,0,100,00,01 66,BlackOpeningMarubozu, // 0,0,100,00,10 67,BlackOpeningMarubozuLongshadow, // 0,0,100,00,11 68,BlackClosingMarubozu, // 0,0,100,01,00 69,LongBlackCandle, // 0,0,100,01,01 70,LongBlackCandle, // 0,0,100,01,10 71,LongBlackCandle, // 0,0,100,01,11 72,BlackClosingMarubozu, // 0,0,100,10,00 73,LongBlackCandle, // 0,0,100,10,01 74,LongBlackCandle, // 0,0,100,10,10 75,LongBlackCandle, // 0,0,100,10,11 76,BlackClosingMarubozu, // 0,0,100,11,00 77,LongBlackCandle, // 0,0,100,11,01 78,LongBlackCandle, // 0,0,100,11,10 79,LongBlackCandle, // 0,0,100,11,11 147,Umbrella_2, // 0,1,001,00,11 149,DojiSN, // 0,1,001,01,01 150,DojiSN, // 0,1,001,01,10 151,DojiSNL, // 0,1,001,01,11 153,DojiSN, // 0,1,001,10,01 154,DojiSN, // 0,1,001,10,10 155,DojiSNL, // 0,1,001,10,11 156,InvertedUmbrella_7, // 0,1,001,11,00 157,DojiSNL, // 0,1,001,11,01 158,DojiSNL, // 0,1,001,11,10 159,LongLeggedDoji_9, // 0,1,001,11,11 167,HighWave, // 0,1,010,01,11 171,HighWave, // 0,1,010,10,11 173,HighWave, // 0,1,010,11,01 174,HighWave, // 0,1,010,11,10 175,HighWave, // 0,1,010,11,11 192,WhiteMarubozu, // 0,1,100,00,00 193,WhiteClosingMarubozu, // 0,1,100,00,01 194,WhiteClosingMarubozu, // 0,1,100,00,10 195,WhiteClosingMarubozu, // 0,1,100,00,11 196,WhiteOpeningMarubozu, // 0,1,100,01,00 197,LongWhiteCandle, // 0,1,100,01,01 198,LongWhiteCandle, // 0,1,100,01,10 199,LongWhiteCandle, // 0,1,100,01,11 200,WhiteOpeningMarubozu, // 0,1,100,10,00 201,LongWhiteCandle, // 0,1,100,10,01 202,LongWhiteCandle, // 0,1,100,10,10 203,LongWhiteCandle, // 0,1,100,10,11 204,WhiteOpeningMarubozu, // 0,1,100,11,00 205,LongWhiteCandle, // 0,1,100,11,01 206,LongWhiteCandle, // 0,1,100,11,10 207,LongWhiteCandle, // 0,1,100,11,11 291,BlackHammerOrHangingMan, // 1,0,010,00,11 293,SmallBlackCandle, // 1,0,010,01,01 298,BlackSpinningTop, // 1,0,010,10,10 299,BlackSpinningTop, // 1,0,010,10,11 300,BlackInvertedHammerOrStar, // 1,0,010,11,00 302,BlackSpinningTop, // 1,0,010,11,10 303,BlackSpinningTop, // 1,0,010,11,11 309,BlackCandle, // 1,0,011,01,01 419,WhiteHammerOrHangingMan, // 1,1,010,00,11 421,SmallWhiteCandle, // 1,1,010,01,01 426,WhiteSpinningTop, // 1,1,010,10,10 427,WhiteSpinningTop, // 1,1,010,10,11 428,WhiteInvertedHammerOrStar, // 1,1,010,11,00 430,WhiteSpinningTop, // 1,1,010,11,10 431,WhiteSpinningTop, // 1,1,010,11,11 437,WhiteCandle // 1,1,011,01,01 }; //-------------------------------------------------------------------- Candle Patterns: string sPattern[91][8]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void init() { // Period ,TextSize,ChartHeight, int iTextRatios[9][3]={PERIOD_M1 , 5, 20, // TextSize based on Pattern number PERIOD_M5 , 21, 70, // 40 and scaled using the Crosshair PERIOD_M15, 32, 110, // and custom indicator CP_TextSize. PERIOD_M30, 35, 120, // PERIOD_H1 , 35, 120, // ChartHeight is the height of chart PERIOD_H4 , 139, 470, // in points, with no sub-windows, PERIOD_D1 , 285, 960, // when Pattern 40 was scaled, PERIOD_W1 , 552, 1864, // corresponds to PriceMaxVisible() PERIOD_MN1, 1729, 5850 // minus PriceMinVisible(). }, i, x; ObjectsDeletePrefixed("CP_"); candle[0]=CALC_ALL; // load all flag dPipsFactor=MathPow(10, Digits); dSize[0]=CALC_ALL; // calculate average for all bars flag iPattern=TT_NO_PATTERN; iPeriod=Period(); sBoxObj=""; sMsg=""; sAudio=""; sPRV=""; sREE=""; sSymbol=Symbol(); tPreviousTime=D'01.01.2008'; if(StringArrayLoad("Candle Patterns.csv", sPattern, 8)<1) sMsg=StringConcatenate(sMsg,"Error "+GetLastError()+" reading file Candle Patterns.csv\n"); if(AudioON) { if(IsDllsAllowed()==false) sMsg=StringConcatenate(sMsg,"Check \"Allow DLL imports\" to enable program\n"); string sSymbols[][2]; x=StringArrayLoad("Symbols_.csv", sSymbols, 2); if(x<1) sMsg=StringConcatenate(sMsg,"Error "+GetLastError()+" reading file Symbols_.csv\n"); for(i=0; i<x; i++) { if(sSymbols[i][0]==sSymbol) break; } if(i<x) sAudio=sSymbols[i][1]; else sMsg=StringConcatenate(sMsg,"Symbol not found\n"); string sPeriods[9][2]={ "1", "1 minute", "5", "5 minutes", "15", "15 minutes", "30", "30 minutes", "60", "1 hour", "240", "4 hour", "1440", "Daily", "10080", "Weekly", "43200", "Monthly" }; for(i=0; i<9; i++) { if(sPeriods[i][0]==DoubleToStr(iPeriod,0)) break; } if(i<9) sAudio=StringConcatenate(sAudio," ",sPeriods[i][1]," "); else sMsg=StringConcatenate(sMsg,"Period not found\n"); } if(MaxBarsToScanForPatterns == 1) { CreateLabelObject("CP_CONFIRM_PRIOR_TREND", 1, 76, MoveTextOneRowDown*10); CreateLabelObject("CP_CONFIRM_RELEVANCE" , 1, 61, MoveTextOneRowDown*10); CreateLabelObject("CP_TYPE" , 1, 46, MoveTextOneRowDown*10); CreateLabelObject("CP_PRIOR_TREND" , 1, 31, MoveTextOneRowDown*10); CreateLabelObject("CP_RELEVANCE" , 1, 16, MoveTextOneRowDown*10); CreateLabelObject("CP_CONFIRMATION" , 1, 1, MoveTextOneRowDown*10); CreateLabelObject("CP_NAME" , 0, 0, MoveTextOneRowDown*10); } else { if(WindowsTotal() > 1) Alert("Labels may overwrite candles if sub-windows open!"); // determine factors for adjustment of vertical text so that labels // do not overlay candles, if possible, as MT4 co-ordinates refer // to the center of label object's (horizontal by design) iScaleAdjustX=-1; iScaleAdjustX_MN=-1; for(i=0; i<9; i++) { // for all chart timeframe's if(iTextRatios[i][0] == iPeriod) { iScaleAdjustX=iTextRatios[i][1]; iScaleAdjustY=iTextRatios[i][2]; } if(iTextRatios[i][0] == PERIOD_MN1) iScaleAdjustX_MN=iTextRatios[i][1]; } if(iScaleAdjustX == -1 || iScaleAdjustX_MN == -1) sMsg=StringConcatenate(sMsg,"Period not found\n"); iBarsToScan=MathMin(Bars-MAX_CANDLES,MathMax(MaxBarsToScanForPatterns,WindowBarsPerChart())); if(iBarsToScan < MAX_CANDLES+1) sMsg=StringConcatenate(sMsg,"Bars < ",MAX_CANDLES+1,"\n"); for(i=iBarsToScan; i>1; i--) { iPattern=Pattern(i); if((iPattern >= 0) && (sPattern[iPattern][P_DISPLAY] == "1")) DisplayPatterns(iPattern, i); } } if(sMsg!="") Alert(sMsg); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void deinit() { ObjectsDeletePrefixed("CP_"); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ void start() { color cColor=ColorArrowUp; int i, x; string sChr=C_UP, obj; if(sMsg!="") return; if((MaxBarsToScanForPatterns != 1) && (Bars > WindowFirstVisibleBar())) { // Bars > WndLeft // Wait for tick and redraw all visible vertical text as chart may have changed height i=1; int iWndLeft=WindowFirstVisibleBar(); double dWndTop=WindowPriceMax(), dWndBot=WindowPriceMin(), dPriceMax=PriceMaxVisible(), dPriceMin=PriceMinVisible(); if(dPriceMax > dWndTop) dWndTop=dPriceMax; if(dPriceMin < dWndBot) dWndBot=dPriceMin; while(i <= iWndLeft) { obj="CP_"+Time[i]; if((ObjectFind(obj) >= 0) && (ObjectType(obj) == OBJ_TEXT)) MoveLabel(obj, dWndTop, dWndBot, dPriceMax, dPriceMin); i++; } WindowRedraw(); // force redraw of current chart after moving of objects } if(tPreviousTime == Time[0]) return; // only start analysis on complete bars if(Bars < MAX_CANDLES+1) return; if(MaxBarsToScanForPatterns == 1) { // switch off any previous confirming arrows DisplayLabelObject("CP_CONFIRM_PRIOR_TREND", " ", ColorText); DisplayLabelObject("CP_CONFIRM_RELEVANCE" , " ", ColorText); // remember last pattern number for confirmation of previous candle pattern x=iPattern; // check if newly formed bar 1 matches a candle pattern iPattern=Pattern(1); PatternConfirm(x); // delete hilite of previous pattern ObjectDelete("CP_BOX"); // check if a new candle pattern has been found if((iPattern >= 0) && (sPattern[iPattern][P_DISPLAY] == "1")) { DisplayPattern1(iPattern, 1); // display indication of current trend with arrow Up or arrow Down if(TrendDn) { sChr=C_DN; cColor=ColorArrowDown; } DisplayLabelObject("CP_PRIOR_TREND", sChr, cColor); sPRV=sChr; /* display indication of Relevance (new direction): TYP |REE| PRV | Action ----+---+-----+--------------------------------- C | D | D | Sell C | U | U | Buy R | D | U | Sell R | D | X | Sell R | I | Xup| Sell Patterns 1/2/3/4 R | I | Xdn| Buy Patterns 1/2/3/4 R | U | D | Buy R | U | X | Buy Pattern 51 X | D | X | Sell Patterns 46-49 on Relevance X | I | X | Wait X | U | X | Buy Patterns 85-88 on Relevance */ if((sPattern[iPattern][P_REE] == "U") || (sPattern[iPattern][P_REE] == "I" && sPattern[iPattern][P_TYP] == "R" && TrendDn)) { sMsg=M_BUY; sChr=C_UP; cColor=ColorArrowUp; } else if((sPattern[iPattern][P_REE] == "D") || (sPattern[iPattern][P_REE] == "I" && sPattern[iPattern][P_TYP] == "R" && TrendUp)) { sMsg=M_SELL; sChr=C_DN; cColor=ColorArrowDown; } else sChr=sPattern[iPattern][P_REE]; // "I" (Indecision) DisplayLabelObject("CP_RELEVANCE", sChr, cColor); sREE=sChr; // display indication of Pattern Type: R=Reversal, C=Continuation, X=Reversal/Continuation DisplayLabelObject("CP_TYPE", sPattern[iPattern][P_TYP], cColor); // display Confirmation required: Pattern Type R/C=_Q, X=_S if(sPattern[iPattern][P_TYP] == "X") sChr=" "; else sChr="?"; DisplayLabelObject("CP_CONFIRMATION", sChr, cColor); sMsg=StringConcatenate(sPattern[iPattern][P_NAM]," ",sMsg); if(AudioON) gSpeak(StringConcatenate(sAudio,sPattern[iPattern][P_NAM])); } else { // pattern not found sMsg=" "; sPRV=" "; sREE=" "; DisplayLabelObject("CP_TYPE" , " ", ColorArrowDown); DisplayLabelObject("CP_PRIOR_TREND" , " ", ColorArrowDown); DisplayLabelObject("CP_RELEVANCE" , " ", ColorArrowDown); DisplayLabelObject("CP_CONFIRMATION", " ", ColorArrowDown); } // display Pattern Name & stats ObjectSetText("CP_NAME",sMsg,11,"Verdana",ColorText); } else { // delete objects beyond range requested by <iBarsToScan> obj="CP_"+Time[iBarsToScan]; if(ObjectFind(obj) >= 0) ObjectDelete(obj); obj="CP_B"+Time[iBarsToScan]; if(ObjectFind(obj) >= 0) ObjectDelete(obj); // remember last pattern number for confirmation of previous candle pattern x=iPattern; // check if newly formed bar 1 matches a candle pattern iPattern=Pattern(1); PatternConfirm(x); if((iPattern >= 0) && (sPattern[iPattern][P_DISPLAY] == "1")) { DisplayPatterns(iPattern, 1); if(AudioON) gSpeak(StringConcatenate(sAudio,sPattern[iPattern][P_NAM])); } } tPreviousTime=Time[0]; sMsg=""; } //+------------------------------------------------------------------+ //| CreateLabelObject | //+------------------------------------------------------------------+ void CreateLabelObject(string obj, int iCorner, int x, int y) { ObjectCreate(obj, OBJ_LABEL, 0, 0, 0); ObjectSet(obj, OBJPROP_CORNER , iCorner); ObjectSet(obj, OBJPROP_XDISTANCE, x ); ObjectSet(obj, OBJPROP_YDISTANCE, y ); } //+------------------------------------------------------------------+ //| DisplayLabelObject | //+------------------------------------------------------------------+ void DisplayLabelObject(string obj, string sChr, color cColor) { int y=1, iFontSize=14; string sFont="Verdana"; if(sChr == "?" ) { y=0; iFontSize=15; sFont="Verdana" ; } if(sChr == C_DN) { y=5; iFontSize=13; sFont="Wingdings"; } if(sChr == C_UP) { y=1; iFontSize=13; sFont="Wingdings"; } ObjectSet(obj, OBJPROP_YDISTANCE, MoveTextOneRowDown*10+y); ObjectSetText(obj, sChr, iFontSize, sFont, cColor); } //+------------------------------------------------------------------+ //| Display Pattern formed at Bar 1 | //+------------------------------------------------------------------+ void DisplayPattern1(int iPattern, int iBar) { double dPadY, h,l; int iCandles, x, y; // determine number of candles found in pattern iCandles=StrToInteger(sPattern[iPattern][P_NUM]); // find position of highest price in the candle pattern y=ArrayMaximum(H,iCandles); // find position of lowest price in the candle pattern x=ArrayMinimum(L,iCandles); // convert pip values back to prices for drawing object on chart h=H[y]/(ERR_0+dPipsFactor); l=L[x]/(ERR_0+dPipsFactor); // calculate some padding between the candle pattern and the rectangular box that will hilite it dPadY=(PriceMaxVisible() - PriceMinVisible()) * MathPow(10, Digits) / 30 * Point; // Hilite the candles forming the pattern in coloured box ObjectCreate("CP_BOX",OBJ_RECTANGLE,0,Time[iBar+iCandles],h+dPadY,Time[iBar-1],l-dPadY); ObjectSet("CP_BOX",OBJPROP_COLOR,AlternateColorSingleCandle); // set background drawing flag for object, so as to only draw perimeter ObjectSet("CP_BOX",OBJPROP_BACK,false); } //+------------------------------------------------------------------+ //| DisplayPatterns() | //+------------------------------------------------------------------+ void DisplayPatterns(int iPattern, int iBar) { color cColor=ColorSingleCandle; datetime t; double dWndTop=WindowPriceMax(), dWndBot=WindowPriceMin(), dChartHeight=dWndTop-dWndBot, dPriceMax=PriceMaxVisible(), dPriceMin=PriceMinVisible(), dPadY, dY, h, l; string obj; int i, iLen, iCandles, x, y; if(dPriceMax > dWndTop) dWndTop=dPriceMax; if(dPriceMin < dWndBot) dWndBot=dPriceMin; // determine number of candles found in pattern iCandles=StrToInteger(sPattern[iPattern][P_NUM]); // find position of highest price in the candle pattern y=ArrayMaximum(H,iCandles); // find position of lowest price in the candle pattern x=ArrayMinimum(L,iCandles); // convert pip values back to prices for drawing object on chart h=H[y]/(ERR_0+dPipsFactor); l=L[x]/(ERR_0+dPipsFactor); // calculate some padding between the candle pattern and the rectangular box that will hilite it dPadY=(dPriceMax - dPriceMin) * MathPow(10, Digits) / 30 * Point; if(iCandles == 1) { bAlternateColorSingle=!bAlternateColorSingle; if(bAlternateColorSingle) cColor=AlternateColorSingleCandle; } else { bAlternateColorMulti=!bAlternateColorMulti; if(bAlternateColorMulti) cColor=AlternateColorMultiCandles; else cColor=ColorMultiCandles; sBoxObj="CP_B"+Time[iBar]; // Hilite the candles forming the pattern in colored box ObjectCreate(sBoxObj,OBJ_RECTANGLE,0,Time[iBar+iCandles],h+dPadY,Time[iBar-1],l-dPadY); ObjectSet(sBoxObj,OBJPROP_COLOR,cColor); // set background drawing flag for object, so as to only draw perimeter ObjectSet(sBoxObj,OBJPROP_BACK,false); } // calculate x and y co-ordinates of middle of the string to feed to MT4 ObjectCreate(), // only "Arial" font can be used for vertical text in MT4 at present. iLen=StrToInteger(sPattern[iPattern][P_LEN]); if(dPriceMax-High[iBar] > Low[iBar]-dPriceMin) dY=High[iBar]+NormalizeDouble(VerticalTextFontSize/V_TXT_FONT_SIZE*iLen*iScaleAdjustX/iScaleAdjustX_MN*dChartHeight/iScaleAdjustY/2, Digits); else dY=Low[iBar]-NormalizeDouble(VerticalTextFontSize/V_TXT_FONT_SIZE*iLen*iScaleAdjustX/iScaleAdjustX_MN*dChartHeight/iScaleAdjustY/2, Digits); obj="CP_"+Time[iBar]; // display the text vertically ObjectCreate(obj, OBJ_TEXT, 0, Time[iBar+VerticalTextAdjustX], dY); ObjectSetText(obj, sPattern[iPattern][P_NAM], VerticalTextFontSize, "Arial", cColor); ObjectSet(obj, OBJPROP_ANGLE, 90); // keep track of label text width for refresh by storing it in unused OBJECT PROPERTY TIME2 slot ObjectSet(obj, OBJPROP_TIME2, iLen); // verify that current single pattern is not on right side of just completed box (done on previous bar) if(iCandles == 1 && sBoxObj != "") { if(ObjectGet(sBoxObj,OBJPROP_TIME2) == Time[iBar]) { // keep track of box y co-ordinates for moving label on right // hand side out of box if possible for more readable output ObjectSet(obj, OBJPROP_PRICE2, ObjectGet(sBoxObj, OBJPROP_PRICE1)); ObjectSet(obj, OBJPROP_PRICE3, ObjectGet(sBoxObj, OBJPROP_PRICE2)); // move label on right border of just completed box (on previous bar) if required MoveLabel(obj, dWndTop, dWndBot, dPriceMax, dPriceMin); WindowRedraw(); // force redraw of current chart after moving of objects sBoxObj=""; } } else if(iCandles > 1) { // keep track of box y co-ordinates for moving labels out of box if possible for more readable output i=iBar; while(true) { obj="CP_"+Time[i]; if(ObjectFind(obj) < 0 || ObjectGet(obj,OBJPROP_TIME1) < Time[iBar+iCandles+VerticalTextAdjustX]) break; if(ObjectType(obj) == OBJ_TEXT) { if(h+dPadY > ObjectGet(obj,OBJPROP_PRICE2)) ObjectSet(obj, OBJPROP_PRICE2, h+dPadY); if(l-dPadY < ObjectGet(obj,OBJPROP_PRICE3) || ObjectGet(obj,OBJPROP_PRICE3) == 0) ObjectSet(obj, OBJPROP_PRICE3, l-dPadY); MoveLabel(obj, dWndTop, dWndBot, dPriceMax, dPriceMin); } i++; } WindowRedraw(); // force redraw of current chart after moving of objects } } //+------------------------------------------------------------------+ //| Function..: MoveLabel | //| Purpose...: Move labels out of box if possible (if present) or | //| above or below candles for more readable output. | //+------------------------------------------------------------------+ void MoveLabel(string obj, double dWndTop, double dWndBot, double dPriceMax, double dPriceMin) { int x =iBarShift(sSymbol,iPeriod,ObjectGet(obj,OBJPROP_TIME1))-VerticalTextAdjustX; double dHi =ObjectGet(obj,OBJPROP_PRICE2), dLo =ObjectGet(obj,OBJPROP_PRICE3), dLen=NormalizeDouble(VerticalTextFontSize/V_TXT_FONT_SIZE*ObjectGet(obj,OBJPROP_TIME2)* iScaleAdjustX/iScaleAdjustX_MN*(dWndTop-dWndBot)/iScaleAdjustY, Digits), dY; if(dHi != 0) { if(High[x] > dHi && High[x]+dLen < dPriceMax) dY=High[x]+dLen/2.0; else if(Low[x] < dLo && Low[x]-dLen > dPriceMin) dY=Low[x]-dLen/2.0; else if(dHi+dLen < dPriceMax) dY=dHi+dLen/2.0; else if(dLo-dLen > dPriceMin) dY=dLo-dLen/2.0; } if(dY == 0) { if(dPriceMax-High[x] > Low[x]-dPriceMin) dY=High[x]+dLen/2.0; else dY=Low[x]-dLen/2.0; } ObjectMove(obj,0,Time[x+VerticalTextAdjustX],dY); } //+------------------------------------------------------------------+ //| ObjectsDeletePrefixed | //+------------------------------------------------------------------+ void ObjectsDeletePrefixed(string sPrefix) { for(int i=ObjectsTotal()-1; i>=0; i--) { if(StringFind(ObjectName(i),sPrefix)==0) ObjectDelete(ObjectName(i)); } Comment(""); } //+------------------------------------------------------------------+ //| Candle Pattern | //+------------------------------------------------------------------+ int Pattern(int iBar) { double b, u, l; int x=1, y=1, i, iPos; //------------------------------------------------------------------ Candle sizes: if(dSize[0]==CALC_ALL) { // calculate average of all bars flag ArrayInitialize(dSize,0); x=2; y=iBars(sSymbol,iPeriod) - 2; } for(i=x; i <= y; i++) { // Candle Body size b=MathAbs(iClose(sSymbol,iPeriod,i)-iOpen(sSymbol,iPeriod,i))*dPipsFactor; if(b > 0) { dSize[CandleBodyCount]+=1; dSize[CandleBodyTotal]+=b; } // Upper Shadow size b=(iHigh(sSymbol,iPeriod,i)-MathMax(iClose(sSymbol,iPeriod,i),iOpen(sSymbol,iPeriod,i)))*dPipsFactor; if(b > 0) { dSize[UpperShadowCount]+=1; dSize[UpperShadowTotal]+=b; } // Bottom Shadow size b=(MathMin(iClose(sSymbol,iPeriod,i),iOpen(sSymbol,iPeriod,i))-iLow(sSymbol,iPeriod,i))*dPipsFactor; if(b > 0) { dSize[BottomShadowCount]+=1; dSize[BottomShadowTotal]+=b; } } // set Lower & Upper Thresholds of Candle Body if(dSize[CandleBodyCount] > 0) { // Candle Body Small (top threshold) dSize[SmallCandleBody]=dSize[CandleBodyTotal]*2/dSize[CandleBodyCount]*LT_FACTOR; // Candle Body Long (bottom threshold) dSize[LongCandleBody]=dSize[SmallCandleBody]*(1-LT_FACTOR)/LT_FACTOR; } // set Lower & Upper Thresholds of Upper Candle Shadows if(dSize[UpperShadowCount] > 0) { // Upper Shadow Small (top threshold) dSize[SmallUpperShadow]=dSize[UpperShadowTotal]*2/dSize[UpperShadowCount]*LT_FACTOR; // Upper Shadow Long (bottom threshold) dSize[LongUpperShadow]=dSize[SmallUpperShadow]*(1-LT_FACTOR)/LT_FACTOR; } // set Lower & Upper Thresholds of Lower Candle Shadows if(dSize[BottomShadowCount] > 0) { // Bottom Shadow Small (top threshold) dSize[SmallBottomShadow]=dSize[BottomShadowTotal]*2/dSize[BottomShadowCount]*LT_FACTOR; // Bottom Shadow Long (bottom threshold) dSize[LongBottomShadow]=dSize[SmallBottomShadow]*(1-LT_FACTOR)/LT_FACTOR; } // Determine what is "Very Near" for Candle Comparisons if(dSize[SmallCandleBody] > 30) iVeryNear=1; else iVeryNear=0; // state definition of "Very small" body if(dSize[SmallCandleBody] > 30) iVerySmallBody=1; else iVerySmallBody=0; //------------------------------------------------------------------ shuffle array elements down for(i=MAX_CANDLES-1; i>0; i--) { // by 1 and save re-calculating O[i]=O[i-1]; H[i]=H[i-1]; L[i]=L[i-1]; C[i]=C[i-1]; B[i]=B[i-1]; T[i]=T[i-1]; candle[i]=candle[i-1]; } //------------------------------------------------------------------ Load Prices converted to pips: if(candle[0]==CALC_ALL) y=MAX_CANDLES; // load all flag else y=1; for(i=0; i < y; i++) { O[i]=iOpen(sSymbol,iPeriod,iBar+i)*dPipsFactor; // Open H[i]=iHigh(sSymbol,iPeriod,iBar+i)*dPipsFactor; // High L[i]=iLow(sSymbol,iPeriod,iBar+i)*dPipsFactor; // Low C[i]=iClose(sSymbol,iPeriod,iBar+i)*dPipsFactor; // Close B[i]=MathMin(O[i],C[i]); // Bottom of candle body T[i]=MathMax(O[i],C[i]); // Top of candle body } /*------------------------------------------------------------------ Determine base candle code number: | H H=High of candle |u u=upper shadow size *-*-* T T=Top of candle body Max(O, C) O=Open of candle, C=Close of candle | |b b=candle body size *-*-* B B=Bottom of candle body Min(O, C) |l l=lower shadow size | L L=Low of candle */ // candle body size b=T[0]-B[0]; // upper shadow size u=H[0]-T[0]; // lower shadow size l=B[0]-L[0]; /* Determine binary code for each candle: | Bit 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | *-------------------+--------+---*---*---+-------*------+------*-------* | Candle Check Type | Colour | Body | Upper Shadow | Lower Shadow | */ // bit 8: two different checks are made to determine candle: // when bit8=0 then b/u/l (body, upper shadow or lower shadow) are defined by size & variable x is used, // when bit8=1 then b is defined by size, u & l are defined by comparison codes & variable y is used y=256; // bit 7: colour of the candle: 0=black/Doji, 1=white if(C[0] > O[0]) x=128; else x=0; // bits 6-4: candle body code: 000=No body, 001=Very small, 010=Small, 011=Normal, 100=Long if(b >= dSize[LongCandleBody]) x+=64; else if(b >= dSize[SmallCandleBody]) x+=48; else if(b > iVerySmallBody) x+=32; else if(b > 0) x+=16; // bits 3-2: upper shadow to Body relation: 01: 0 < u <= b, 10: b < u < 2b, 11: u >= 2b if(u >= 2*b) y+=12; else if(u > b) y+= 8; else if(u > 0) y+= 4; // bits 1-0: lower shadow to Body relation: 01: 0 < l <= b, 10: b < l < 2b, 11: l >= 2b if(l >= 2*b) y+=3; else if(l > b) y+=2; else if(l > 0) y+=1; // check if candle with bit8=1 matches iPos=ArrayBsearch(iBaseCandle,x+y); if(iBaseCandle[iPos][0] != x+y) { // bits 3-2: upper shadow size: 00=No shadow, 01=Small, 10=Normal, 11=Long if(u >= dSize[LongUpperShadow]) x+=12; else if(u >= dSize[SmallUpperShadow]) x+= 8; else if(u > 0) x+= 4; // bits 1-0: lower shadow size: 00=No shadow, 01=Small, 10=Normal, 11=Long if(l >= dSize[LongBottomShadow]) x+=3; else if(l >= dSize[SmallBottomShadow]) x+=2; else if(l > 0) x+=1; // check if candle with bit8=0 matches iPos=ArrayBsearch(iBaseCandle,x); if(iBaseCandle[iPos][0] != x) { candle[0]=TT_NO_PATTERN; return(TT_NO_PATTERN); } } candle[0]=iBaseCandle[iPos][1]; //------------------------------------------------------------------ Determine trend: TrendUp=(iMA(sSymbol,iPeriod,TrendMA_Period,0,MODE_SMA,PRICE_CLOSE,iBar)- iMA(sSymbol,iPeriod,TrendMA_Period,0,MODE_SMA,PRICE_CLOSE,iBar+TrendMA_Shift)>0); TrendDn=!TrendUp; //------------------------------------------------------------------ Candle pattern: switch(candle[0]) { case SmallBlackCandle: // A // Bullish Homing Pigeon (2 candles) if(TrendDn && (candle[1]==LongBlackCandle) && (B[1]<B[0]) && (T[1]>T[0])) return(65); // Bearish Harami (2 candles) if(TrendUp && (candle[1]==LongWhiteCandle) && (T[1]>T[0]) && (B[1]<B[0])) return(36); // Small Black Candle (1 candle) return(9); case SmallWhiteCandle: // L if(TrendDn) { // Bullish Unique 3 River Bottom (3 candles) if((candle[2]==LongBlackCandle) && (candle[1]==BlackHammerOrHangingMan) && (L[1]<L[2]) && (T[1]<T[2]) && (B[1]>B[2]) && (T[0]<B[1])) return(71); // Bullish Harami (2 candles) if((candle[1]==LongBlackCandle) && (T[1]>T[0]) && (B[1]<B[0])) return(77); // Bearish In Neck (2 candles) if((candle[1]==LongBlackCandle) && (T[0]==B[1] || T[0]<=B[1]+iVeryNear)) return(38); // Bearish On Neck (2 candles) if((candle[1]==LongBlackCandle) && (T[0]==L[1] || T[0]==L[1]-iVeryNear)) return(39); } // Bearish Deliberation (3 candles) if(TrendUp && (candle[2]==LongWhiteCandle) && (candle[1]==LongWhiteCandle) && (T[1]>T[2]) && (B[0]>=T[1])) return(29); // Small White Candle (1 candle) return(8); case BlackCandle: // D if(TrendUp) { // Bullish Upside Gap 3 Methods (3 candles) if((candle[2]==LongWhiteCandle) && (candle[1]==LongWhiteCandle) && (T[2]<B[1]) && (O[0]<T[1]) && (O[0]>B[1]) && (B[0]<T[2]) && (B[0]>B[2])) return(81); // Bullish Upside Tasuki Gap (3 candles) if((candle[2]==LongWhiteCandle) && (candle[1]==LongWhiteCandle) && (T[2]<B[1]) && (O[0]<T[1]) && (O[0]>B[1]) && (B[0]<B[1]) && (B[0]>B[2])) return(82); // Bearish Abandoned Baby (3 candles) if((candle[2]==LongWhiteCandle) && (candle[1]==Doji || candle[1]==DojiSN || candle[1]==DojiSNL) && (H[2]<L[1]) && (L[1]>T[0])) return(14); // Bearish Evening Star (3 candles) if((candle[2]==LongWhiteCandle) && (candle[1]==SmallBlackCandle || candle[1]==SmallWhiteCandle) && (T[2]<B[1]) && (T[0]<B[1]) && (C[0]<T[2]) && (C[0]>B[2])) return(15); // Bearish Evening Doji Star (3 candles) if((candle[2]==WhiteCandle) && (candle[1]==Doji || candle[1]==DojiSN || candle[1]==DojiSNL) && (T[2]<B[1]) && (B[1]>T[0]) && (B[0]<T[2]) && (B[0]>B[2])) return(16); // Bearish 3 Inside Down (3 candles) if((candle[2]==LongWhiteCandle) && (candle[1]==SmallBlackCandle) && (T[2]>T[1]) && (B[2]<B[1]) && (B[0]<B[2])) return(18); // Bearish 3 Outside Down (3 candles) if((candle[2]==Doji || candle[2]==DojiSN || candle[2]==DojiSNL || candle[2]==SmallWhiteCandle) && (candle[1]==LongBlackCandle) && (T[1]>T[2]) && (B[1]<B[2]) && (B[0]<B[1])) return(19); // Bearish Upside Gap 2 Crows (3 candles) if((candle[2]==LongWhiteCandle) && (candle[1]==BlackCandle) && (B[1]>T[2]) && (T[0]>T[1]) && (B[0]<B[1]) && (B[0]>T[2])) return(20); // Bearish 2 Crows (3 candles) if((candle[2]==LongWhiteCandle) && (candle[1]==BlackCandle) && (B[1]>T[2]) && (T[0]<T[1]) && (T[0]>B[1]) && (B[0]<T[2]) && (B[0]>B[2])) return(31); // Bearish Dark Cloud Cover (2 candles) if((candle[1]==LongWhiteCandle) && (T[1]<T[0]) && (B[0]<(T[1]+B[1])/2) && (B[0]>B[1])) return(12); } // Bullish Matching Low (2 candles) if(TrendDn && (candle[1]==LongBlackCandle) && ((B[0]==B[1]-iVeryNear) || (B[0]==B[1]) || (B[0]==B[1]+iVeryNear))) return(66); // Black Candle (1 candle) return(11); case WhiteCandle: // N if(TrendDn) { // Bullish Ladder Bottom (5 candles) if((candle[4]==LongBlackCandle) && (candle[3]==LongBlackCandle) && (candle[2]==LongBlackCandle) && (candle[1]==BlackCandleDay4LadderBottom) && (O[4]>O[3]) && (C[4]>C[3]) && (O[3]>O[2]) && (C[3]>C[2]) && (B[2]>B[1]) && (T[1]<B[0])) return(73); // Bullish Abandoned Baby (3 candles) if((candle[2]==LongBlackCandle) && (O[1]==C[1]) && (L[2]>H[1]) && (H[1]<L[0])) return(52); // Bullish Morning Doji Star (3 candles) if((candle[2]==LongBlackCandle) && (O[1]==C[1]) && (B[2]>T[1]) && (T[1]<B[0]) && (T[0]>B[2]) && (T[0]<T[2])) return(53); // Bullish Morning Star (3 candles) if((candle[2]==LongBlackCandle) && ((candle[1]==SmallBlackCandle) || (candle[1]==SmallWhiteCandle)) && (B[2]>T[1]) && (T[1]<B[0]) && (T[0]>B[2]) && (T[0]<T[2])) return(54); // Bullish 3 Inside Up (3 candles) if((candle[2]==LongBlackCandle) && (candle[1]==SmallWhiteCandle) && (B[2]<B[1]) && (T[2]>T[1]) && (B[1]<B[0]) && (T[0]>T[2])) return(55); // Bullish 3 Outside Up (3 candles) if(((candle[2]==Doji) || (candle[2]==DojiSN) || (candle[2]==DojiSNL) || (candle[2]==SmallBlackCandle)) && (candle[1]==LongWhiteCandle) && (B[2]>B[1]) && (T[2]<T[1]) && (T[0]>T[1])) return(56); // Bearish Downside Gap 3 Methods (3 candles) if((candle[2]==LongBlackCandle) && (candle[1]==LongBlackCandle) && (T[1]<B[2]) && (T[0]>B[2]) && (B[0]<T[1])) return(40); // Bearish Downside Tasuki Gap (3 candles) if((candle[2]==LongBlackCandle) && (candle[1]==LongBlackCandle) && (B[2]>T[1]) && (B[0]<T[1] && B[0]>B[1]) && (T[0]>T[1] && T[0]<B[2])) return(41); // Bearish Side By Side White Lines (3 candles) if((candle[2]==BlackCandle) && (candle[1]==WhiteCandle) && (B[2]>T[1]) && (B[0]<=B[1]+iVeryNear && B[0]>=B[1]-iVeryNear)) return(42); // Bearish Thrusting (2 candles) if((candle[1]==BlackCandle || candle[1]==LongBlackCandle) && (B[0]<B[1]) && (T[0]>B[1] && T[0]<(T[1]+B[1])/2)) return(44); } if(TrendUp) { // Bullish Mat Hold (5 candles) if((candle[4]==LongWhiteCandle) && ((candle[3]==SmallBlackCandle) || (candle[3]==SmallWhiteCandle)) && ((candle[2]==SmallBlackCandle) || (candle[2]==SmallWhiteCandle)) && ((candle[1]==SmallBlackCandle) || (candle[1]==SmallWhiteCandle)) && (T[4]<B[3]) && (B[4]<B[2]) && (B[4]<B[1]) && (B[1]<B[0]) && (B[3]>B[2]) && (B[2]>B[1]) && (H[4]<H[0]) && (H[3]<H[0]) && (H[2]<H[0]) && (H[1]<H[0])) return(79); // Bullish Side By Side White Lines (3 candles) if((candle[2]==WhiteCandle) && (candle[1]==WhiteCandle) && (T[2]<B[1]) && (T[1]==T[0]) && (B[1]==B[0])) return(78); } // White Candle (1 candle) return(10); case LongBlackCandle: // K if(TrendUp) { // Bearish Breakaway (5 candles) if((candle[4]==LongWhiteCandle) && (candle[3]==WhiteCandle) && (candle[2]==BlackCandle || candle[2]==WhiteCandle) && (candle[1]==WhiteCandle) && (B[3]>T[4]) && (T[2]>T[3]) && (T[1]>T[2]) && (B[0]<B[3]) && (B[0]>T[4])) return(32); // Bullish 3 Line Strike (4 candles) if((candle[3]==LongWhiteCandle) && (candle[2]==LongWhiteCandle) && (candle[1]==LongWhiteCandle) && (T[3]<T[2]) && (T[2]<T[1]) && (T[1]<T[0]) && (B[0]<B[3])) return(84); // Bearish 3 Black Crows (3 candles) if((candle[2]==LongBlackCandle) && (candle[1]==LongBlackCandle) && (B[1]<B[2]) && (B[0]<B[1]) && (T[1]<T[2]) && (T[1]>B[2]) && (T[0]<T[1]) && (T[0]>B[1])) return(17); // Bearish Dark Cloud Cover (2 candles) if((candle[1]==LongWhiteCandle) && (T[1]<T[0]) && (B[0]<(T[1]+B[1])/2) && (B[0]>B[1])) return(12); // Bearish Engulfing (2 candles) if((candle[1]==Doji || candle[1]==DojiSN || candle[1]==DojiSNL || candle[1]==SmallWhiteCandle) && (T[0]>T[1]) && (B[0]<B[1])) return(23); // Bearish Meeting Lines (2 candles) if((candle[1]==LongWhiteCandle) && (B[0]<=T[1]+iVeryNear && B[0]>=T[1]-iVeryNear)) return(27); } // Bearish Falling 3 Methods (5 candles) if(TrendDn && (candle[4]==LongBlackCandle) && (candle[3]==SmallBlackCandle || candle[3]==SmallWhiteCandle) && (candle[2]==SmallBlackCandle || candle[2]==SmallWhiteCandle) && (candle[1]==SmallBlackCandle || candle[1]==SmallWhiteCandle) && (T[3]>B[4]) && (T[3]<T[4]) && (T[2]>B[4]) && (T[2]<T[4]) && (T[1]>B[4]) && (T[1]<T[4]) && (T[2]>T[3]) && (T[1]>T[2]) && (T[0]<T[1]) && (T[0]>B[1]) && (B[0]<B[4])) return(37); // Long Black Candle (1 candle) return(46); case LongWhiteCandle: // R if(TrendDn) { // Bullish Breakaway (5 candles) if((candle[4]==LongBlackCandle) && (candle[3]==BlackCandle) && ((candle[2]==BlackCandle) || (candle[2]==WhiteCandle)) && (candle[1]==BlackCandle) && (B[4]>T[3]) && (T[3]>T[2]) && (B[3]>B[2]) && (T[2]>T[1]) && (B[2]>B[1]) && (B[1]<B[0]) && (T[0]>T[3]) && (T[0]<B[4])) return(72); // Bearish 3 Line Strike (4 candles) if((candle[3]==LongBlackCandle) && (candle[2]==LongBlackCandle) && (candle[1]==LongBlackCandle) && (B[3]>B[2]) && (B[2]>B[1]) && (B[1]>B[0]) && (T[0]>T[3])) return(45); // Bullish 3 White Soldiers (3 candles) if((candle[2]==LongWhiteCandle) && (candle[1]==LongWhiteCandle) && (T[2]<T[1]) && (B[2]<B[1]) && (T[2]>B[1]) && (T[1]<T[0]) && (B[1]<B[0]) && (T[1]>B[0])) return(57); // Bullish Piercing Line (2 candles) if((candle[1]==LongBlackCandle) && (B[0]<L[1]) && (((B[1]+T[1])/2 < T[0]) && (T[0] < T[1]))) return(50); // Bullish Engulfing (2 candles) if(((candle[1]==Doji) || (candle[1]==DojiSN) || (candle[1]==DojiSNL) || (candle[1]==SmallBlackCandle)) && (B[1]>B[0]) && (T[1]<T[0])) return(61); // Bullish Meeting Lines (2 candles) if((candle[1]==LongBlackCandle) && ((T[0]==B[1]-iVeryNear) || (T[0]==B[1]) || (T[0]==B[1]+iVeryNear))) return(67); // Bearish Thrusting (2 candles) if((candle[1]==BlackCandle || candle[1]==LongBlackCandle) && (B[0]<B[1]) && (T[0]>B[1] && T[0]<(T[1]+B[1])/2)) return(44); } if(TrendUp) { // Bullish Rising 3 Methods (5 candles) if((candle[4]==LongWhiteCandle) && ((candle[3]==SmallBlackCandle) || (candle[3]==SmallWhiteCandle)) && ((candle[2]==SmallBlackCandle) || (candle[2]==SmallWhiteCandle)) && ((candle[1]==SmallBlackCandle) || (candle[1]==SmallWhiteCandle)) && (L[4]<L[3]) && (L[4]<L[2]) && (L[4]<L[1]) && (B[3]>B[2]) && (B[2]>B[1]) && (B[1]<B[0]) && (T[4]<T[0]) && (T[3]<T[2]) && (T[2]<T[0]) && (T[1]<T[0])) return(80); // Bearish Advance Block (3 candles) if((candle[2]==LongWhiteCandle) && (candle[1]==LongWhiteCandle) && (T[1]>T[2]) && (T[0]>T[1]) && (B[1]>B[2]) && (B[1]<T[2]) && (B[0]>B[1]) && (B[0]<T[1]) && ((T[2]-B[2])>(T[1]-B[1])) && ((T[1]-B[1])>(T[0]-B[0]))) return(28); } // Long White Candle (1 candle) return(85); case FourPriceDoji: // 0 return(0); case Umbrella_1: // 1 // Bullish Dragonfly Doji (1 candle) if(TrendDn) return(59); // Bearish Dragonfly Doji (1 candle) if(TrendUp) return(21); // Umbrella (1 candle) return(3); case Umbrella_2: // 2 // Umbrella (1 candle) return(3); case Doji: // 3 case DojiSN: // 4 if(TrendDn) { // Bullish Tri Star (3 candles) if(((candle[2]==Doji) || (candle[2]==DojiSN) || (candle[2]==DojiSNL)) && ((candle[1]==Doji) || (candle[1]==DojiSN)) && (T[1]<B[2]) && (T[1]<B[0])) return(70); // Bullish Harami Cross (2 candles) if((candle[1]==LongBlackCandle) && (B[1]<B[0]) && (T[1]>T[0])) return(64); // Bullish Doji Star (2 candles) if((candle[0]!=DojiSNL) && (candle[1]==LongBlackCandle) && (B[1]>T[0])) return(63); } if(TrendUp) { // Bearish Tri Star (3 candles) if((candle[2]==Doji || candle[2]==DojiSN || candle[2]==DojiSNL) && (candle[1]==Doji || candle[1]==DojiSN || candle[1]==DojiSNL) && (B[1]>T[2]) && (B[1]>T[0])) return(30); // Bearish Doji Star (2 candles) if((candle[1]==LongWhiteCandle) && (B[0]>T[1])) return(25); // Bearish Harami Cross (2 candles) if((candle[1]==LongWhiteCandle) && (T[1]>T[0]) && (B[1]<B[0])) return(26); } // Doji (1 candle) return(5); case DojiSNL: // 5 if(TrendDn) { // Bullish Tri Star (3 candles) if(((candle[2]==Doji) || (candle[2]==DojiSN) || (candle[2]==DojiSNL)) && ((candle[1]==Doji) || (candle[1]==DojiSN)) && (T[1]<B[2]) && (T[1]<B[0])) return(70); // Bullish Harami Cross (2 candles) if((candle[1]==LongBlackCandle) && (B[1]<B[0]) && (T[1]>T[0])) return(64); // Bullish Doji Star (2 candles) if((candle[0]!=DojiSNL) && (candle[1]==LongBlackCandle) && (B[1]>T[0])) return(63); } if(TrendUp) { // Bearish Tri Star (3 candles) if((candle[2]==Doji || candle[2]==DojiSN || candle[2]==DojiSNL) && (candle[1]==Doji || candle[1]==DojiSN || candle[1]==DojiSNL) && (B[1]>T[2]) && (B[1]>T[0])) return(30); // Bearish Harami Cross (2 candles) if((candle[1]==LongWhiteCandle) && (T[1]>T[0]) && (B[1]<B[0])) return(26); } // Doji (1 candle) return(5); case InvertedUmbrella_6: // 6 // Bullish Gravestone Doji (2 candles) if(TrendDn && (candle[1]==BlackCandle) && (B[2]>B[1]) && (T[1]>T[0])) return(62); // Bearish Gravestone Doji (2 candles) if(TrendUp && (candle[1]==WhiteCandle) && (T[1]>T[2]) && (B[0]>T[1])) return(24); // Inverted Umbrella (1 candle) return(4); case InvertedUmbrella_U: // U case InvertedUmbrella_V: // V // Bullish Gravestone Doji (2 candles) if(TrendDn && (candle[1]==BlackCandle) && (B[2]>B[1]) && (T[1]>T[0])) return(62); break; case InvertedUmbrella_7: // 7 // Inverted Umbrella (1 candle) return(4); case LongLeggedDoji_8: // 8 case LongLeggedDoji_9: // 9 // Bullish Long Legged Doji (1 candle) if(TrendDn && (T[0]<B[1])) return(60); // Bearish Long Legged Doji (1 candle) if(TrendUp && (B[0]>T[1])) return(22); // Long Legged Doji (1 candle) return(2); case HighWave: // B return(1); case BlackSpinningTop: // C return(7); case BlackCandleDay4LadderBottom: // E case BlackDay3ConcealBabySwallow: // F // Black Candle (1 candle) return(11); case BlackMarubozu: // G // Bullish Concealing Baby Swallow (4 candles) if(TrendDn && (candle[3]==BlackMarubozu) && (candle[2]==BlackMarubozu) && (candle[1]==BlackDay3ConcealBabySwallow) && (B[3]>B[2]) && (B[2]>T[1]) && (H[1]>B[2]) && (H[1]<T[2]) && (B[0]<L[1]) && (T[0]>H[1])) return(58); // Bullish 3 Star in the South (3 candles) if(TrendDn && (candle[2]==BlackOpeningMarubozuLongshadow) && (candle[1]==BlackOpeningMarubozu) && (O[1]>C[2]) && (L[1]>L[2]) && (H[0]<H[1]) && (L[0]>L[1])) return(69); // Bearish Kicking Pattern (2 candles) if((candle[1]==WhiteMarubozu) && (B[1]>T[0])) return(13); // Black Marubozu (1 candle) return(47); case BlackOpeningMarubozu: // H case BlackOpeningMarubozuLongshadow: // I // Bearish Seperating Lines (2 candles) if(TrendDn && (candle[1]==LongWhiteCandle) && (T[0]<=B[1]+iVeryNear && T[0]>=B[1]-iVeryNear)) return(43); // Bearish Belt Hold (1 candle) if(TrendUp && (B[0]>T[1])) return(33); // Black Opening Marubozu (1 candle) return(49); case BlackClosingMarubozu: // J // Bullish Stick Sandwich (3 candles) if(TrendDn && (candle[2]==BlackClosingMarubozu) && (candle[1]==WhiteCandle) && (B[2]<B[1]) && (B[0]==B[2])) return(68); // Black Closing Marubozu (1 candle) return(48); case WhiteSpinningTop: // M // Bearish Deliberation (3 candles) if(TrendUp && (candle[2]==LongWhiteCandle) && (candle[1]==LongWhiteCandle) && (T[1]>T[2]) && (B[0]>=T[1])) return(29); // White Spinning Top (1 candle) return(6); case WhiteMarubozu: // O // Bullish Kicking Pattern (2 candles) if((candle[1]==BlackMarubozu) && (H[1]<L[0])) return(51); // White Marubozu (1 candle) return(86); case WhiteClosingMarubozu: // P // White Closing Marubozu (1 candle) return(87); case WhiteOpeningMarubozu: // Q // Bullish Seperating Lines (2 candles) if(TrendUp && (candle[1]==LongBlackCandle) && (B[0]<=T[1]+iVeryNear && B[0]>=T[1]-iVeryNear)) return(83); // Bullish Belt Hold (1 candle) if(TrendDn && (B[1]>T[0])) return(74); // White Opening Marubozu (1 candle) return(88); case BlackHammerOrHangingMan: // S case WhiteHammerOrHangingMan: // T // Bullish Hammer (1 candle) if(TrendDn && (B[1]>T[0])) return(75); // Bearish Hanging Man (1 candle) if(TrendUp && (B[0]>T[1])) return(34); break; case BlackInvertedHammerOrStar: // W case WhiteInvertedHammerOrStar: // X // Bullish Inverted Hammer (2 candles) if(TrendDn && (candle[1]==BlackCandle) && (B[1]>T[0])) return(76); // Bearish Shooting Star (2 candles) if(TrendUp && (candle[1]==WhiteCandle) && (B[0]>T[1])) return(35); break; default: break; } return(TT_NO_PATTERN); } //+------------------------------------------------------------------+ //| PatternConfirm(iPreviousPatternNumber) | //+------------------------------------------------------------------+ void PatternConfirm(int x) { string sMsg=""; // check if previous pattern trend forecast can be confirmed if(ConfirmPattern && (x != TT_NO_PATTERN) && (sPattern[x][P_DISPLAY] == "1")) { if(sPattern[x][P_CHK] == "0") sMsg=M_NULL; // check 1: Lower Close else if(sPattern[x][P_CHK] == "1" && (C[0] < C[1])) sMsg=M_DN; // check 2: Black Candle or Lower Close else if(sPattern[x][P_CHK] == "2" && (C[0] < O[0] || C[0] < C[1])) sMsg=M_DN; //check 3: Black Candle && Lower Close else if(sPattern[x][P_CHK] == "3" && (C[0] < O[0] && C[0] < C[1])) sMsg=M_DN; //check 4: Lower Open OR Black Candle && Lower Close else if(sPattern[x][P_CHK] == "4" && (O[0] < O[1] || (C[0] < O[0] && C[0] < C[1]))) sMsg=M_DN; // check 5: White Candle or Higher Close else if(sPattern[x][P_CHK] == "5" && (C[0] > O[0] || C[0] > C[1])) sMsg=M_UP; // check 6: White Candle && Higher Close else if(sPattern[x][P_CHK] == "6" && (C[0] > O[0] && C[0] > C[1])) sMsg=M_UP; // check 7: Higher Open OR White Candle && Higher Close else if(sPattern[x][P_CHK] == "7" && (O[0] > O[1] || (C[0] > O[0] && C[0] > C[1]))) sMsg=M_UP; // check 8: Opposite move to the one which occured on the previous day, trend up then reverse down else if(sPattern[x][P_CHK] == "8" && (C[1] > O[1] && C[0] < O[0])) sMsg=M_REV_DN; // check 8: Opposite move to the one which occured on the previous day, trend down then reverse up else if(sPattern[x][P_CHK] == "8" && (C[1] < O[1] && C[0] > O[0])) sMsg=M_REV_UP; else sMsg=M_NULL; if((sMsg != M_NULL) && (MaxBarsToScanForPatterns == 1)) { DisplayLabelObject("CP_CONFIRM_PRIOR_TREND", sPRV, ColorText); DisplayLabelObject("CP_CONFIRM_RELEVANCE" , sREE, ColorText); } if(sMsg != M_NULL && AudioON) gSpeak(StringConcatenate(sAudio,sPattern[iPattern][P_NAM]," ",sMsg)); } } //+------------------------------------------------------------------+ //| PriceMaxVisible() | //+------------------------------------------------------------------+ double PriceMaxVisible() { int iCount=WindowBarsPerChart(), iStart=MathMax(WindowFirstVisibleBar()-iCount,1), iPriceMax=iHighest(NULL,0,MODE_HIGH,iCount,iStart); return(High[iPriceMax]); } //+------------------------------------------------------------------+ //| PriceMinVisible() | //+------------------------------------------------------------------+ double PriceMinVisible() { int iCount=WindowBarsPerChart(), iStart=MathMax(WindowFirstVisibleBar()-iCount,1), iPriceMin=iLowest(NULL,0,MODE_LOW,iCount,iStart); return(Low[iPriceMin]); } //+------------------------------------------------------------------+ //| StringArrayLoad() | //+------------------------------------------------------------------+ int StringArrayLoad(string sFile, string& A[][], int iColumns) { int handle = FileOpen(sFile, FILE_CSV|FILE_READ, ";"), i, iStart, iPos; //---- if(handle < 1) { Alert("File:", sFile, " error "+GetLastError()); return(-1); } string sLine; int iRows = ArrayRange(A,0), iLinesRead = 0; //---- while(FileIsEnding(handle) == false) { sLine = FileReadString(handle); iStart = StringLen(sLine); //---- if(iStart < 1 || StringSubstr(sLine,0,2) == "//") continue; // empty strings or comment lines dropped //---- if(iLinesRead >= iRows) { if(ArrayResize(A,iRows+1) == 0 ) { Alert("StringArrayLoad() error ", GetLastError()); return(-1); } iRows += 1; } //---- if(StringFind(sLine, ",,", 0) >= 0 || StringSubstr(sLine, iStart - 1, 1) == ",") { Alert("File:", sFile, " Line:", iLinesRead, " NULL value"); break; } sLine = sLine + ","; iStart = 0; //---- for(i = 0; i < iColumns; i++) { iPos = StringFind(sLine, ",", iStart); A[iLinesRead][i] = StringSubstr(sLine, iStart, iPos - iStart); iStart = iPos + 1; } iLinesRead++; } FileClose(handle); return (iLinesRead); } //+------------------------------------------------------------------+
Sample
Analysis
Market Information Used:
Series array that contains open time of each bar
Series array that contains the highest prices of each bar
Series array that contains the lowest prices of each bar
Series array that contains open prices of each bar
Series array that contains close prices for each bar
Indicator Curves created:
Indicators Used:
Moving average indicator
Custom Indicators Used:
Order Management characteristics:
Other Features:
It issuies visual alerts to the screen
Uses files from the file system
It reads information from a file