forked from mnbvc188199/Warrior_EA
- Replaced standard library signal modules with custom implementations to allow for named patterns and improved voting. - Added new input parameters for module weights, allowing for optimization of individual signal contributions. - Enhanced the management of trades with new options for breakeven and management cut. - Introduced a mechanism for dynamic ranking of signal weights based on historical performance. - Improved initialization logic to ensure proper registration of filters and handling of trading conditions. - Added detailed logging for trading permissions and account status during initialization.
668 lines
35 KiB
MQL5
668 lines
35 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| SignalIchimoku.mqh |
| |
//| AnimateDread |
| |
//| https://www.mql5.com |
| |
//+------------------------------------------------------------------+
| |
#include "..\Expert\WarriorSignal.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 CWarriorSignal 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 CWarriorSignal
| |
{
| |
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);
| |
//--- deep-history readiness for the meta candidate sweep - see CWarriorSignal::SweepPrepare
| |
| |
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);
| |
//--- the three Sanyaku roles, as reusable STATES so model 11 can test the alignment's transition
| |
//--- rather than its persistence (see LongCondition()'s model 11 for why that distinction matters)
| |
bool AboveCloud(int ind) { return(Close(ind) > CloudTop(ind)); }
| |
bool BelowCloud(int ind) { return(Close(ind) < CloudBottom(ind)); }
| |
bool ChikouClearLong(int ind) { return(Close(ind) > Close(ind + m_period_kijun) &&
| |
Close(ind) > CloudTop(ind + m_period_kijun)); }
| |
bool ChikouClearShort(int ind) { return(Close(ind) < Close(ind + m_period_kijun) &&
| |
Close(ind) < CloudBottom(ind + m_period_kijun)); }
| |
bool SanyakuLong(int ind) { return(Tenkan(ind) > Kijun(ind) && ChikouClearLong(ind) && AboveCloud(ind)); }
| |
bool SanyakuShort(int ind) { return(Tenkan(ind) < Kijun(ind) && ChikouClearShort(ind) && BelowCloud(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";
| |
//--- Confirmation pattern(s): weight 10, never traded alone, never ranked.
| |
m_confirm_mask = (1<<0)|(1<<1)|(1<<2)|(1<<3);
| |
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(!CWarriorSignal::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(!CWarriorSignal::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.
| |
//--- Checked at ind+1 as well: model 11 evaluates its whole alignment one bar back to detect the
| |
//--- TRANSITION into Sanyaku, and that reaches one bar deeper than any other model here.
| |
if(SpanAAt(ind + m_period_kijun) == EMPTY_VALUE || SpanBAt(ind + m_period_kijun) == EMPTY_VALUE)
| |
return(false);
| |
if(SpanAAt(ind + 1 + m_period_kijun) == EMPTY_VALUE || SpanBAt(ind + 1 + 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 || Close(ind + 1 + 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", Ichimoku's own strongest signal:
| |
//--- Tenkan above Kijun, Chikou clear of past price and cloud, and price clear above the Kumo.
| |
//--- This tests the bar the alignment BECOMES true, not every bar it happens to hold. The three
| |
//--- conditions are standing states, so the conjunction is true across long stretches - measured at
| |
//--- 27% of all bars on EURUSD H1. At weight 100, last in the chain (so it overwrites every weaker
| |
//--- match) and averaged into the vote, that made the module's highest-conviction reading its most
| |
//--- common one, and drowned the eight event models below it.
| |
//--- The previous comment here rejected an event form on the grounds that "demanding all three flip
| |
//--- on the same bar would fire almost never" - true, but that is not the alternative. Kouten means
| |
//--- the turn: the ALIGNMENT is what transitions, and only one role need change for it to. Testing
| |
//--- !Sanyaku(idx+1) fires exactly once per aligned stretch, which is what the doctrine describes and
| |
//--- what a weight of 100 is for.
| |
if(IS_PATTERN_USAGE(11) && SanyakuLong(idx) && !SanyakuLong(idx + 1))
| |
{
| |
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
| |
//--- Sanyaku Gyakuten - mirror of model 11 long, and an EVENT for the same reason (see there)
| |
if(IS_PATTERN_USAGE(11) && SanyakuShort(idx) && !SanyakuShort(idx + 1))
| |
{
| |
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;
| |
}
| |
}
| |
//+------------------------------------------------------------------+
|