//+------------------------------------------------------------------+ //| SignalIchimoku.mqh | //| AnimateDread | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "..\Expert\ExpertSignalCustom.mqh" // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Signals of indicator 'Ichimoku Kinko Hyo' | //| Type=SignalAdvanced | //| Name=Ichimoku | //| ShortName=Ichimoku | //| Class=CSignalIchimoku | //| Page=signal_ichimoku | //| Parameter=PeriodTenkan,int,9,Tenkan-sen period | //| Parameter=PeriodKijun,int,26,Kijun-sen period | //| Parameter=PeriodSenkou,int,52,Senkou Span B period | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| Class CSignalIchimoku. | //| Purpose: Class of generator of trade signals based on the | //| 'Ichimoku Kinko Hyo' indicator. | //| Is derived from the CExpertSignalCustom class. | //| | //| Written from scratch - unlike MA/RSI/MACD there is NO Ichimoku | //| signal module in the MQL5 standard library to port, so the | //| twelve market models below encode the conventional Ichimoku | //| readings directly rather than inheriting a stock pattern set. | //| Between them they cover the full canonical repertoire: | //| | //| - Tenkan/Kijun cross, GRADED the classic three ways by where | //| the cross happens relative to the Kumo: below it = weak | //| (model 3), inside it = neutral (model 5), above it = strong | //| (model 10), mirrored for shorts. Grading is the point of the | //| TK cross in Ichimoku doctrine - an ungraded cross treats a | //| counter-trend cross under the cloud as if it were a trend | //| continuation above it, which is precisely the trade the | //| method tells you to stand down on. | //| - Kumo breakout (model 8), and the same breakout through a | //| THIN cloud (model 9) - cloud thickness is Ichimoku's own | //| measure of how much support/resistance is actually there, so | //| a break through a thin Kumo is the higher-quality one. | //| - Chikou Span confirmation (model 2): the lagging span clear | //| of BOTH the price 26 periods back and the cloud at that | //| point, which is the full form of the confirmation rather | //| than the price-only shorthand. | //| - Kijun-sen cross (model 6) and the Kijun-sen bounce (model 7) | //| - the pull-back entry that the base line's "magnet" effect | //| produces, which is why that model also requires the line to | //| be holding its level rather than sloping against the trade. | //| - Kumo twist (model 4): Senkou A actually CROSSING Senkou B | //| in the projected cloud, as distinct from the cloud merely | //| BEING one colour or the other (model 1). | //| - Price vs the cloud (model 0), the standing trend bias every | //| other reading is confirmed against. | //| - Sanyaku Kouten / Sanyaku Gyakuten (model 11), the "three | //| roles" alignment - Tenkan above Kijun, Chikou clear of past | //| price, price clear of the cloud, all at once. Ichimoku's own | //| strongest signal, hence the top weight. | //| | //| Pattern numbering is ordered by conviction, weakest first, so | //| the highest-numbered match wins - the same convention the stock | //| wizard signals use (see LongCondition() below). Weights follow | //| the standard library's own scheme: the confirming STATES that | //| hold across long stretches of bars (models 0-2) plus the weak | //| cross grade (model 3) all sit at the 10 floor that CSignalMA, | //| CSignalRSI and CSignalMACD give their Pattern_0, and the event | //| models are spread across 30-100 by how much the method itself | //| trusts each. Nothing between 10 and 30 - a reading either | //| corroborates or it triggers. | //| | //| LOOKAHEAD - the single thing to get right in this class. MT5's | //| iIchimoku does NOT pre-shift its buffers; it stores raw | //| per-bar values and shifts only the DRAWING (Ichimoku.mq5: | //| PlotIndexSetInteger(2,PLOT_SHIFT,InpKijun) for the Span A/B | //| cloud plot, and (3,PLOT_SHIFT,-InpKijun) for Chikou). In | //| series (reverse) indexing that means: | //| - SenkouSpanA/B(i) is computed FROM bar i and is DRAWN at bar | //| i-Kijun, i.e. Kijun bars into the future. So the cloud | //| actually sitting under bar `idx` is SenkouSpanA/B(idx+Kijun) | //| - derived from bar idx+Kijun and older, hence strictly past | //| data. That +Kijun offset is what CloudTop()/CloudBottom() | //| below exist to apply; reading SenkouSpanA/B(idx) as "the | //| cloud here" is the classic Ichimoku backtest bug. | //| - SenkouSpanA/B(idx) with NO offset is legitimate as the | //| PROJECTED cloud (what the chart already draws ahead of the | //| current bar) - it is computed from bar idx, so a live bar | //| really does know it. Models 2 and 3 use it in exactly that | //| sense, and nothing here ever indexes BELOW idx. | //| - ChinkouSpan(i) is just Close(i), drawn at i+Kijun. The | //| Chikou value plotted AT bar idx would be Close(idx-Kijun) - | //| a bar Kijun into the FUTURE - so it is never read. The | //| lookahead-free statement of the same reading is "is this | //| bar's close clear of what price was Kijun bars ago", i.e. | //| Close(idx) vs Close(idx+Kijun), and of the cloud that was | //| plotted THERE, i.e. the spans at idx+2*Kijun. That is what | //| model 9 does, and why CiIchimoku::ChinkouSpan() is | //| deliberately never called anywhere in this file. | //+------------------------------------------------------------------+ class CSignalIchimoku : public CExpertSignalCustom { protected: CiIchimoku m_ichimoku; // object-indicator //--- adjusted parameters int m_period_tenkan; // the "Tenkan-sen period" parameter of the indicator int m_period_kijun; // the "Kijun-sen period" parameter of the indicator int m_period_senkou; // the "Senkou Span B period" parameter of the indicator //--- "weights" of market models (0-100), numbered weakest-to-strongest so the last match in the //--- if-chain is always the highest-conviction one (see the class comment). Models 0-3 are the //--- CONFIRMING readings and all carry the standard-library floor weight of 10: each describes a //--- standing STATE that is true across long stretches of bars rather than an event, so any of them //--- alone must never approach the Min vote to open gate - they exist to corroborate an event model //--- below, exactly as Pattern_0 does in CSignalMA/CSignalRSI/CSignalMACD. Models 4-11 are events //--- (or, for 11, the full three-role confluence) and are spread across the same 30-100 band the //--- standard library uses, ranked by how much the method itself trusts each one. int m_pattern_0; // model 0 "price is on the necessary side of the cloud" int m_pattern_1; // model 1 "the projected cloud is the necessary colour" int m_pattern_2; // model 2 "Chikou Span confirmation (clear of past price AND cloud)" int m_pattern_3; // model 3 "TK cross on the WRONG side of the cloud (weak grade)" int m_pattern_4; // model 4 "Kumo twist - projected Senkou A crossed Senkou B" int m_pattern_5; // model 5 "TK cross INSIDE the cloud (neutral grade)" int m_pattern_6; // model 6 "price crossed Kijun-sen in the necessary direction" int m_pattern_7; // model 7 "Kijun-sen bounce - pull-back to the base line, resumed" int m_pattern_8; // model 8 "Kumo breakout" int m_pattern_9; // model 9 "Kumo breakout through a THIN cloud" int m_pattern_10; // model 10 "TK cross on the RIGHT side of the cloud (strong grade)" int m_pattern_11; // model 11 "Sanyaku Kouten/Gyakuten - all three roles aligned" public: CSignalIchimoku(void); ~CSignalIchimoku(void); //--- methods of setting adjustable parameters void PeriodTenkan(int value) { m_period_tenkan = value; } void PeriodKijun(int value) { m_period_kijun = value; } void PeriodSenkou(int value) { m_period_senkou = value; } //--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0 = value; } void Pattern_1(int value) { m_pattern_1 = value; } void Pattern_2(int value) { m_pattern_2 = value; } void Pattern_3(int value) { m_pattern_3 = value; } void Pattern_4(int value) { m_pattern_4 = value; } void Pattern_5(int value) { m_pattern_5 = value; } void Pattern_6(int value) { m_pattern_6 = value; } void Pattern_7(int value) { m_pattern_7 = value; } void Pattern_8(int value) { m_pattern_8 = value; } void Pattern_9(int value) { m_pattern_9 = value; } void Pattern_10(int value) { m_pattern_10 = value; } void Pattern_11(int value) { m_pattern_11 = value; } virtual void ApplyPatternWeight(int patternNumber, int weight); //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual int LongCondition(void); virtual int ShortCondition(void); protected: //--- method of initialization of the indicator bool InitIchimoku(CIndicators *indicators); //--- methods of getting data double Tenkan(int ind) { return(m_ichimoku.TenkanSen(ind)); } double Kijun(int ind) { return(m_ichimoku.KijunSen(ind)); } //--- cloud AS PLOTTED AT bar `ind` - the +m_period_kijun offset is the whole point, see the class //--- comment's LOOKAHEAD note. Never call SenkouSpan*(ind) directly for a "cloud here" reading. double SpanAAt(int ind) { return(m_ichimoku.SenkouSpanA(ind + m_period_kijun)); } double SpanBAt(int ind) { return(m_ichimoku.SenkouSpanB(ind + m_period_kijun)); } double CloudTop(int ind) { return(MathMax(SpanAAt(ind), SpanBAt(ind))); } double CloudBottom(int ind) { return(MathMin(SpanAAt(ind), SpanBAt(ind))); } double CloudThickness(int ind) { return(MathAbs(SpanAAt(ind) - SpanBAt(ind))); } //--- PROJECTED cloud - the values the chart draws m_period_kijun bars ahead of bar `ind`, computed //--- from bar `ind` itself, so a live bar genuinely has them (again, see the class comment). double FutureSpanA(int ind) { return(m_ichimoku.SenkouSpanA(ind)); } double FutureSpanB(int ind) { return(m_ichimoku.SenkouSpanB(ind)); } //--- classification helpers shared by the long and short models bool CloudIsThin(int ind); bool TKCrossUp(int ind) { return(Tenkan(ind) > Kijun(ind) && Tenkan(ind + 1) <= Kijun(ind + 1)); } bool TKCrossDown(int ind) { return(Tenkan(ind) < Kijun(ind) && Tenkan(ind + 1) >= Kijun(ind + 1)); } //--- true if every value the models read at `ind` is present (enough history loaded) bool DataReady(int ind); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSignalIchimoku::CSignalIchimoku(void) : m_period_tenkan(9), m_period_kijun(26), m_period_senkou(52), m_pattern_0(10), // confirming state - price vs the cloud m_pattern_1(10), // confirming state - projected cloud colour m_pattern_2(10), // confirming state - Chikou clear m_pattern_3(10), // the WEAK cross grade: doctrine's "stand down", so it sits at the floor too m_pattern_4(30), // Kumo twist: anticipatory, and the only event not involving price at all m_pattern_5(40), // neutral cross grade - the Kumo offers no bias either way here m_pattern_6(60), // Kijun cross - the same conviction CSignalMA gives its own price/level crosses m_pattern_7(70), // Kijun bounce - a cross with established trend context behind it m_pattern_8(80), // Kumo breakout - a structural break, not just a line cross m_pattern_9(90), // ...through a thin cloud: the break the method rates most likely to hold m_pattern_10(90), // the STRONG cross grade - the one Ichimoku actually wants traded m_pattern_11(100) // Sanyaku: all three roles at once, the method's own top signal { m_id = "Ichimoku"; m_pattern_count = 12; //--- initialization of protected data. High/Low are needed by the Kijun-sen bounce (model 6), which has //--- to see the bar actually reach down to / up to the base line, not merely close near it. m_used_series = USE_SERIES_HIGH + USE_SERIES_LOW + USE_SERIES_CLOSE; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CSignalIchimoku::~CSignalIchimoku(void) { } //+------------------------------------------------------------------+ //| Validation settings protected data. | //+------------------------------------------------------------------+ bool CSignalIchimoku::ValidationSettings(void) { //--- validation settings of additional filters if(!CExpertSignalCustom::ValidationSettings()) return(false); //--- initial data checks if(m_period_tenkan <= 0 || m_period_kijun <= 0 || m_period_senkou <= 0) { printf(__FUNCTION__ + ": all Ichimoku periods must be greater than 0"); return(false); } //--- Tenkan < Kijun < Senkou B is not cosmetic: Tenkan is meant to be the FAST line (a TK cross has no //--- meaning if it is the slower of the two), and Senkou B is the widest lookback, so an inverted set //--- would silently invert every model below rather than fail. if(m_period_tenkan >= m_period_kijun) { printf(__FUNCTION__ + ": Kijun-sen period must be greater than Tenkan-sen period"); return(false); } if(m_period_kijun >= m_period_senkou) { printf(__FUNCTION__ + ": Senkou Span B period must be greater than Kijun-sen period"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| Create indicators. | //+------------------------------------------------------------------+ bool CSignalIchimoku::InitIndicators(CIndicators *indicators) { //--- check pointer if(indicators == NULL) return(false); //--- initialization of indicators and timeseries of additional filters if(!CExpertSignalCustom::InitIndicators(indicators)) return(false); //--- create and initialize Ichimoku indicator if(!InitIchimoku(indicators)) return(false); //--- ok return(true); } //+------------------------------------------------------------------+ //| Initialize Ichimoku indicator. | //+------------------------------------------------------------------+ bool CSignalIchimoku::InitIchimoku(CIndicators *indicators) { //--- check pointer if(indicators == NULL) return(false); //--- add object to collection if(!indicators.Add(GetPointer(m_ichimoku))) { printf(__FUNCTION__ + ": error adding object"); return(false); } //--- initialize object if(!m_ichimoku.Create(m_symbol.Name(), m_period, m_period_tenkan, m_period_kijun, m_period_senkou)) { printf(__FUNCTION__ + ": error initializing object"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| Cloud thickness is Ichimoku's own measure of how much support or | //| resistance the Kumo actually represents - a break through a thin | //| cloud is the one the method treats as meaningful, a thick one is | //| expected to absorb the attempt. "Thin" is deliberately expressed | //| RELATIVE to this instrument's own recent cloud rather than as an | //| absolute price distance, so the test carries across symbols and | //| timeframes with no scaling constant to tune - the same reasoning | //| the AI feature side applies when it ATR-normalizes thickness. | //| Averaged over m_period_kijun bars, i.e. the same horizon the | //| cloud is projected across. | //+------------------------------------------------------------------+ bool CSignalIchimoku::CloudIsThin(int ind) { double sum = 0.0; int count = 0; for(int i = 0; i < m_period_kijun; i++) { double t = CloudThickness(ind + i); if(t == EMPTY_VALUE) break; sum += t; count++; } if(count == 0) return(false); double average = sum / count; //--- a degenerate (zero-width) average means there is no cloud to speak of over the whole window, which //--- is not the same statement as "this bar's cloud is unusually thin" - decline rather than divide. if(average <= 0.0) return(false); return(CloudThickness(ind) < 0.5 * average); } //+------------------------------------------------------------------+ //| Every value the models below read, checked in one place. The | //| deepest read is the cloud plotted at the CHIKOU's own position | //| (model 9), which is the spans at ind + 2*m_period_kijun; the | //| thin-cloud average (model 8) walks a further m_period_kijun bars | //| of cloud but tolerates running short on its own. Early in the | //| loaded history the lines can be valid while the cloud is not, so | //| one gate covers both rather than a per-value check per model. | //+------------------------------------------------------------------+ bool CSignalIchimoku::DataReady(int ind) { if(Tenkan(ind) == EMPTY_VALUE || Tenkan(ind + 1) == EMPTY_VALUE) return(false); if(Kijun(ind) == EMPTY_VALUE || Kijun(ind + 1) == EMPTY_VALUE) return(false); if(SpanAAt(ind) == EMPTY_VALUE || SpanBAt(ind) == EMPTY_VALUE) return(false); if(SpanAAt(ind + 1) == EMPTY_VALUE || SpanBAt(ind + 1) == EMPTY_VALUE) return(false); if(FutureSpanA(ind) == EMPTY_VALUE || FutureSpanB(ind) == EMPTY_VALUE) return(false); if(FutureSpanA(ind + 1) == EMPTY_VALUE || FutureSpanB(ind + 1) == EMPTY_VALUE) return(false); //--- the cloud plotted at the Chikou's own position, i.e. ind + 2*m_period_kijun in span terms if(SpanAAt(ind + m_period_kijun) == EMPTY_VALUE || SpanBAt(ind + m_period_kijun) == EMPTY_VALUE) return(false); if(Close(ind) == EMPTY_VALUE || Close(ind + 1) == EMPTY_VALUE) return(false); if(Close(ind + m_period_kijun) == EMPTY_VALUE) return(false); if(Low(ind) == EMPTY_VALUE || High(ind) == EMPTY_VALUE) return(false); //--- ok return(true); } //+------------------------------------------------------------------+ //| "Voting" that price will grow. | //+------------------------------------------------------------------+ int CSignalIchimoku::LongCondition(void) { int result = 0; int idx = StartIndex(); if(!DataReady(idx)) return(0); double close = Close(idx); double closePrev = Close(idx + 1); double kijun = Kijun(idx); double kijunPrev = Kijun(idx + 1); double cloudTop = CloudTop(idx); double cloudBottom = CloudBottom(idx); double cloudTopPrev = CloudTop(idx + 1); //--- price position relative to the Kumo, the axis every graded model below is graded against bool aboveCloud = (close > cloudTop); bool insideCloud = (close >= cloudBottom && close <= cloudTop); bool crossUp = TKCrossUp(idx); //--- Chikou clear of BOTH the price Kijun bars back and the cloud plotted at that same position - the //--- full form of the confirmation. Both references sit further into the PAST than this bar, never the //--- future; see the class comment for why that direction is the lookahead-free one. bool chikouClear = (close > Close(idx + m_period_kijun) && close > CloudTop(idx + m_period_kijun)); //--- every model enters at the current price. Ichimoku's own levels (Kijun, cloud edge) are the //--- textbook pull-back targets, but each of these models is a BREAK/CROSS/BOUNCE that has already //--- happened, so resting a limit order back at the level it just left would routinely never fill on //--- the move the model voted for. Left at market for all twelve, deliberately. m_base_price = 0.0; //--- model 0: price is above the cloud - the standing bullish bias the stronger models confirm against, //--- rather than an event in its own right. if(IS_PATTERN_USAGE(0) && aboveCloud) { result = m_pattern_0; m_active_pattern = "Pattern_0"; } //--- model 1: the projected cloud is bullish (Senkou A above Senkou B ahead of this bar). This is the //--- cloud's COLOUR - a state, not the twist event; model 4 is the event. See the class comment for why //--- reading the spans unshifted here is correct and is not lookahead. if(IS_PATTERN_USAGE(1) && FutureSpanA(idx) > FutureSpanB(idx)) { result = m_pattern_1; m_active_pattern = "Pattern_1"; } //--- model 2: Chikou Span confirmation in its full form - the lagging span clear of the price Kijun //--- bars back AND of the cloud that was plotted there, with price above the cloud now. Demanding, but //--- still a STATE that holds for long stretches of a trend rather than an entry trigger, which is why //--- it sits with the confirming models at weight 10 despite how much it asks for. if(IS_PATTERN_USAGE(2) && chikouClear && aboveCloud) { result = m_pattern_2; m_active_pattern = "Pattern_2"; } //--- model 3: WEAK grade - a bullish TK cross occurring BELOW the cloud, i.e. against the prevailing //--- Kumo bias. This is the grade Ichimoku doctrine tells you to stand down on, so it carries the same //--- floor weight as the confirming states rather than being lumped in with a real cross. if(IS_PATTERN_USAGE(3) && crossUp && close < cloudBottom) { result = m_pattern_3; m_active_pattern = "Pattern_3"; } //--- model 4: Kumo twist - Senkou A actually CROSSED above Senkou B in the projected cloud on this bar, //--- the moment the future cloud changes colour. The lowest-weighted event: it is anticipatory, and the //--- only model here that does not involve price at all. if(IS_PATTERN_USAGE(4) && FutureSpanA(idx) > FutureSpanB(idx) && FutureSpanA(idx + 1) <= FutureSpanB(idx + 1)) { result = m_pattern_4; m_active_pattern = "Pattern_4"; } //--- model 5: NEUTRAL grade - a bullish TK cross occurring INSIDE the cloud, where the Kumo offers no //--- bias either way. if(IS_PATTERN_USAGE(5) && crossUp && insideCloud) { result = m_pattern_5; m_active_pattern = "Pattern_5"; } //--- model 6: price crossed above the Kijun-sen - the equilibrium line, Ichimoku's nearest analogue to //--- the MA cross CSignalMA votes on, and weighted to match what that signal gives its own crosses. if(IS_PATTERN_USAGE(6) && close > kijun && closePrev <= kijunPrev) { result = m_pattern_6; m_active_pattern = "Pattern_6"; } //--- model 7: Kijun-sen bounce - price was already above the base line, dipped down to touch or pierce //--- it, and closed back above. The pull-back entry the base line's magnet effect produces; requiring //--- the previous close to have been above it is what separates this from the fresh cross in model 6, //--- and requiring price above the cloud keeps it a trend continuation rather than a catch of a fall. //--- The base line must also be flat or rising - the magnet effect is what makes this trade, and it //--- only exists while the Kijun holds its level; bouncing off a FALLING base line in a long is just //--- buying into a line that is coming down to meet you. Rated above the plain cross in model 6 for //--- exactly that added trend context. if(IS_PATTERN_USAGE(7) && aboveCloud && closePrev > kijunPrev && Low(idx) <= kijun && close > kijun && kijun >= kijunPrev) { result = m_pattern_7; m_active_pattern = "Pattern_7"; } //--- model 8: Kumo breakout - price closed above the cloud having not been above it on the previous bar //--- (it left the cloud, or gapped over it, upward). A structural break rather than a line cross, hence //--- the step up from models 6/7. if(IS_PATTERN_USAGE(8) && aboveCloud && closePrev <= cloudTopPrev) { result = m_pattern_8; m_active_pattern = "Pattern_8"; } //--- model 9: the same breakout, but through a THIN cloud - little real resistance stood in the way, so //--- Ichimoku rates the break more likely to hold than one through a thick Kumo. if(IS_PATTERN_USAGE(9) && aboveCloud && closePrev <= cloudTopPrev && CloudIsThin(idx)) { result = m_pattern_9; m_active_pattern = "Pattern_9"; } //--- model 10: STRONG grade - a bullish TK cross occurring ABOVE the cloud, so Kumo bias and trigger //--- agree. The grade Ichimoku actually wants you trading. if(IS_PATTERN_USAGE(10) && crossUp && aboveCloud) { result = m_pattern_10; m_active_pattern = "Pattern_10"; } //--- model 11: Sanyaku Kouten - the "three roles turning bullish" alignment, Ichimoku's own strongest //--- signal: Tenkan above Kijun, Chikou clear of past price and cloud, and price clear above the Kumo, //--- all true together. Note this asks for the cross STATE (Tenkan above Kijun), not the cross event - //--- the alignment is what matters, and demanding all three flip on the same bar would fire almost //--- never. Last, so it overwrites any weaker match above. if(IS_PATTERN_USAGE(11) && Tenkan(idx) > Kijun(idx) && chikouClear && aboveCloud) { result = m_pattern_11; m_active_pattern = "Pattern_11"; } if(result != 0) { m_active_direction = "Buy"; } //--- return the result return(result); } //+------------------------------------------------------------------+ //| "Voting" that price will fall. | //+------------------------------------------------------------------+ int CSignalIchimoku::ShortCondition(void) { int result = 0; int idx = StartIndex(); if(!DataReady(idx)) return(0); double close = Close(idx); double closePrev = Close(idx + 1); double kijun = Kijun(idx); double kijunPrev = Kijun(idx + 1); double cloudTop = CloudTop(idx); double cloudBottom = CloudBottom(idx); double cloudBottomPrev = CloudBottom(idx + 1); bool belowCloud = (close < cloudBottom); bool insideCloud = (close >= cloudBottom && close <= cloudTop); bool crossDown = TKCrossDown(idx); //--- mirror of LongCondition()'s chikouClear - clear BELOW past price and below the cloud plotted there bool chikouClear = (close < Close(idx + m_period_kijun) && close < CloudBottom(idx + m_period_kijun)); //--- see LongCondition() for why every model enters at market m_base_price = 0.0; //--- model 0: price is below the cloud if(IS_PATTERN_USAGE(0) && belowCloud) { result = m_pattern_0; m_active_pattern = "Pattern_0"; } //--- model 1: the projected cloud is bearish (Senkou A below Senkou B ahead of this bar) - colour, not //--- the twist event; model 4 is the event if(IS_PATTERN_USAGE(1) && FutureSpanA(idx) < FutureSpanB(idx)) { result = m_pattern_1; m_active_pattern = "Pattern_1"; } //--- model 2: Chikou Span confirmation, full form - see LongCondition() for why a reading this //--- demanding still sits at the confirming floor weight if(IS_PATTERN_USAGE(2) && chikouClear && belowCloud) { result = m_pattern_2; m_active_pattern = "Pattern_2"; } //--- model 3: WEAK grade - bearish TK cross occurring ABOVE the cloud, against the prevailing bias if(IS_PATTERN_USAGE(3) && crossDown && close > cloudTop) { result = m_pattern_3; m_active_pattern = "Pattern_3"; } //--- model 4: Kumo twist - Senkou A crossed BELOW Senkou B in the projected cloud on this bar if(IS_PATTERN_USAGE(4) && FutureSpanA(idx) < FutureSpanB(idx) && FutureSpanA(idx + 1) >= FutureSpanB(idx + 1)) { result = m_pattern_4; m_active_pattern = "Pattern_4"; } //--- model 5: NEUTRAL grade - bearish TK cross occurring INSIDE the cloud if(IS_PATTERN_USAGE(5) && crossDown && insideCloud) { result = m_pattern_5; m_active_pattern = "Pattern_5"; } //--- model 6: price crossed below the Kijun-sen if(IS_PATTERN_USAGE(6) && close < kijun && closePrev >= kijunPrev) { result = m_pattern_6; m_active_pattern = "Pattern_6"; } //--- model 7: Kijun-sen bounce - price was already below the base line, rallied up to touch or pierce //--- it, and closed back below, with the base line flat or falling. See LongCondition()'s model 7 for //--- why the slope condition is part of the model rather than a weight adjustment. if(IS_PATTERN_USAGE(7) && belowCloud && closePrev < kijunPrev && High(idx) >= kijun && close < kijun && kijun <= kijunPrev) { result = m_pattern_7; m_active_pattern = "Pattern_7"; } //--- model 8: Kumo breakout - price closed below the cloud having not been below it on the previous bar if(IS_PATTERN_USAGE(8) && belowCloud && closePrev >= cloudBottomPrev) { result = m_pattern_8; m_active_pattern = "Pattern_8"; } //--- model 9: the same breakout through a THIN cloud if(IS_PATTERN_USAGE(9) && belowCloud && closePrev >= cloudBottomPrev && CloudIsThin(idx)) { result = m_pattern_9; m_active_pattern = "Pattern_9"; } //--- model 10: STRONG grade - bearish TK cross occurring BELOW the cloud if(IS_PATTERN_USAGE(10) && crossDown && belowCloud) { result = m_pattern_10; m_active_pattern = "Pattern_10"; } //--- model 11: Sanyaku Gyakuten - the bearish "three roles" alignment if(IS_PATTERN_USAGE(11) && Tenkan(idx) < Kijun(idx) && chikouClear && belowCloud) { result = m_pattern_11; m_active_pattern = "Pattern_11"; } if(result != 0) { m_active_direction = "Sell"; } //--- return the result return(result); } //+------------------------------------------------------------------+ //| Set the specified pattern's weight to the specified value | //+------------------------------------------------------------------+ void CSignalIchimoku::ApplyPatternWeight(int patternNumber, int weight) { switch(patternNumber) { default: break; case 0: Pattern_0(weight); break; case 1: Pattern_1(weight); break; case 2: Pattern_2(weight); break; case 3: Pattern_3(weight); break; case 4: Pattern_4(weight); break; case 5: Pattern_5(weight); break; case 6: Pattern_6(weight); break; case 7: Pattern_7(weight); break; case 8: Pattern_8(weight); break; case 9: Pattern_9(weight); break; case 10: Pattern_10(weight); break; case 11: Pattern_11(weight); break; } } //+------------------------------------------------------------------+