forked from animatedread/Warrior_EA
643 lines
33 KiB
MQL5
643 lines
33 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| 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;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|