//+------------------------------------------------------------------+
//|                                             Trending or Ranging? |
//|                                                    ToR_1.20k.mq4 |
//|                                       Copyright © 2008 Tom Balfe |
//|                                                                  |
//| This indicator shows you whether a pair is trending or ranging.  | 
//| For trending markets use moving averages and for ranging         |
//| market use oscillators.                                          |
//|                                                                  |
//| Best of luck in all your trades...                               |
//|                                                                  |
//| Special thanks to whereswaldo!                                   |
//|                                                                  |
//| Version: 1.20k - Krakoukas!                                      |
//|                                                                  |
//| Changelog:                                                       |
//|     1.20k- less code, more timeframes, 5-digits broker support   |
//|     1.20 - added CCI                                             |
//|     1.12 - made color assignment more efficient, made arrow      |
//|            assignment more efficient                             |
//|     1.11 - adjusted fonts, spacing, added ranging, text broken   |
//|     1.10 - added ADX increasing and decreasing notice            |
//|     1.03 - adjusted spacing, fonts, unreleased                   |
//|     1.02 - added arrows, ranging icon, no zero space state       |
//|            for icons/arrows, spacing got messed up, now          | 
//|            fixed                                                 |
//|     1.01 - unreleased, Reduced number of colors, functional      |
//|     1.0  - unreleased, too many colors for ADX values            |
//|                                                                  |
//|                   http://www.forex-tsd.com/members/nittany1.html |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007-2008 Tom Balfe"
#property link      "http://www.forex-tsd.com/members/nittany1.html"
#property link      "redcarsarasota@yahoo.com"
#property indicator_separate_window

//---- user selectable stuff
extern int     SpreadThreshold      = 6;
extern string  ADX_Settings         = "=== ADX Settings ===";
extern int     ADX_trend_level      = 23;
extern int     ADX_trend_strong     = 28;
extern string  CCI_Settings         = "=== CCI Settings ===";
extern int     M1_EntryCCI_Period   = 14;
extern int     M1_TrendCCI_Period   = 50;
extern int     M5_EntryCCI_Period   = 14;
extern int     M5_TrendCCI_Period   = 34;
extern int     M15_EntryCCI_Period  = 6;
extern int     M15_TrendCCI_Period  = 14;
extern int     M30_EntryCCI_Period  = 6;  // Krakoukas sez: Default values here and below may not be optimal.
extern int     M30_TrendCCI_Period  = 14; //                Adjust as needed.
extern int     H1_EntryCCI_Period   = 6;
extern int     H1_TrendCCI_Period   = 14;
extern int     H4_EntryCCI_Period   = 6;
extern int     H4_TrendCCI_Period   = 14;
extern int     D1_EntryCCI_Period   = 6;
extern int     D1_TrendCCI_Period   = 14;
extern int     W1_EntryCCI_Period   = 6;
extern int     W1_TrendCCI_Period   = 14;
extern int     MN1_EntryCCI_Period  = 6;
extern int     MN1_TrendCCI_Period  = 14;


int id_counter=0;

#define INDICATOR_NAME "ToR 1.20k "

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int
init() 
{
   //---- indicator short name
   IndicatorShortName(INDICATOR_NAME);

   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int
deinit()
{
   // That's all folks.
   ObjectsDeleteAll(WindowFind(INDICATOR_NAME), OBJ_LABEL);
   return(0);
}

int 
start()
{
   // clean up first.
   ObjectsDeleteAll(WindowFind(INDICATOR_NAME), OBJ_LABEL);
   id_counter = 0;

   // headers
   createLabel( 2, 15, "SPREAD:");
   createLabel(40, 32, "CHANGE:");
   createLabel(40, 62, "HEADING:");
   createLabel(40, 92, "HEADING:");

   // spread
   double spread=MarketInfo(Symbol(),MODE_SPREAD);
   if (Digits == 3 || Digits > 4) {
      spread /= 10;
   }
   color spreadColor = Lime;
   if (spread>SpreadThreshold) {
      spreadColor = Red;
   }
   createLabel(55, 14, DoubleToStr(spread, 1), spreadColor, 10);
   
   // timeframes
   drawTimeframe(100,  2, "  1 MIN", PERIOD_M1,  M1_EntryCCI_Period,  M1_TrendCCI_Period);
   drawTimeframe(200,  2, "  5 MIN", PERIOD_M5,  M5_EntryCCI_Period,  M5_TrendCCI_Period);
   drawTimeframe(300,  2, " 15 MIN", PERIOD_M15, M15_EntryCCI_Period, M15_TrendCCI_Period);
   drawTimeframe(400,  2, " 30 MIN", PERIOD_M30, M30_EntryCCI_Period, M30_TrendCCI_Period);
   drawTimeframe(500,  2, "   1 HR", PERIOD_H1,  H1_EntryCCI_Period,  H1_TrendCCI_Period);
   drawTimeframe(600,  2, "   4 HR", PERIOD_H4,  H4_EntryCCI_Period,  H4_TrendCCI_Period);
   drawTimeframe(700,  2, "  DAILY", PERIOD_D1,  D1_EntryCCI_Period,  D1_TrendCCI_Period);
   drawTimeframe(800,  2, " WEEKLY", PERIOD_W1,  W1_EntryCCI_Period,  W1_TrendCCI_Period);
   drawTimeframe(900,  2, "MONTHLY", PERIOD_MN1, MN1_EntryCCI_Period, MN1_TrendCCI_Period);
  
   return(0);
} //---- end of main loop
   
//+------------------------------------------------------------------+
//|  Common Functions                                                |
//+------------------------------------------------------------------+

void
drawTimeframe(int x, int y, string label, int timeframe, int entryPeriod, int trendPeriod)
{
   double cci_entry = iCCI(NULL, timeframe, entryPeriod, PRICE_TYPICAL, 0),
          cci_trend = iCCI(NULL, timeframe, trendPeriod, PRICE_TYPICAL, 0),
          cci_entry_1ago = iCCI(NULL, timeframe, entryPeriod, PRICE_TYPICAL, 1),
          cci_trend_1ago = iCCI(NULL, timeframe, trendPeriod, PRICE_TYPICAL, 1);

   createLabel(x+10, y, label);
   drawADX(x, y+15, label, timeframe);
   drawCCI(x, y+45, label, entryPeriod, cci_entry, cci_entry_1ago);
   drawCCI(x, y+75, label, trendPeriod, cci_trend, cci_trend_1ago);
}

void
drawCCI(int x, int y, string label, int period, double value, double ago)
{
   string str_value = value;
   color cci_color = Red;
   if (value > 0) { 
      cci_color = Lime; 
   }
   string hillSide = " DOWNHILL ";
   if (value<ago) {
      hillSide = " UPHILL ";
   }

   createLabel(x, y, " CCI(" + period +") "+StringSubstr(str_value,0,6)+" ", cci_color, 9);
   createLabel(x+5, y+15, hillSide, Silver);
}

void
drawADX(int x, int y, string label, int timeframe)
{
   double adx      = iADX(NULL,timeframe,14,PRICE_CLOSE,0,0),
          adx_1ago = iADX(NULL,timeframe,14,PRICE_CLOSE,0,1),
          di_p     = iADX(NULL,timeframe,14,PRICE_CLOSE,1,0),
          di_m     = iADX(NULL,timeframe,14,PRICE_CLOSE,2,0);
   string str_adx = adx, ranging;
   color adx_color; 
   if (adx < ADX_trend_level) {
      ranging = " RANGING ";
   } else if (adx > adx_1ago) {
      ranging = " STRONGER ";
   } else {
      ranging = " WEAKER ";
   }
   if (adx < ADX_trend_level) { 
      adx_color = LightSkyBlue;
   } else if (di_p > di_m) { 
      adx_color = Lime; 
   } else {
      adx_color = Red;
   }
   createLabel(x, y, " ADX "+StringSubstr(str_adx,0,5)+" ", adx_color, 9);
   createLabel(x+65, y, AssignArrow(adx,di_p,di_m), adx_color, 9, "Wingdings");
   createLabel(x+5, y+15, ranging, Silver);
}

void
createLabel(int x, int y, string text, color col = LightSteelBlue, int size =8, string font="Arial Bold")
{
   id_counter += 1;
   string id = "obj"+id_counter;
   ObjectCreate(id,OBJ_LABEL, WindowFind(INDICATOR_NAME), 0, 0);
   ObjectSetText(id,text,size, font,col);
   ObjectSet(id, OBJPROP_CORNER, 0);
   ObjectSet(id, OBJPROP_XDISTANCE, x);
   ObjectSet(id, OBJPROP_YDISTANCE, y);
}

string 
AssignArrow (double adx_time, double di_p_time, double di_m_time)
{                                
   if ((adx_time < ADX_trend_level) && (adx_time != 0)) {
      return ("h");
   } else if (adx_time < ADX_trend_strong ) {
      if (di_p_time > di_m_time) {
         return ("ì");
      } else {
         return ("î");
      }
   } else {
      if (di_p_time > di_m_time) {
         return ("é");
      } else {
         return ("ê");
      }
   }
}

