Riddle me this - Discussion on Doji

 

When is a Doji no longer considered a Doji? We all know that visually a Doji is basically a candle where the open and close are nearly equal and there is a high stem and a low stem. Variations of the Doji such as dragonfly shows no high, but long low, a gravestone has a long high, but no low. BUT at what point wound it not be considered a Doji?

What if the body was 5 pips from open to close, or only 3 pips, or only .3 pips, would it still be a doji?

What if the high was only .1 pip, or 1 pip, or 5 pips, would it still be a doji?

Let's hear your opinion.

I was looking into doji Reader 2 and I noticed that the default settings aloud you to change the configuration of what to look for. My thought on this was to modify it to do the determination on it's own.

How would I do that? Good question. I was thinking of writing a code snippet that would go into the history of the pair it was put on and look for similar patterns that make up a doji, then evaluate the average of each one to determine what value to insert into the configuration settings of Doju Reader 2. This way the user didn't have to do the configuration, and for each pair it would be the average of what is consistent on that particular pair.

 
if(Open[1]==Close[1]) Print("the most recently closed candle was a Doji");  // doji detected, candle has no body length

else Print("the most recently closed candle was NOT a Doji"); // candle has a body, therefore is not a doji
 
Candles are subjective. So there has to be wiggle room for people to define what they consider Doji. The most Objective definition of doji would be when open=close. If you wanna give it a range then you're creating muddy waters. Also if you want to differentiate between doji and dragon-flys and grave-stones then you'll need to define where the cross would lie on a percentage body of the candle. Programming candle-sticks is one of the last things on my programming laundry list.
 

Good, lets keep it going, any more opinions? Maybe you have found a good reference that contributes to the conversation.

 

LEH

If you look at the function

IsDojiCandle()

in codebase item https://www.mql5.com/en/code/8714

That gives a basic code snippet to use - as the others have said, proportions can vary...

In general, candle patterns are not quite so specific as we would like, especially on the shorter timeframes and when market volume is low

Does vary with pair though as crosses have different bar shapes anyway to majors

See what you think

-BB-

 

I have come up with a variant on the Doji Reader 2. It didn't fit my needs. Also there was a lot of code that was redundant and useless. For the moment, I have something strange happening with it. It seems to be contiuously loading on the charts. While I am somewhat accustomed to a indicator loading on charts, none of the indicators I am using, except this one is doing this. I am not sure why it is doing this, can you take a look at the code and give me some ideas?

int start()
  {
   int i, counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   
   if (counter1 > 1 || counter2 > 1 || counter3 > 1)
   {
      ObjectsDeleteAll(0, OBJ_RECTANGLE);
      counter1 = 0;
      counter2 = 0;
      counter3 = 0;
   }
   
      for(i=1;i<=RangeOfBars;i++)            
      {                                    
         Doji[RangeOfBars-i]=EMPTY_VALUE;         
      }
        
      for(i=RangeOfBars; i>0; i--)
      {

       if(FindRegularDoji)
         {
          if(High[i]-Close[i]>=MinLengthOfUpTail*PipPoints && Close[i]-Low[i]>=MinLengthOfLoTail*PipPoints  && MathAbs(Close[i]-Open[i])<=MaxLengthOfBody*PipPoints) 
            {
               Doji[i] = 1;
             if(ShowCandleBox) 
               {
                if(ObjectFind("box 1"+counter1)==-1)
                  {
                   ObjectCreate("box 1"+counter1, OBJ_RECTANGLE, 0, Time[i+1], High[i]+(MathMin(Open[i], Close[i])-Low[i])/2, Time[i-1], Low[i]-(MathMin(Open[i], Close[i])-Low[i])/2);
                   ObjectSet("box 1"+counter1, OBJPROP_COLOR, BoxColor);
                //   ObjectSet("box 1"+counter1, OBJPROP_BACK, true);
                  }
               } 

              counter1++;
            }
         } 
       if(FindDragonflyDoji)
         {
            Doji[i] = 1;
          if(High[i]-Close[i]<=MaxLengthOfUpTail1*PipPoints && Close[i]-Low[i]>=MinLengthOfLoTail1*PipPoints  && MathAbs(Close[i]-Open[i])<=MaxLengthOfBody1*PipPoints)
            {
             counter2++;
             if(ShowCandleBox) 
               {
                if(ObjectFind("box 2"+counter2)==-1)
                  {
                   ObjectCreate("box 2"+counter2, OBJ_RECTANGLE, 0, Time[i+1], High[i]+(MathMin(Open[i], Close[i])-Low[i])/2, Time[i-1], Low[i]-(MathMin(Open[i], Close[i])-Low[i])/2);
                   ObjectSet("box 2"+counter2, OBJPROP_COLOR, BoxColor);
                 //  ObjectSet("box 2"+counter2, OBJPROP_BACK, true);
                  }
               } 
             }
         } 
       if(FindGravestoneDoji)
         {
            Doji[i] = 1;
          if(High[i]-Close[i]>=MinLengthOfUpTail2*PipPoints && Close[i]-Low[i]<=MaxLengthOfLoTail2*PipPoints  && MathAbs(Close[i]-Open[i])<=MaxLengthOfBody2*PipPoints)
            {
             counter3++;
             if(ShowCandleBox) 
               {
                if(ObjectFind("box 3"+counter3)==-1)
                  {
                   ObjectCreate("box 3"+counter3, OBJ_RECTANGLE, 0, Time[i+1], High[i]+(MathMin(Open[i], Close[i])-Low[i])/2, Time[i-1], Low[i]-(High[i]-MathMax(Open[i], Close[i]))/2);
                   ObjectSet("box 3"+counter3, OBJPROP_COLOR, BoxColor);
                 //  ObjectSet("box 3"+counter3, OBJPROP_BACK, true);
                  }
               } 
            }
         } 
      } 
          
   return(0);
  } //end of file 
//+------------------------------------------------------------------+
I then made some modifications to the code in start() to try and fix this problem

int start()
  {
  
   if(Bars<=RangeOfBars) return(0);
  
   int i, counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   
   if (counter1 > 1 || counter2 > 1 || counter3 > 1)
   {
      ObjectsDeleteAll(0, OBJ_RECTANGLE);
      counter1 = 0;
      counter2 = 0;
      counter3 = 0;
   }
   
      for(i=1;i<=RangeOfBars;i++)            
      {                                    
         Doji[RangeOfBars-i]=EMPTY_VALUE;         
      }
      
      int limit=Bars-counted_bars;              // determine our limit
      if(counted_bars>0) limit++;
      for(i=0; i<limit; i++)
      {

       if(FindRegularDoji)
         {
          if(High[i]-Close[i]>=MinLengthOfUpTail*PipPoints && Close[i]-Low[i]>=MinLengthOfLoTail*PipPoints  && MathAbs(Close[i]-Open[i])<=MaxLengthOfBody*PipPoints) 
            {
               Doji[i] = 1;
             if(ShowCandleBox) 
               {
                if(ObjectFind("box 1"+counter1)==-1)
                  {
                   ObjectCreate("box 1"+counter1, OBJ_RECTANGLE, 0, Time[i+1], High[i]+(MathMin(Open[i], Close[i])-Low[i])/2, Time[i-1], Low[i]-(MathMin(Open[i], Close[i])-Low[i])/2);
                   ObjectSet("box 1"+counter1, OBJPROP_COLOR, BoxColor);
                //   ObjectSet("box 1"+counter1, OBJPROP_BACK, true);
                  }
               } 

              counter1++;
            }
         } 
       if(FindDragonflyDoji)
         {
            Doji[i] = 1;
          if(High[i]-Close[i]<=MaxLengthOfUpTail1*PipPoints && Close[i]-Low[i]>=MinLengthOfLoTail1*PipPoints  && MathAbs(Close[i]-Open[i])<=MaxLengthOfBody1*PipPoints)
            {
             counter2++;
             if(ShowCandleBox) 
               {
                if(ObjectFind("box 2"+counter2)==-1)
                  {
                   ObjectCreate("box 2"+counter2, OBJ_RECTANGLE, 0, Time[i+1], High[i]+(MathMin(Open[i], Close[i])-Low[i])/2, Time[i-1], Low[i]-(MathMin(Open[i], Close[i])-Low[i])/2);
                   ObjectSet("box 2"+counter2, OBJPROP_COLOR, BoxColor);
                 //  ObjectSet("box 2"+counter2, OBJPROP_BACK, true);
                  }
               } 
             }
         } 
       if(FindGravestoneDoji)
         {
            Doji[i] = 1;
          if(High[i]-Close[i]>=MinLengthOfUpTail2*PipPoints && Close[i]-Low[i]<=MaxLengthOfLoTail2*PipPoints  && MathAbs(Close[i]-Open[i])<=MaxLengthOfBody2*PipPoints)
            {
             counter3++;
             if(ShowCandleBox) 
               {
                if(ObjectFind("box 3"+counter3)==-1)
                  {
                   ObjectCreate("box 3"+counter3, OBJ_RECTANGLE, 0, Time[i+1], High[i]+(MathMin(Open[i], Close[i])-Low[i])/2, Time[i-1], Low[i]-(High[i]-MathMax(Open[i], Close[i]))/2);
                   ObjectSet("box 3"+counter3, OBJPROP_COLOR, BoxColor);
                 //  ObjectSet("box 3"+counter3, OBJPROP_BACK, true);
                  }
               } 
            }
         } 
      } 
          
   return(0);
  } //end of file 
//+------------------------------------------------------------------+

Problem still exists... file is attached.

Files:
 
It loaded successfully for me. Maybe it's something with your mt4.
 

Look in your logs, does it repeatedly give a load message? I was getting a load, then an unload message repeating. I took out the deinit value and now it just repeatedly gives a load message. I am running it on multiple pairs also.

 

Here's the full log file, I deleted the old log file so I get a fresh one. Hope it helps.

04:19:48 Compiling '- Fund_Draw'
04:19:48 Compiling 'Doji_Hunter'
04:19:48 Compiling 'Format'
04:19:49 - Fund_Draw EURUSD,M30: loaded successfully
04:19:49 Doji_Hunter EURUSD,M30: loaded successfully
04:19:49 Doji_Hunter EURUSD,M30: initialized
04:20:11 - Fund_Draw EURUSD,M30: uninit reason 1
04:20:11 Doji_Hunter EURUSD,M30: deinitialized
04:20:11 Doji_Hunter EURUSD,M30: uninit reason 1
04:20:11 - Fund_Draw EURUSD,M30: removed
04:20:11 Doji_Hunter EURUSD,M30: removed

 Edit* and for multiple pairs

04:31:01 Compiling '- Fund_Draw'
04:31:01 Compiling 'Doji_Hunter'
04:31:01 Compiling 'Format'
04:31:01 - Fund_Draw EURUSD,M30: loaded successfully
04:31:01 Doji_Hunter EURUSD,M30: loaded successfully
04:31:01 Doji_Hunter EURUSD,M30: initialized
04:31:01 Doji_Hunter USDJPY,H1: loaded successfully
04:31:01 Doji_Hunter USDJPY,H1: initialized
04:31:05 - Fund_Draw EURUSD,M30: uninit reason 1
04:31:05 Doji_Hunter EURUSD,M30: deinitialized
04:31:05 Doji_Hunter EURUSD,M30: uninit reason 1
04:31:05 - Fund_Draw EURUSD,M30: removed
04:31:05 Doji_Hunter EURUSD,M30: removed
04:31:05 Doji_Hunter USDJPY,H1: deinitialized
04:31:05 Doji_Hunter USDJPY,H1: uninit reason 1
04:31:05 Doji_Hunter USDJPY,H1: removed
 

This is odd. You are not getting the same problem I am getting. I was getting it loading repeatedly for 2 or 3 times per pair. It was also consuming my CPU capacity. I stripped down all other indicators on this EA I am running it on and throughout the night I was having failures of modification to trades. not constantly, but just every once in a while. I have some friends looking it over to see what they can find.

Did you just drop it on the chart or did you actually put it in some code and attempt to pass it data and get a value back?

 

LEHayes: ... Did you just drop it on the chart or did you actually put it in some code and attempt to pass it data and get a value back?

I downloaded as it was. Never made any modifications to it. Compiled it. In the mt4 window, I double clicked the indicator from the folder structure view plain instead of dragging and dropping ( I really don't think that part would make a difference). If your friends aren't getting the same repeated load then it's just you. If not then maybe you guys have the same version of mt4. In the past, I was having funny problems with built 226 or higher. So I went back to 225 and deleted the auto.upgrade feature somewhere in the mt4 folder structure.

Reason: