//+------------------------------------------------------------------+ 
//|                      No Demand / No Supply                      | 
//|              WRITTEN BY TIM HYDER - pro4x@ymail.com              | 
//+------------------------------------------------------------------+ 
#property copyright "Copyright © 2014, Pro4x"
#property link      "pro4x@ymail.com"
#include <stdlib.mqh>

#define vers   "04.Mar.2014"
#define major  "1"
#define minor  "0"
#define Prefix "NDS"

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1  Blue
#property indicator_width1  2
#property indicator_color2  Yellow
#property indicator_width2  2

extern string  Indicators = "===== Indicator Options =====";
extern int     MaxBars = 11500;
extern double  VolAvgPd = 15;
extern double  VolIncPcnt = 0.618;

int     AlertLineLength = 20;
int     AlertLineWidth = 0;
color   AlertLineColorBull = Gray;
color   AlertLineColorBear = Gray;

extern string  Alerts = "===== Alert Options =====";
extern bool    UseAlerts = true;
extern bool    MsgAlerts = true;
extern bool    SoundAlerts = true;
extern string  AlertSoundFile  = "fanfare2";
extern bool    eMailAlerts = False;

double NoDem[];
double NoSup[];
int LastAlertBar;
double PipPoint;    //Default Point size for 4/5 digit pricing

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{    
   IndicatorBuffers(2);

   SetIndexBuffer(0, NoDem);
   SetIndexStyle(0, DRAW_ARROW);
   SetIndexArrow(0,115); //wingding 119 (small diamond)
   SetIndexLabel(0,"No Demand");
   
   SetIndexBuffer(1, NoSup);
   SetIndexStyle(1, DRAW_ARROW);
   SetIndexArrow(1,115); //wingding 74 (Smiley Face) if just the yowming condition is met and 
   SetIndexLabel(1,"No Supply");

   IndicatorShortName("NO D/S");
   
   LastAlertBar = Bars;
   VolIncPcnt = VolIncPcnt+1.0;

   //Set the Point size for this symbol, automatically adjusts for 3/5 digit if necessary
   PipPoint = GetPointSize(Symbol());

   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   Comment("");
   DeleteObjects(Prefix);
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{   
   string sAlert, Msg;
   
   int counted_bars = IndicatorCounted();
   //---- check for possible errors
   if (counted_bars<0) return(-1);
   //---- last counted bar will be recounted
   if (counted_bars>0) counted_bars--;
   int limit = Bars - counted_bars;
   limit = MathMin(limit, MaxBars);
   
   string setup;
   
   for(int i=limit; i>=1; i--)
   {
      NoDem[i] = EMPTY_VALUE;
      NoSup[i] = EMPTY_VALUE;

      //double Vol = 0;                                       
      //for(int x=i;x<=i+VolAvgPd;x++) Vol += iVolume(Symbol(),Period(),x);        
      //double VolMA = NormalizeDouble((Vol/VolAvgPd)*VolIncPcnt,0); 
      //double Vol1 = NormalizeDouble(iVolume(Symbol(),Period(),i),0);

      double Vol1 = NormalizeDouble(iVolume(Symbol(),Period(),i),0);
      double Vol2 = NormalizeDouble(iVolume(Symbol(),Period(),i+1),0);
      double Vol3 = NormalizeDouble(iVolume(Symbol(),Period(),i+2),0);

      if(Close[i]<Open[i] && Vol1<Vol2 && Vol1<Vol3 ) NoDem[i] = Low[i]-(iATR(Symbol(),Period(),120,i)*0.45);
      if(Close[i]>Open[i] && Vol1<Vol2 && Vol1<Vol3 ) NoSup[i] = High[i]+(iATR(Symbol(),Period(),120,i)*0.45);
      

      /*if (Vol1>VolMA) 
      {         
         if(Close[i]>=Open[i]) 
         {
            YowUp[i] = Low[i]+(iATR(Symbol(),Period(),5,i)*0.50);
            DeleteObjects(Prefix + "UP");
            DrawPriceLevel("UP", False, i, High[i],AlertLineColorBull,AlertLineLength,AlertLineWidth,False);
        }
         if(Close[i]<Open[i]) 
         {
            YowDn[i] = High[i]-(iATR(Symbol(),Period(),5,i)*0.50);
            DeleteObjects(Prefix + "DN");
            DrawPriceLevel("DN", False, i, Low[i],AlertLineColorBear,AlertLineLength,AlertLineWidth,False);
         }
      }*/
   }   
   
   if(LastAlertBar<Bars && UseAlerts) //Only look at bar 1 for a signal
   {
      if(NoDem[1]!=EMPTY_VALUE) setup = "NO SUP";
      if(NoSup[1]!=EMPTY_VALUE) setup = "NO DEM";

      if(StringLen(setup)>0)
      {
         LastAlertBar=Bars;
         sAlert = AccountNumber() + ", " + setup + " on " +  Symbol() + ", " +  TF2Str(Period());
         Msg = sAlert + " @ Local Time: " + TimeToStr(TimeLocal(),TIME_MINUTES);
         DoAlerts(Msg,sAlert,AlertSoundFile);
      }
   }      

      
   return(0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DoAlerts(string msgText,string eMailSub, string SoundAlertFile)
{
   if (MsgAlerts) Alert(msgText);
   if (eMailAlerts) SendMail(eMailSub, msgText);
   if (SoundAlerts) PlaySound(SoundAlertFile);
}

//+------------------------------------------------------------------+
//| Convert Time Frame integer value into a descriptive string       |
//+------------------------------------------------------------------+
string TF2Str(int period) 
{
  switch (period) 
  {
    case PERIOD_M1: return("M1"); break;
    case PERIOD_M5: return("M5"); break;
    case PERIOD_M15: return("M15"); break;
    case PERIOD_M30: return("M30"); break;
    case PERIOD_H1: return("H1"); break; 
    case PERIOD_H4: return("H4"); break;
    case PERIOD_D1: return("D1"); break;
    case PERIOD_W1: return("W1"); break;
    case PERIOD_MN1: return("MN"); break;
  }
  return (Period());
} 

//+------------------------------------------------------------------+
//| Delete Objects that match ObjName                                |
//+------------------------------------------------------------------+
void DeleteObjects(string ObjName)
{
   for (int i=ObjectsTotal()-1; i >= 0; i--) 
   {
     string name = ObjectName(i);
     if (StringFind(name, ObjName) > -1) ObjectDelete(name);
   }
}

//+-------------------------------------------------------------------+
//| Draws price levels on the chart, including a name and price label |
//+-------------------------------------------------------------------+
void DrawPriceLevel(string LabelName, bool DeleteOnly, int BarRef = 0, double Price=0, color LineColor=CLR_NONE, int Length = 20, int Width = 1, bool ShowPrice=True) 
{   
   string Name = Prefix + LabelName; //set unique base name
   if(DeleteOnly) 
   {
      DeleteObjects(Name);
      return;
   }
   else if(!DeleteOnly && Price>0)
   {
      double TimeDiff = Period()*60;  

      if(ObjectFind(Name) < 0) ObjectCreate(Name, OBJ_TREND, 0, Time[BarRef]+(Width*TimeDiff), Price, Time[BarRef+1], Price);

      ObjectSet(Name,OBJPROP_COLOR,LineColor);
      ObjectSet(Name,OBJPROP_TIME1,Time[BarRef]+(Length*TimeDiff));
      ObjectSet(Name,OBJPROP_PRICE1,Price);
      ObjectSet(Name,OBJPROP_TIME2,Time[BarRef+1]);
      ObjectSet(Name,OBJPROP_PRICE2,Price);
      ObjectSet(Name,OBJPROP_WIDTH,Width);
      ObjectSet(Name,OBJPROP_RAY,FALSE);

      if(ShowPrice)
      {
         //Attach label to TL detailing name and price
         Name = Name + "$";
         if(ObjectFind(Name) < 0) ObjectCreate(Name, OBJ_TEXT, 0, Time[BarRef+1]+9*TimeDiff, Price);
         ObjectSet(Name,OBJPROP_PRICE1,Price+(5*PipPoint));
         ObjectSetText(Name, "$" + DoubleToStr(Price,Digits), 7, "Arial Bold", LineColor);
      }
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsGoldSilver(string Symb)
{
   string sUpper = StringUpperCase(Symb);
   return(StringFind(sUpper, "GOLD", 0) != -1 || StringFind(sUpper, "GLD", 0) != -1 || StringFind(sUpper, "XAU", 0) != -1 ||
   StringFind(sUpper, "SILVER", 0) != -1 || StringFind(sUpper, "XAG", 0) != -1);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double GetPointSize(string Sym)
{
   if(IsGoldSilver(Sym)) return(0.1);
   if(StringFind(Sym, "JPY", 0) != -1) return(0.01);  

   double Pt = 0.0001;
   //Dont check for USD as a US based futures may have these three letters in it.
   //if we check on all other cross pairs then this we should be able to get all main fx pairs
   if(StringFind(Sym, "EUR", 0) != -1) return(Pt);     
   if(StringFind(Sym, "GBP", 0) != -1) return(Pt);  
   if(StringFind(Sym, "AUD", 0) != -1) return(Pt);  
   if(StringFind(Sym, "CAD", 0) != -1) return(Pt);  
   if(StringFind(Sym, "CHF", 0) != -1) return(Pt);  
   if(StringFind(Sym, "NZD", 0) != -1) return(Pt);  
   if(StringFind(Sym, "SGD", 0) != -1) return(Pt);  
   if(StringFind(Sym, "SEK", 0) != -1) return(Pt);  
   if(StringFind(Sym, "DKK", 0) != -1) return(Pt);  
   if(StringFind(Sym, "HKD", 0) != -1) return(Pt);  
   if(StringFind(Sym, "ZAR", 0) != -1) return(Pt);  
   return(MarketInfo(Sym,MODE_POINT)); //Unknown so return symbol point
}   

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string StringUpperCase(string str)
{
   string   s = str;
   int      length = StringLen(str) - 1;
   int      ichar;

   while(length >= 0)
   {
      ichar = StringGetChar(s, length);
      if((ichar > 96 && ichar < 123) || (ichar > 223 && ichar < 256))
         s = StringSetChar(s, length, ichar - 32);
       else
         if(ichar > -33 && ichar < 0)
            s = StringSetChar(s, length, ichar + 224);
      length--;
   }
   return(s);
}

