//+-------------------------------------------------------------------------------------------+
//|                                                                                           |
//|                                SonicR VSA Histogram.mq4                                   |
//|                                                                                           |
//+-------------------------------------------------------------------------------------------+
#property copyright "Copyright © 2012 traderathome"
#property link      "email:   traderathome@msn.com"

/*---------------------------------------------------------------------------------------------
Overview, _v2:
 
This indicator creates an multi-colored volume histogram with the four features listed here
and more fully described below.
1. The volume histogram bars have special colors to denote special volume/price situations. 
2. The volume histogram bars can be set to adjust width as you zoom in/out on the chart. 
3. The volume histogram bars can be manually widened.
4. The volume histogram bars qualifying as "Climax" bars can trigger an alert.

1. Special Volume/Price Situations-
   Volume bars emphasized with special colors to denote special volume/price situations help  
   you quickly associate these volume bars with the correct candlesticks.
   A. Volume Bars for Climax Candles  
      Volume bars where the product of candle spread x candle volume is highest for the 20 most
      recent candles.  Bars for bull candles are green and for bear candles are red. 
   B. Volume Bars for Candles Rising Above Average Volume 
      Volume bars where volume is greater than the product of 1.38 x the average volume of the 
      10 most recent candles.  These bars are blue. 

2. Automatic_Zoom-
   This feature will have widths automatically adjust, with the next arriving tick, to what 
   is appropriate for the chart zoom setting.  When MT4 is first started the bar widths are 
   incorrect until the first tick arrives.  If ticks are slow coming, or if there is no live
   feed (weekend/holiday), you can force the width adjustment by switching the chart TF.  
      
   The widths are set by code based on encountered "WindowBarsPerChart( )".  As you zoom
   out, there are more.  As you zoom in there are less.  This might be affected by the 
   width capacity of the monitor.  Extra wide monitors, if showing more bars per chart
   on all zoom settings than what the code expects, can result in narrower bars displayed 
   than intended.  This is because the additional bars encountered are interpreted by the 
   code as meaning the chart has been zoomed out an extra step or more, and the code displays
   the narrower bar widths that would otherwise be appropriate.  Downsizing charts presents a 
   problem also, causing bar widths that are too wide because the fewer bars encountered are 
   interpreted by the code as meaning the chart has been zoomed in an extra step or more.  It
   therefore displays the wider bars that would otherwise be appropriate.  So, in cases of an 
   extra wide monitor or downsizing of charts, undesirable results can occur and you should 
   use the manual width adjustment.  
            
3. Manual_Zoom_01234-
   For reasons stated in #2 above, or if you tend to use only the standard zoom setting, or 
   some other single zoom setting, manually selecting the zoom setting is the best choice.  
   Selecting "0" sets widths appropriate for the two chart zoom out/"-" settings that are
   below the standard chart zoom setting.  Selecting "1" sets width appropriate for the Mt4
   standard/default chart zoom setting.  Apply "2,3, or 4" for zooming in/"+" on a chart from
   the standard zoom setting to get the wider bars that are appropriate.  
   
4. Sound and Sound/Text Alerts
   This indicator includes both a sound only alert, and a sound with text alert, that trigger 
   once per TF (M5 and greater) at the first qualification of the volume bar as a Climax bar.
   The single input "Climax_Volume_Alert_Off_On_012" controls this function.  "0" = Off, 
   "1" is for the sound alert, and "2" is for the sound with text alert.  Inputs outside this 
   range default to "0".
     
This indicator can be turned on/off without having to remove it from the chart, preserving the 
chart settings.  You can elect not to show the indicator ShortName in the study sub-window.
This might help if multiple small downsized charts are used within the MT4 main chart window.

Changes from previous release 04-04-2012 to current release 05-01-2012:
01 - Corrected name of wave file to call for alert #1.
02 - Revised coding of ShortName to recognize alerts are automatically off for M1 TF charts.

    
                                                                    - Traderathome, 05-01-2012
-----------------------------------------------------------------------------------------------
Acknowledgements:
BetterVolume.mq4 - for "climax" candle code definition (BetterVolume_v1.4).

----------------------------------------------------------------------------------------------
Suggested Colors            White Chart        Black Chart      

Current_Volume              Black              WhiteSmoke                              
Historic_Volume             C'226,231,233'     C'45,50,53'       
Above_Average               C'45,81,206'       C'62,158,255' 
Climax_Bull                 C'0,170,85'        C'33,207,77'       
Climax_Bear                 C'222,18,80'       C'244,0,0'
Histo_Top_line              SlateGray          Gray
 
Note: Suggested colors coincide with the colors of the SonicR VSA Candlesticks indicator.                                        
---------------------------------------------------------------------------------------------*/


//+-------------------------------------------------------------------------------------------+
//| Indicator Global Inputs                                                                   |                                                        
//+-------------------------------------------------------------------------------------------+ 
#property indicator_separate_window
#property indicator_buffers 6
 
#property indicator_color1  WhiteSmoke
#property indicator_color2  C'45,50,53' 
#property indicator_color3  C'62,158,255'     
#property indicator_color4  C'33,207,77'  
#property indicator_color5  C'244,0,0'
#property indicator_color6  Gray 
  
//Global External Inputs 
extern bool   Indicator_On                    = true;
extern bool   Automatic_Zoom                  = false;
extern int    Manual_Zoom_01234               = 1;
extern bool   Show_Climax_Volume              = true;
extern bool   Show_Above_Average_Volume       = true;
extern int    Climax_Volume_Alert_Off_On_012  = 0;

//Global Buffers and Variables
bool          FLAG_deinit    = false;    
bool          Alert_Allowed  = true;         
int           i,j,n,Wide_Bar_Width;
double        Historic[],Current[],AboveAverage[],ClimaxBull[],ClimaxBear[],TopLine[],
              av,Range,Value2,HiValue2,tempv2;
string        ShortName;
int           Climax_Analysis_Period          = 20;
int           Volume_Averaging_Period         = 10; 
double        Above_Average_Volume_Factor     = 1.38;

//Automatic Zoom Parameters
string __                              = "";
string Part_2                          = "Auto-Width_Adjustments:";
string note1                           = "Wide monitors may require";
string note2                           = "WindowsBarsPerChart be increased";
string note3                           = "for these chart zoom settings:";
int    Zoom_Out_2_Bars                 = 1200;
int    Zoom_Out_1_Bars                 = 500;
int    Zoom_Std_Bars                   = 200;
int    Zoom_In_1_Bars                  = 100;
int    Zoom_In_2_Bars                  = 60;

//+-------------------------------------------------------------------------------------------+
//| Custom indicator initialization function                                                  |
//+-------------------------------------------------------------------------------------------+
int init()
  {
  FLAG_deinit  = false;
  
  //Automatically Adjust Width    
  if(Automatic_Zoom)   
    {
          if (WindowBarsPerChart( ) >= Zoom_Out_2_Bars) {Wide_Bar_Width = 1;} 
    else {if (WindowBarsPerChart( ) >= Zoom_Out_1_Bars) {Wide_Bar_Width = 2;} 
    else {if (WindowBarsPerChart( ) >= Zoom_Std_Bars)   {Wide_Bar_Width = 2;} 
    else {if (WindowBarsPerChart( ) >= Zoom_In_1_Bars)  {Wide_Bar_Width = 3;} 
    else {if (WindowBarsPerChart( ) >= Zoom_In_2_Bars)  {Wide_Bar_Width = 6;} 
    else {Wide_Bar_Width = 13;} }}}}
    }
  else //Manually Adjust Width
    {
          if (Manual_Zoom_01234 <= 0) {Wide_Bar_Width = 1;}
    else {if (Manual_Zoom_01234 == 1) {Wide_Bar_Width = 2;}
    else {if (Manual_Zoom_01234 == 2) {Wide_Bar_Width = 3;}
    else {if (Manual_Zoom_01234 == 3) {Wide_Bar_Width = 6;}
    else {Wide_Bar_Width = 13;} }}}
    }

  //Indicators       
  SetIndexBuffer(0, Current);
  SetIndexStyle(0, DRAW_HISTOGRAM, 0, Wide_Bar_Width);       
  SetIndexBuffer(1, Historic);                  
  SetIndexStyle(1, DRAW_HISTOGRAM, 0, Wide_Bar_Width);  
  if(Show_Above_Average_Volume)
    {        
    SetIndexBuffer(2, AboveAverage);   
    SetIndexStyle(2, DRAW_HISTOGRAM, 0, Wide_Bar_Width);
    }      
  if(Show_Climax_Volume)
    {
    SetIndexBuffer(3, ClimaxBull);
    SetIndexStyle(3, DRAW_HISTOGRAM, 0, Wide_Bar_Width);   
    SetIndexBuffer(4, ClimaxBear);        
    SetIndexStyle(4, DRAW_HISTOGRAM, 0, Wide_Bar_Width);                  
    }  
  SetIndexBuffer(5, TopLine);  
  SetIndexStyle(5, DRAW_LINE); 
                    
  //Indicator ShortName
  if(Show_Climax_Volume)
    {
    ShortName= "SonicR Climax Volume   ";
    if(Show_Above_Average_Volume) {ShortName= "SonicR VSA   ";}  
    if(Climax_Volume_Alert_Off_On_012 == 0) {ShortName= ShortName + "Alert off.   ";}
    else 
      {
      if(Climax_Volume_Alert_Off_On_012 == 1) 
        {
        if(Period() >1){ShortName= ShortName + " Sound Alert On.   ";}
        else {ShortName= ShortName + "Alert off.   ";} 
        }
      else if(Climax_Volume_Alert_Off_On_012 == 2) 
        {
        if(Period() >1){ShortName= ShortName + " Text Alert On.   ";}
        else {ShortName= ShortName + "Alert off.   ";} 
        }
      }  
    }    
  if((!Show_Climax_Volume) && (Show_Above_Average_Volume)) {ShortName= "SonicR Rising Volume   ";} 
  else if((!Show_Climax_Volume) && (!Show_Above_Average_Volume)) {ShortName= "SonicR Volume   ";}      
  IndicatorShortName (ShortName);       
                           
  //Indicator subwindow data                  
  SetIndexLabel(0,  NULL);
  SetIndexLabel(1,  NULL); 
  SetIndexLabel(2,  NULL);
  SetIndexLabel(3,  NULL);
  SetIndexLabel(4,  NULL);
  SetIndexLabel(5,  NULL);
  SetIndexLabel(6,  NULL);
  SetIndexLabel(7,  NULL); 
  
  //Alert input range control
  if((Climax_Volume_Alert_Off_On_012 < 0) || (Climax_Volume_Alert_Off_On_012 > 2)) 
    {Climax_Volume_Alert_Off_On_012 = 0;}
       
  return(0);
  }
  
//+-------------------------------------------------------------------------------------------+
//| Custom indicator deinitialization function                                                |
//+-------------------------------------------------------------------------------------------+
int deinit()
  {
  //Comment("");
  return(0);
  }
  
//+-------------------------------------------------------------------------------------------+
//| Custom indicator iteration function                                                       |
//+-------------------------------------------------------------------------------------------+
int start()
  {
  //If Indicator is "Off" deinitialize only once, not every tick 
  if (!Indicator_On)
    {
    IndicatorShortName("SonicR VSA  -off.   ");

    if (!FLAG_deinit) {deinit(); FLAG_deinit = true;}
    return(0);
    }
    
  //Otherwise indicator is "On" & chart TF is in display range, so proceed.   
  if(Automatic_Zoom) {init();}
  else {deinit(); FLAG_deinit = false;}

  //With each tick all bars are updated.  No changes occur in previous bars because incoming
  //data for them is now static.  The per tick incoming data for the current bar, however, is 
  //used to update the current bar totals which are recalculated/re-displayed.            
  for(i = Bars-1-IndicatorCounted(); i >= 0; i--)          
    {
    //Clear buffers   
    Current[i]      = 0;
    Historic[i]     = 0;
    AboveAverage[i] = 0;   
    ClimaxBull[i]   = 0;
    ClimaxBear[i]   = 0;    
    Value2          = 0;
    HiValue2        = 0;
    tempv2          = 0; 
    av              = 0;
    
    //Define Historic and Current "normal" histogram bars
    if(i > 0)  {Historic[i] = Volume[i];}   
    if(i == 0) {Current[i]  = Volume[i];}        

    //Compute Average Volume and Volume Rising Above Average    
    if(Show_Above_Average_Volume)
      {       
      for (j = i; j < (i+Volume_Averaging_Period); j++) {av = av + Volume[j];}   
      av = av / Volume_Averaging_Period;                           
      if (Volume[i] > av * Above_Average_Volume_Factor)
        {
        AboveAverage[i] = NormalizeDouble(Volume[i],0);
        } 
      }//End Average & Rising Volume
             
    //Compute "Climax" Parameter (HiValue2)
    if(Show_Climax_Volume)
      {                  
      Range = (High[i]-Low[i]);
      Value2 = Volume[i]*Range;                 
      for (n=i;n<i+Climax_Analysis_Period;n++)
        {
        tempv2 = Volume[n]*((High[n]-Low[n])); 
        if (tempv2 >= HiValue2) {HiValue2 = tempv2;}    
        }
      
      //Define Current and Historic "Climax" bars                  
      if(Value2 >= HiValue2)
        { 
        //Bull Candle                                  
        if (Close[i] > Open[i]) 
          {
          ClimaxBull[i] = NormalizeDouble(Volume[i],0);
          }
        //Bear Candle  
        else if (Close[i] <= Open[i]) 
          {
          ClimaxBear[i] = NormalizeDouble(Volume[i],0);
          }
               
        //Sound & Text Alert
        if((i == 0) && (Climax_Volume_Alert_Off_On_012 > 0) && 
          (Show_Climax_Volume) && (Period() >1))         
          {
          if(Time[i]+30 >= TimeCurrent( )) {Alert_Allowed = true;}
          if(Alert_Allowed)                  
            {                  
            if(Climax_Volume_Alert_Off_On_012 == 1) {PlaySound("alert2.wav");}
            if(Climax_Volume_Alert_Off_On_012 == 2) {Alert (Symbol()+", TF "+Period()+", volume alert!");} 
            Alert_Allowed = false;         
            }
          }//End Alert                               
        }//End Define Current & Historic
      }//End Compute Climax                
    }//End "for i" loop  
    
  //Top Line of Histogram    
  for(i = Bars-1-IndicatorCounted(); i >= 1; i--)       
    {    
    TopLine[i] = Volume[i];
    } 
        
  return(0);
  }

//+-------------------------------------------------------------------------------------------+
//|Custom indicator end                                                                       |
//+-------------------------------------------------------------------------------------------+    
         