//
// "00-Chart_v102.mq4" -- draw chart
//
//    Ver. 1.00  2008/09/26(Fri)  initial version
//    Ver. 1.01  2009/01/02(Mon)  draw Bollinger Bands/Moving Average
//    Ver. 1.02  2009/06/17(Wed)  added DailyShowSH1/2/EH1/2
// 
#property  copyright  "00 - 00mql4@gmail.com"
#property  link       "http://www.mql4.com/"

//---- defines
#define SEC_PER_DAY   86400
#define SEC_PER_HOUR  3600

//---- indicator settings
#property  indicator_separate_window

#property  indicator_buffers  7

#property  indicator_color1  CLR_NONE  // 0: close value
#property  indicator_color2  CLR_NONE  // 1: high value
#property  indicator_color3  CLR_NONE  // 2: low value
#property  indicator_color4  Yellow    // 3: Bollinger Bands, upper line
#property  indicator_color5  Yellow    // 4: Bollinger Bands, center line
#property  indicator_color6  Yellow    // 5: Bollinger Bands, lower line
#property  indicator_color7  Red       // 6: Moving Average

#property  indicator_width1  1
#property  indicator_width2  1
#property  indicator_width3  1
#property  indicator_width4  1
#property  indicator_width5  1
#property  indicator_width6  1
#property  indicator_width7  1

#property  indicator_style1  STYLE_SOLID
#property  indicator_style2  STYLE_SOLID
#property  indicator_style3  STYLE_SOLID
#property  indicator_style4  STYLE_DOT
#property  indicator_style5  STYLE_DOT
#property  indicator_style6  STYLE_DOT
#property  indicator_style7  STYLE_SOLID

//---- indicator parameters
extern int     ServerGMT     = 0;          // GMT time offset, 0: ODL, 9: 121, 3: FXDD,...
extern string  symbol        = "";         // symbol
extern double  DailyShowSH1  = 0.0;        // GMT+0, display begin time 1 in hour
extern double  DailyShowEH1  = 0.0;        // GMT+0, display end time 1 in hour
extern double  DailyShowSH2  = 0.0;        // GMT+0, display begin time 2 in hour
extern double  DailyShowEH2  = 0.0;        // GMT+0, display end time 2 in hour
extern string  DayOfWeekShow = "1111111";  // GMT+0, display day of week, 1000000: Sun 100000: Mon 10000: Tue 1000: Wed 100: Thu 10: Fri 1: Sat
extern int     nMaxBars      = 10000;      // number of bars
extern bool    bDrawBar      = true;       // draw bars
extern bool    bDrawBB       = true;       // draw Bollinger Bands
extern int     bb_period     = 20;         // Bollinger Bands, period
extern double  bb_sigma      = 2.0;        // Bollinger Bands, sigma
extern bool    bDrawMA       = true;       // draw Moving Average
extern int     ma_period     = 100;        // Moving Average, period
extern int     ma_method     = MODE_SMA;   // Moving Average, period
extern string  symTimeRef    = "";         // reference symbol for time
extern color   cUpLine       = Lime;       // up bar, color of line
extern color   cUpFrame      = Lime;       // up bar, color of frame
extern color   cUpBody       = Black;      // up bar, color of bar
extern color   cDownLine     = Lime;       // down bar, color of line
extern color   cDownFrame    = Lime;       // down bar, color of frame
extern color   cDownBody     = White;      // down bar, color of bar
extern int     nBodyWidth    = 2;          // bar width

//---- indicator buffers
double BufferClose[];     // 0: close value
double BufferHigh[];      // 1: high value
double BufferLow[];       // 2: low value
double BufferBbUpper[];   // 3: Bollinger Bands, upper line
double BufferBbCenter[];  // 4: Bollinger Bands, center line
double BufferBbLower[];   // 5: Bollinger Bands, lower line
double BufferMa[];        // 6: Moving Average

//---- vars
string sIndicatorName;
string sPrefix;
string sIndSelf        = "00-Chart_v102";
string sUpLineName     = "0upLine";
string sUpFrameName    = "1upFrame";
string sUpBodyName     = "2upBody";
string sDownLineName   = "0downLine";
string sDownFrameName  = "1downFrame";
string sDownBodyName   = "2downBody";
bool   bDayOfWeekShow[7];

//----------------------------------------------------------------------
string TimeFrameToStr(int timeFrame)
{
    switch (timeFrame) {
    case 1:     return("M1");
    case 5:     return("M5");
    case 15:    return("M15");
    case 30:    return("M30");
    case 60:    return("H1");
    case 240:   return("H4");
    case 1440:  return("D1");
    case 10080: return("W1");
    case 43200: return("MN");
    }
    
    return("??");
}

//----------------------------------------------------------------------
double clip24(double t)
{
    if (t >= 24) {
	t -= 24;
    } else if (t < 0) {
	t += 24;
    }
    
    return(t);
}

//----------------------------------------------------------------------
void init()
{
    if (symbol == "") {
	symbol = Symbol();
    }
    if (symTimeRef == "") {
	symTimeRef = symbol;
    }
    
    string tf = TimeFrameToStr(Period());
    sIndicatorName = sIndSelf + "(" + symbol + "," + tf + ")";
    sPrefix = sIndicatorName;
    
    IndicatorShortName(sIndicatorName);
    
    SetIndexStyle(0, DRAW_LINE);
    SetIndexStyle(1, DRAW_LINE);
    SetIndexStyle(2, DRAW_LINE);
    SetIndexStyle(3, DRAW_LINE);
    SetIndexStyle(4, DRAW_LINE);
    SetIndexStyle(5, DRAW_LINE);
    SetIndexStyle(6, DRAW_LINE);
    
    SetIndexBuffer(0, BufferClose);
    SetIndexBuffer(1, BufferHigh);
    SetIndexBuffer(2, BufferLow);
    SetIndexBuffer(3, BufferBbUpper);
    SetIndexBuffer(4, BufferBbCenter);
    SetIndexBuffer(5, BufferBbLower);
    SetIndexBuffer(6, BufferMa);
    
    SetIndexLabel(0, symbol + " Close");
    SetIndexLabel(1, symbol + " High");
    SetIndexLabel(2, symbol + " Low");
    SetIndexLabel(3, symbol + " BB(" + bb_period + ") upper");
    SetIndexLabel(4, symbol + " BB(" + bb_period + ") center");
    SetIndexLabel(5, symbol + " BB(" + bb_period + ") lower");
    SetIndexLabel(6, symbol + " MA(" + ma_period + ")");
    
    SetIndexDrawBegin(0, 0);
    SetIndexDrawBegin(1, 0);
    SetIndexDrawBegin(2, 0);
    SetIndexDrawBegin(3, bb_period);
    SetIndexDrawBegin(4, bb_period);
    SetIndexDrawBegin(5, bb_period);
    int n = ma_period;
    if (ma_method != MODE_SMA) {
	n = n * 3;
    }
    SetIndexDrawBegin(6, n);
    
    // time
    DailyShowSH1 = clip24(DailyShowSH1 + ServerGMT);
    DailyShowEH1 = clip24(DailyShowEH1 + ServerGMT);
    DailyShowSH2 = clip24(DailyShowSH2 + ServerGMT);
    DailyShowEH2 = clip24(DailyShowEH2 + ServerGMT);
    
    int mask = StrToDouble(DayOfWeekShow);
    for (int i = 0; i < 7; i++) {
	bool b = !(mask % 10 == 0);
	bDayOfWeekShow[6 - i] = b;
	mask /= 10;
    }
}

//----------------------------------------------------------------------
void deinit()
{
    int i;
    int n = ObjectsTotal();
    
    for (i = n - 1; i >= 0; i--) {
	string sName = ObjectName(i);
	if (StringFind(sName, sPrefix) == 0) {
	    ObjectDelete(sName);
	}
    }
}

//----------------------------------------------------------------------
string getBarName(int i, string sName)
{
    return(sPrefix + " bar" + i + " " + sName);
}

//----------------------------------------------------------------------
void barCreate(int win, int i)
{
    string sUpLine    = getBarName(i, sUpLineName);
    string sUpFrame   = getBarName(i, sUpFrameName);
    string sUpBody    = getBarName(i, sUpBodyName);
    string sDownLine  = getBarName(i, sDownLineName);
    string sDownFrame = getBarName(i, sDownFrameName);
    string sDownBody  = getBarName(i, sDownBodyName);
    
    // up bar
    ObjectCreate(sUpLine, OBJ_TREND, win, 0, 0);
    ObjectSet(sUpLine, OBJPROP_RAY, 0);
    ObjectSet(sUpLine, OBJPROP_WIDTH, 1);
    ObjectSet(sUpLine, OBJPROP_COLOR, cUpLine);
	    
    ObjectCreate(sUpFrame, OBJ_TREND, win, 0, 0);
    ObjectSet(sUpFrame, OBJPROP_RAY, 0);
    ObjectSet(sUpFrame, OBJPROP_WIDTH, nBodyWidth + 2);
    ObjectSet(sUpFrame, OBJPROP_COLOR, cUpFrame);
	    
    ObjectCreate(sUpBody, OBJ_TREND, win, 0, 0);
    ObjectSet(sUpBody, OBJPROP_RAY, 0);
    ObjectSet(sUpBody, OBJPROP_WIDTH, nBodyWidth);
    ObjectSet(sUpBody, OBJPROP_COLOR, cUpBody);
    
    // down bar
    ObjectCreate(sDownLine, OBJ_TREND, win, 0, 0);
    ObjectSet(sDownLine, OBJPROP_RAY, 0);
    ObjectSet(sDownLine, OBJPROP_WIDTH, 1);
    ObjectSet(sDownLine, OBJPROP_COLOR, cDownLine);
	    
    ObjectCreate(sDownFrame, OBJ_TREND, win, 0, 0);
    ObjectSet(sDownFrame, OBJPROP_RAY, 0);
    ObjectSet(sDownFrame, OBJPROP_WIDTH, nBodyWidth + 2);
    ObjectSet(sDownFrame, OBJPROP_COLOR, cDownFrame);
	    
    ObjectCreate(sDownBody, OBJ_TREND, win, 0, 0);
    ObjectSet(sDownBody, OBJPROP_RAY, 0);
    ObjectSet(sDownBody, OBJPROP_WIDTH, nBodyWidth);
    ObjectSet(sDownBody, OBJPROP_COLOR, cDownBody);
}

//----------------------------------------------------------------------
void barMove(int i, datetime t, double open, double close, double high, double low)
{
    string sUpLine    = getBarName(i, sUpLineName);
    string sUpFrame   = getBarName(i, sUpFrameName);
    string sUpBody    = getBarName(i, sUpBodyName);
    string sDownLine  = getBarName(i, sDownLineName);
    string sDownFrame = getBarName(i, sDownFrameName);
    string sDownBody  = getBarName(i, sDownBodyName);
    
    double upOpen = Point;
    double upClose = Point;
    double upHigh = Point;
    double upLow = Point;
    double downOpen = Point;
    double downClose = Point;
    double downHigh = Point;
    double downLow = Point;
    
    if (bDrawBar) {
	if (close >= open) {
	    upOpen  = open;
	    upClose = close;
	    upHigh  = high;
	    upLow   = low;
	} else {
	    downOpen  = open;
	    downClose = close;
	    downHigh  = high;
	    downLow   = low;
	}
    }
    
    ObjectMove(sUpLine,  0, t, upHigh);
    ObjectMove(sUpLine,  1, t, upLow);
    ObjectMove(sUpFrame, 0, t, upOpen);
    ObjectMove(sUpFrame, 1, t, upClose);
    ObjectMove(sUpBody,  0, t, upOpen);
    ObjectMove(sUpBody,  1, t, upClose);
    
    ObjectMove(sDownLine,  0, t, downHigh);
    ObjectMove(sDownLine,  1, t, downLow);
    ObjectMove(sDownFrame, 0, t, downOpen);
    ObjectMove(sDownFrame, 1, t, downClose);
    ObjectMove(sDownBody,  0, t, downOpen);
    ObjectMove(sDownBody,  1, t, downClose);
}

//----------------------------------------------------------------------
void start()
{
    int i, limit;
    int counted_bars = IndicatorCounted();
    
    //---- last counted bar will be recounted
    if (counted_bars > 0) {
	counted_bars--;
    }
    
    limit = Bars - counted_bars;
    int limit0 = limit;
    if (nMaxBars > 0) {
	limit = MathMin(limit, nMaxBars);
    }
    
    int win = WindowFind(sIndicatorName);
    if (win < 0) {
	win = 1;
    }
    
    int ibar, idata;
    for (ibar = 0, idata = 0; ibar < limit; idata++) {
	datetime t = iTime(symTimeRef, 0, idata);
	if (t <= 0) {
	    break;
	}
	double h = TimeHour(t) + TimeMinute(t) / 60.0;
	bool bShow1 = (h >= DailyShowSH1 && h < DailyShowEH1);
	bool bShow2 = (h >= DailyShowSH2 && h < DailyShowEH2);
	bool bShowAll = (DailyShowSH1 == DailyShowEH1 && DailyShowSH2 == DailyShowEH2);
	bool bShowDow = bDayOfWeekShow[TimeDayOfWeek(t + ServerGMT * SEC_PER_HOUR)];
	if (bShowDow && (bShow1 || bShow2 || bShowAll)) {
	    int x = iBarShift(symbol, 0, t);
	    BufferClose[ibar] = iClose(symbol, 0, x);
	    BufferHigh[ibar] = iHigh(symbol, 0, x);
	    BufferLow[ibar] = iLow(symbol, 0, x);
	    
	    // bar
	    barCreate(win, ibar);
	    x = iBarShift(symbol, 0, t, true);
	    double open = 0;
	    double close = 0;
	    double high = 0;
	    double low = 0;
	    if (x >= 0) {
		open = iOpen(symbol, 0, x);
		close = iClose(symbol, 0, x);
		high = iHigh(symbol, 0, x);
		low = iLow(symbol, 0, x);
	    }
	    barMove(ibar, iTime(symTimeRef, 0, ibar), open, close, high, low);
	    
	    ibar++;
	}
    }
    int nBar = ibar;
    
    for (ibar = nBar; ibar < limit; ibar++) {
	barCreate(win, ibar);
	barMove(ibar, iTime(symTimeRef, 0, ibar), 0, 0, 0, 0);
    }
    
    for (ibar = nBar; ibar < limit; ibar++) {
	BufferClose[ibar] = EMPTY_VALUE;
	BufferHigh[ibar] = EMPTY_VALUE;
	BufferLow[ibar] = EMPTY_VALUE;
    }
    
    for (ibar = 0; ibar < limit; ibar++) {
	if (ibar < nBar - bb_period && bDrawBB) {
	    double ave = iMAOnArray(BufferClose, 0, bb_period, 0, MODE_SMA, ibar);
	    double sd = iStdDevOnArray(BufferClose, 0, bb_period, 0, MODE_SMA, ibar);
	    BufferBbUpper[ibar] = ave + sd * bb_sigma;
	    BufferBbCenter[ibar] = ave;
	    BufferBbLower[ibar] = ave - sd * bb_sigma;
	} else {
	    BufferBbUpper[ibar] = EMPTY_VALUE;
	    BufferBbCenter[ibar] = EMPTY_VALUE;
	    BufferBbLower[ibar] = EMPTY_VALUE;
	}
    }
    
    for (ibar = 0; ibar < limit; ibar++) {
	if (ibar < nBar - ma_period && bDrawMA) {
	    BufferMa[ibar] = iMAOnArray(BufferClose, 0, ma_period, 0, ma_method, ibar);
	} else {
	    BufferMa[ibar] = EMPTY_VALUE;
	}
    }
    
    WindowRedraw();
}

