//+------------------------------------------------------------------+
//|             AuthorizedSSBODynamicBreakoutBoxFinalEdition nmc.mq4 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+

#property copyright "Copyright © 2012, SSBO Team"
#property link      "http://www.forexfactory.com/showthread.php?t=302007"
#property version   "1.00"
#property strict
#property indicator_chart_window

#property indicator_buffers 8

extern int       BoxLength                        = 21;
extern double    BoxRange                         = 28;
extern string    BoxTimeFrame                     = "0";
extern double    BoxBufferPips                    = 1;
extern int       MinBarsClosedOutsideBO           = 0;
extern int       MaxBreakoutTradesPerBox          = 4;
extern bool      InitialBreakoutDirectionOnly     = false;
extern bool      LongTrades                       = true;
extern bool      ShortTrades                      = true;
extern double    QuickTakeProfit                  = 20;
extern double    StopLossOverride                 = 0;
extern double    EmergencyStopLoss                = 100;
extern bool      BoxMartingale                    = true;
extern bool      AutoReduceBoxSize                = true;
extern int       DaysBack                         = 100;
extern bool      SignalMail                       = false;
extern bool      SignalAlert                      = false;
// Cosmetics inputs
extern bool      ShowFibs                         = false;
extern string    FibSequence                      = "0.618,1.382,2.618,4.236,5.854,7.472,9.090,11.708,14.326";
extern int       FibsFontSize                     = 9;
extern color     FibsLinesColor                   = LightGray;
extern int       FibsLinesWidth                   = 1;
extern bool      ShowSwings                       = false;
extern int       SwingsFontSize                   = 9;
extern color     SwingsLinesColor                 = Wheat;
extern int       SwingsLinesWidth                 = 1;
extern int       BoxFontSize                      = 9;
extern color     BoxColor                         = 11184640;
extern color     ContBoxColor                     = DarkSlateGray;
extern bool      ContBoxFullColored               = true;
extern color     BoxBufferLinesColor              = 11184640;
extern int       BoxBufferLinesWidth              = 2;
extern color     ContBoxBufferLinesColor          = DarkSlateGray;
extern int       ContBoxBufferLinesWidth          = 1;
extern color     BreakoutPriceColor               = 11184640;
extern int       BreakoutPriceWidth               = 2;
extern color     ContBoxPriceColor                = DarkSlateGray;
extern int       ChartDisplay                     = 3;
extern int       DisplayPanelFontSize             = 11;
extern color     StatsColor                       = Black;
extern color     StatsBGColor                     = DarkSalmon;
extern color     PipsProfitColor                  = DarkGreen;
extern color     PipsLossColor                    = MediumVioletRed;
extern int       StatsCorner                      = 0;
extern bool      BoxVerticalLineDelimiter         = false;
extern color     BoxVerticalLineColor             = DarkSlateGray;
extern int       SwingLabelsFontSize              = 9;
extern color     SwingLabelsColor                 = Yellow;
extern int       BuySignalArrowCode               = 2;
extern color     BuySignalArrowColor              = 11193702;
extern int       BuySignalArrowWidth              = 3;
extern int       SellSignalArrowCode              = 2;
extern color     SellSignalArrowColor             = 5275647;
extern int       SellSignalArrowWidth             = 3;
extern string    Fonts                            = "Calibri";

//************************************************************************************************************************************************************
//************************************************************************************************************************************************************

//Buffers
double highBO[];
double lowBO[];
double highBOcont[];
double lowBOcont[];
double BoxStart[];
double BoxEnd[];
double BuySignal[];
double SellSignal[];

//************************************************************************************************************************************************************

bool open_new_box;
bool g_bFirstRun;

int _bounce_counts[];
int wins_bounce_counts[];
int _consecutive_losses; 
int _curr_consecutive_losses;
int _consecutive_wins; 
int _curr_consecutive_wins;

int tf;
int btf;
int InitialBreakoutDirection;
int space_font_size;
int num_long_boxes;
int num_short_boxes;
datetime LastTradeCloseTime;
int trigger_direction;
datetime LastTakeProfitTime;

int _period;
int _minP;
int _maxP;
int _prevP;
int BarsBack;
datetime g_dtLastBarTime;
int _trade_win_set; 
int _trade_loss_set;
int last_trigger_direction;
int num_total_longs;
int num_total_shorts;
int num_boxes;

int num_wins;
int num_losses;
int win_set;
int loss_set;
int _box_curr_trade_dir; 
int _box_total_trades; 
int _box_profit_trades;
int counted_bars;
int num_closed_longs;
int num_closed_shorts;

int i0;
int i1;
int i2;
int i3;
int i4;
int i5;
int i6;
int i7;
int i8;
int i9;
int t0;
int t1;
int t2;
int t3;
int t4;
int t5;
int t6;
int t7;
int t8;
int t9;
int x0;
int x1;
int x2;
int x3;
int x4;
int x5;
int x6;
int x7;
int x8;
int x9;
int q0;
int q1;
int q2;
int q3;
int q4;
int q5;
int q6;
int q7;
int q8;
int q9;
int v0;
int v1;
int v2;
int v3;
int v4;
int v5;
int v6;
int v7;
int v8;
int v9;
int e1;
int e2;
int z0;
int z1;
int z2;
int z3;
int k1;
int k2;

int TF[]={0,1,5,15,30,60,240,1440,10080,43200};

double CZone[10000][6];
double TakeProfit;
double StopLoss;
double WinRatio;
double LblDst;
double BPips;
double closed_longs_profit;
double closed_shorts_profit;
double upper;
double lower;
double best_buy;
double best_sell;

double mult;
double SL_pips;
double total_losses;
double trade_set_win_ratio;
double closed_longs_loss;
double closed_shorts_loss;
double Tdist;
double LongBO;
double ShortBO;
double loss;

double Temp[200][200];
double d[500];
double Fib[20];
double tp_val;
double trigger_price;
int num_weeks;
double avgBuys;
double avgSells;
double _Range;
double upperBox;
double lowerBox;

double d0;
double d1;
double d2;
double d3;
double d4;
double d5;
double d6;
double d7;
double d8;
double d9;
double g0;
double g1;
double g2;
double g3;
double g4;
double g5;
double g6;
double g7;
double g8;
double g9;
double f0;
double f1;
double f2;
double f3;
double f4;
double f5;
double f6;
double f7;
double f8;
double f9;
double w0;
double w1;
double w2;
double w3;
double w4;
double w5;
double w6;
double w7;
double w8;
double w9;
double y0;
double m0;
double m1;
double m2;
double m3;
double m4;
double m5;
double m6;
double m7;
double m8;
double m9;

string Vs[50][450];
string g_sPrefix;
string s0;
string s1;
string s2;
string s3;
string s4;
string s5;
string s6;
string s7;
string s8;
string s9;

string bg_box_length;
string Empty;

string TimeFrame[]={"0","M1","M5","M15","M30","H1","H4","D1","W1","MN"};

string op_str[6]={"BUY","SELL","BUYLIMIT","SELLLIMIT","BUYSTOP","SELLSTOP"};

datetime _box_time;
datetime _box_curr_trade;

//************************************************************************************************************************************************************

int init()
{
   mult=MathPow(10,(MathRound(Digits*0.5)!=Digits*0.5));
    
   TF[0]=Period();
   
   tf=(Period()==1)+(Period()==5)*2+(Period()==15)*3+(Period()==30)*4+(Period()==60)*5+(Period()==240)*6+(Period()==1440)*7+(Period()==10080)*8+(Period()==43200)*9;
   
   i2=0;
    
   i1=0;
    
   while(i1<=9 && i2==0) 
   {
      i2 = (int)(BoxTimeFrame == TimeFrame[i1]) * TF[i1]; 
      i1++;
   }
    
   i2+=(i2==0)*TF[0];
   
   btf=(i2==1)+(i2==5)*2+(i2==15)*3+(i2==30)*4+(i2==60)*5+(i2==240)*6+(i2==1440)*7+(i2==10080)*8+(i2==43200)*9;
   
   _Range=BoxRange*mult*Point; 
   
   BPips=BoxBufferPips*mult*Point; 
   
   bg_box_length=StringSubstr("ggggggggggggggggggggggggg",0,11);
    
   Empty="                                                                                                                                     ";
   
   i5=StringLen(FibSequence); 
   
   i3=1; 
   
   i1=0; 
   
   while(i1<=i5-1) 
   {
      i2=i1; 
      while(i2<=i5-1 && StringSubstr(FibSequence,i2,1)!=",") 
      {
         i2++;
      } 
      s1=StringSubstr(FibSequence,i1,i2-i1); 
      Fib[i3]=StrToDouble(s1); 
      i3+=(i2-i1>0); 
      i1=i2+1;
   }

   ArrayResize(_bounce_counts,MaxBreakoutTradesPerBox+1); 
   
   ArrayResize(wins_bounce_counts,MaxBreakoutTradesPerBox+1);
   
   Tdist=4*mult*Point; 
   
   LblDst=1; 
   
   space_font_size = (int) MathMax(MathRound(DisplayPanelFontSize*1.4),15);
   
   last_trigger_direction=-1; 
   
   closed_longs_profit=0; 
   
   closed_shorts_profit=0; 
   
   closed_longs_loss=0; 
   
   closed_shorts_loss=0;
   
   num_total_longs=0; 
   
   num_total_shorts=0; 
   
   num_closed_longs=0; 
   
   num_closed_shorts=0; 
   
   num_boxes=0; 
   
   total_losses =0; 
   
   num_wins=0; 
   
   num_losses=0; 

   win_set=0; 
   
   loss_set=0; 
   
   _period=BoxLength*TF[btf]/TF[0]; 
   
   _minP=_period; 
   
   _prevP=_period; 
   
   g_dtLastBarTime=0; 
   
   g_bFirstRun=true;
   
   LongBO=0; 
   
   ShortBO=0; 
   
   num_long_boxes=0; 
   
   num_short_boxes=0; 
   
   LastTradeCloseTime=0; 
   
   LastTakeProfitTime=0;

   DaysBack+=(DaysBack==0)*9999; 
   
   BarsBack=MathMin(iBars(Symbol(),0),iBarShift(Symbol(),0,iTime(Symbol(),PERIOD_D1,0)-DaysBack*PERIOD_D1*60));

   Vs[30][2]="SSBO "; 
   
   g_sPrefix=Vs[30][2];
   
   s1=Vs[30][2]; 
   
   Vs[32][21]=StringConcatenate(s1,"Box "); 
   
   Vs[32][22]=StringConcatenate(s1,"High line "); 
   
   Vs[32][23]=StringConcatenate(s1,"Low line ");
   
   Vs[32][24]=StringConcatenate(s1,"High box label "); 
   
   Vs[32][25]=StringConcatenate(s1,"Low box label "); 
   
   Vs[32][40]=StringConcatenate(s1,"Box info ");
   
   Vs[32][31]=StringConcatenate(s1,"Cont box "); 
   
   Vs[32][32]=StringConcatenate(s1,"High cont line "); 
   
   Vs[32][33]=StringConcatenate(s1,"Low cont line ");
    
   Vs[32][34]=StringConcatenate(s1,"High breakout label "); 
   
   Vs[32][35]=StringConcatenate(s1,"Low breakout label ");
   
   i1=1; 
   
   while(i1<=2) 
   {
      i2=1; 
      while(i2<=19 && Fib[i2]>0) 
      {
         Vs[32][i1*20+i2+20] = StringConcatenate(s1, CharToStr( (uchar) (43 + (i1==2)*2)),Fib[i2]," Fib "); 
         i2++;
      }      
      i1++;
   }

   IndicatorShortName(StringConcatenate(WindowExpertName()," (",BoxRange,"p x ",BoxLength,"b)"));

   IndicatorBuffers(8);
   
   i1=-1;
   
   i1++;SetIndexBuffer(i1,highBO); SetIndexStyle(i1,12);
   
   i1++; SetIndexBuffer(i1,lowBO); SetIndexStyle(i1,12);
   
   i1++; SetIndexBuffer(i1,highBOcont); SetIndexStyle(i1,12);
   
   i1++; SetIndexBuffer(i1,lowBOcont); SetIndexStyle(i1,12);
   
   i1++; SetIndexBuffer(i1,BoxStart); SetIndexStyle(i1,12);
   
   i1++; SetIndexBuffer(i1,BoxEnd); SetIndexStyle(i1,12);
   
   i1++; SetIndexBuffer(i1,BuySignal); SetIndexStyle(i1,12); SetIndexLabel(i1, "BuySignal");
   
   i1++; SetIndexBuffer(i1,SellSignal); SetIndexStyle(i1,12); SetIndexLabel(i1, "SellSignal");

   return(0);
}

//************************************************************************************************************************************************************

int deinit()
{
   RemoveObjects(g_sPrefix);
	return(0);
}

//************************************************************************************************************************************************************

int OnCalculate (const int rates_total,      // 
                 const int prev_calculated,  //
                 const datetime &time[],     // Time
                 const double &open[],       // Open
                 const double &high[],       // High
                 const double &low[],        // Low
                 const double &close[],      // Close
                 const long &tick_volume[],  // Tick Volume
                 const long &volume[],       // Real Volume
                 const int &spread[])        // Spread
{
	if (prev_calculated == 0)		// first run
	{
		RemoveObjects(g_sPrefix);
		ArrayInitialize(highBO, EMPTY_VALUE);
		ArrayInitialize(lowBO, EMPTY_VALUE);
		ArrayInitialize(highBOcont, EMPTY_VALUE);
		ArrayInitialize(lowBOcont, EMPTY_VALUE);
		ArrayInitialize(BoxStart, 0);
		ArrayInitialize(BoxEnd, 0);
		ArrayInitialize(BuySignal, 0);
		ArrayInitialize(SellSignal, 0);
		ArrayInitialize(_bounce_counts, 0);
		ArrayInitialize(wins_bounce_counts, 0);
	}

	if(g_dtLastBarTime != Time[0]) 
	{
		g_dtLastBarTime = Time[0];
		
		
		
      counted_bars=IndicatorCounted(); 
      k2=MathMax(MathMin(BarsBack, Bars-counted_bars-1),1); 
      
      if(k2 > (Bars - 2))
      	k2 = Bars - 2;
      	
      k1=k2; 
      while(k1>0)
      {  // get the period over which PA Range remained below BoxRange
         i2=_period; 
         _period=GetPeriodForMinRange(k1,_minP,999,_Range,i2);
         upper = High[iHighest(Symbol(),TF[0], MODE_HIGH, _period, k1)];
         lower = Low [iLowest (Symbol(),TF[0], MODE_LOW,  _period, k1)];

         // continue the previous Box high/low lines
         highBOcont[k1]=highBOcont[k1+1]; 
         lowBOcont[k1]=lowBOcont[k1+1]; 
         BoxStart[k1]=BoxStart[k1+1]; 
         BoxEnd[k1]=BoxEnd[k1+1];
    
         //draw a Dynamic Breakout Box when Price Range remains below BoxRange during more than BoxLength
         if (_period > _minP) 
         {  // Price range remained below BoxRange longer than BoxLength:
            // draw a new Breakout Box, or extend the Box if one is already drawing 
            open_new_box =(_box_total_trades ==0 || (_box_total_trades >= MaxBreakoutTradesPerBox && !has_open_trade()));
            if (highBO[k1+1]==EMPTY_VALUE && lowBO[k1+1]==EMPTY_VALUE && open_new_box) 
            {  // no Box was forming:
               // start a new Box ONLY if a the previous Box is older than BoxLength
               if ((k1+_minP) < Bars && highBO[k1+_minP]==EMPTY_VALUE && lowBO[k1+_minP]==EMPTY_VALUE) 
               {
                  if (BoxEnd[k1+1]>0 && _box_total_trades>0) 
                  {
                     i3=iBarShift(Symbol(),TF[0], (int) BoxEnd[k1+1]);
                     d1=iHigh(Symbol(),TF[0],iHighest(Symbol(),TF[0],MODE_HIGH,i3-k1-1,k1+1))-highBOcont[k1+1]+BPips; 
                     d1*=(d1>0); 
                     LongBO+=d1; 
                     num_long_boxes += (int) (d1>0); 
                     d1=lowBOcont[k1+1]+BPips-iLow(Symbol(),TF[0],iLowest(Symbol(),TF[0],MODE_LOW,i3-k1-1,k1+1)); 
                     d1*=(d1>0); 
                     ShortBO+=d1; 
                     num_short_boxes += (int)(d1>0);
                  }
                  // we can draw a new Box now
                  // limit the Box Range to BoxRange;
                  // snap the Box to the extreme that is opposite of the first(oldest) candle of the Box
                  if(k1+_period-1 < Bars)
                  {
	                  if (High[k1+_period-1]==upper) 
	                  {
	                     upper = NormalizeDouble(lower+_Range,Digits);
	                  }
	                  if (Low[k1+_period-1]==lower)  
	                  {
	                     lower = NormalizeDouble(upper-_Range,Digits);
	                  }
                  }
                  upperBox=upper; 
                  lowerBox=lower; 
                  _box_total_trades =0; 
                  TakeProfit=QuickTakeProfit;
                  // draw High and Low lines starting from the beginning of the Box
                  i2=k1+_minP-1; 
                  while(i2>=k1) 
                  {
                     highBO[i2]=upperBox+BPips; 
                     lowBO[i2]=lowerBox-BPips; 
                     i2--;
                  }
                  last_trigger_direction=-1;
                  num_boxes+=1;
                  highBOcont[k1]=highBO[k1]; 
                  lowBOcont[k1]=lowBO[k1];
                  BoxStart[k1] = (double) iTime(Symbol(),TF[0],k1+_minP-1); 
                  BoxEnd[k1]= (double) iTime(Symbol(),TF[0],k1);
                  if (BoxVerticalLineDelimiter) 
                  {
                     drawVLine(StringConcatenate(g_sPrefix,"V",TimeToStr((datetime)BoxStart[k1])), (int) BoxEnd[k1],BoxVerticalLineColor,STYLE_SOLID,1,0);
                  }
               }
            } 
            
            else 
            {  // a Box was already forming:
               // extend it ONLY IF price did not break out already
               if (Low[k1]>=lowBO[k1+1] && High[k1]<=highBO[k1+1]) 
               {
                  i3=iBarShift(Symbol(),TF[0], (datetime)BoxStart[k1]);
                  if (AutoReduceBoxSize) 
                  {
                     upperBox=MathMin(upperBox,iHigh(Symbol(),TF[0],iHighest(Symbol(),TF[0],MODE_HIGH,i3-k1+1,k1))); 
                     lowerBox=MathMax(lowerBox,iLow(Symbol(),TF[0],iLowest(Symbol(),TF[0],MODE_LOW,i3-k1+1,k1)));
                  }           
                  // price is still inside the Box limits: extend the forming Box
                  // draw High and Low Yellow lines starting from the beginning of the Box
                  i2=i3; 
                  while (i2>=k1) 
                  {  
                     highBO[i2]=upperBox+BPips; 
                     lowBO[i2]=lowerBox-BPips; 
                     i2--;
                  }
                  highBOcont[k1]=highBO[k1]; 
                  lowBOcont[k1]=lowBO[k1];
                  BoxEnd[k1]= (double)iTime(Symbol(),TF[0],k1);

                  if (BoxVerticalLineDelimiter) 
                  {
                     drawVLine(StringConcatenate(g_sPrefix,"V",TimeToStr((datetime)BoxStart[k1])),(int)BoxEnd[k1], BoxVerticalLineColor,STYLE_SOLID,1,0);
                  }
               } 
               
               else 
               {  // Price has broken out of the forming Box: stop the forming Box
                  highBO[k1]=EMPTY_VALUE;
                  lowBO[k1]=EMPTY_VALUE;
               }
            }
         }
         
         CZone[num_boxes][1]=BoxStart[k1]; 
         CZone[num_boxes][2]=BoxEnd[k1]; 
         CZone[num_boxes][3]= (double)iTime(Symbol(),TF[0],k1);
         CZone[num_boxes][4]=highBOcont[k1]; 
         CZone[num_boxes][5]=lowBOcont[k1];
         calc_tp_sl(k1,best_buy,best_sell); 
         manage_signals(k1);
         DrawGraphics(BPips,k1,TF[0]); 
         k1--;
      }

      highBOcont[k1]=highBOcont[k1+1]; 
      lowBOcont[k1]=lowBOcont[k1+1]; 
      BoxStart[k1]=BoxStart[k1+1]; 
      BoxEnd[k1]=BoxEnd[k1+1];
   }
  
   calc_tp_sl(0,best_buy,best_sell); 
   manage_signals(0); 
   display_stats();
   return(rates_total);
}

//************************************************************************************************************************************************************

void calc_tp_sl(int t8_1, double & best_buy_1, double &best_sell_1)
{
   if (!has_open_trade()) 
   {
      return;
   }
   int highest_bar,lowest_bar;
   double highest_price = 0,lowest_price = 0,trade_open_price = 0,trade_SL = 0;
   int trade_type,trade_open_bar,num_trades;
   int trade_size = 1;

   if (BoxMartingale) 
   {
      trade_size= (int)MathPow(2,_box_total_trades-1);
   }

   int box_forming_shift = iBarShift(Symbol(),0,(datetime)BoxStart[t8_1]);
   if (t8_1>box_forming_shift) 
   {
      return;
   }
   trade_open_bar = iBarShift(Symbol(), 0, _box_curr_trade);
   trade_open_price = Open[trade_open_bar];
   trade_type = -1;
   num_trades = 0;
   tp_val = TakeProfit;  

   string end_swing = g_sPrefix+"EndSwing"+TimeToStr(_box_curr_trade);
   if (ObjectFind(end_swing)!=-1) 
   {
      return;
   }
   
   double tp;
   switch (_box_curr_trade_dir) 
   {
      case OP_BUY: // a BUY trade is open: check if it hit the SL = opposite DB side
      if (MinBarsClosedOutsideBO==0) 
      {
         trade_open_price=highBOcont[t8_1]+Point;
      }
      lowest_bar=-1; 
      highest_bar=-1; 
      tp=trade_open_price+tp_val*mult*Point;
        
      if (StopLossOverride==0) 
      {
         trade_SL=lowBOcont[t8_1]+BPips;
      }
      if (StopLossOverride>0) 
      {
         trade_SL=trade_open_price-StopLossOverride*mult*Point;
      }       
        
      if (Low[t8_1] <= (double)trade_SL) 
      {
         lowest_bar = t8_1;
         lowest_price  = Low[lowest_bar];
      }
      if (High[t8_1] >= tp) 
      {
         highest_bar = t8_1;
         highest_price = High[highest_bar];
      }
        
     // highest_price = High[highest_bar];

      if (tp < highest_price) 
      {
         highest_price = tp;
      }
        
      //lowest_price  = Low[lowest_bar];
      best_buy_1 = (highest_price - trade_open_price)/(mult*Point);
        
      if (lowest_price<=trade_SL && lowest_bar>=0) 
      {  // SL was hit at opposite DB side: "close" the trade
         _bounce_counts[_box_total_trades]+=1; 
         num_closed_longs=num_total_longs; 
         trade_type = -1;
         loss = -(trade_open_price-trade_SL)/(mult*Point); 
         LastTradeCloseTime=iTime(Symbol(),TF[0],t8_1);
         if (_box_total_trades==1) 
         {
            TakeProfit=MathAbs(loss);
         } 
         loss*=trade_size; 
         drawLbl(g_sPrefix+"SwingHigh"+TimeToStr(Time[trade_open_bar]), DoubleToStr(loss,(MathRound(loss*10)!=MathRound(loss)*10))+"p", Time[lowest_bar],lowest_price-LblDst*iATR(Symbol(),TF[0],7,lowest_bar), SwingLabelsFontSize, Fonts, SwingLabelsColor, 3);
         drawTrendLine(g_sPrefix+"TLSwing"+TimeToStr(Time[trade_open_bar]), Time[trade_open_bar], trade_open_price, Time[lowest_bar], trade_SL, SwingLabelsColor, STYLE_DOT, 0);
         drawOrderArrow(g_sPrefix+"EndSwing"+TimeToStr(Time[trade_open_bar]), Time[lowest_bar], trade_SL, 3, SwingLabelsColor, 2);

         closed_longs_loss+=loss; 
         total_losses+=loss; 
         num_losses+=1;
         if (_box_total_trades>=MaxBreakoutTradesPerBox) 
         {
            _trade_loss_set+=1;
         }
         _curr_consecutive_losses+=1; 
         _curr_consecutive_wins=0;
      }

      if (highest_bar >= 0) 
      {
         _bounce_counts[_box_total_trades]+=1; 
         wins_bounce_counts[_box_total_trades]+=1; // TP
         num_closed_longs=num_total_longs; 
         best_buy_1*=trade_size; 
         LastTradeCloseTime=iTime(Symbol(),TF[0],t8_1); 
         LastTakeProfitTime=iTime(Symbol(),TF[0],t8_1);
         drawLbl(g_sPrefix+"SwingHigh"+TimeToStr(Time[trade_open_bar]), DoubleToStr(best_buy_1,(MathRound(best_buy_1*10)!=MathRound(best_buy_1)*10))+"p", Time[highest_bar], highest_price+LblDst*iATR(Symbol(),TF[0],7,highest_bar), SwingLabelsFontSize, Fonts, SwingLabelsColor, 3);
         drawTrendLine(g_sPrefix+"TLSwing"+TimeToStr(Time[trade_open_bar]), Time[trade_open_bar], trade_open_price, Time[highest_bar], highest_price, SwingLabelsColor, STYLE_DOT, 0);
         drawOrderArrow(g_sPrefix+"EndSwing"+TimeToStr(Time[trade_open_bar]), Time[highest_bar], highest_price, 3, SwingLabelsColor, 2);
         num_wins+=1; 
         closed_longs_profit+=best_buy_1; 
         _trade_win_set +=1; 
         _curr_consecutive_losses = 0; 
         _curr_consecutive_wins += 1;
      }
      break;

      case OP_SELL: // a SELL trade is open: check if it hit the SL = opposite DB side
      if (MinBarsClosedOutsideBO==0) 
      {
         trade_open_price=lowBOcont[t8_1]-Point;
      }
      lowest_bar = -1; 
      highest_bar = -1; 
      tp = trade_open_price - (tp_val*mult*Point) ;
      if (StopLossOverride==0) 
      {
         trade_SL=highBOcont[t8_1]-BPips;
      }
      if (StopLossOverride>0) 
      {
         trade_SL=trade_open_price+StopLossOverride*mult*Point;
      }

      if (High[t8_1] >= trade_SL) 
      {
         highest_bar = t8_1;
         highest_price = High[highest_bar];
      }
      if (Low[t8_1] <= tp) 
      {
         lowest_bar = t8_1;
         lowest_price  = Low[lowest_bar];
      }

		
      //highest_price = High[highest_bar]; 
      //lowest_price  = Low[lowest_bar];

      if (tp > lowest_price) 
      {
         lowest_price = tp;
      }
      best_sell_1 = (trade_open_price - lowest_price)/(mult*Point);
        
      if (highest_price >= trade_SL && highest_bar >= 0) 
      {  // SL was hit at opposite DB side: "close" the trade
         _bounce_counts[_box_total_trades]+=1; 
         num_closed_shorts=num_total_shorts; 
         trade_type = -1;
         loss = (trade_open_price-trade_SL)/(mult*Point); 
         LastTradeCloseTime=iTime(Symbol(),TF[0],t8_1);
         if (_box_total_trades==1) 
         {
            TakeProfit=MathAbs(loss);
         } 
         loss*=trade_size; 
         drawLbl(g_sPrefix+"SwingLow"+TimeToStr(Time[trade_open_bar]), DoubleToStr(loss,(MathRound(loss*10)!=MathRound(loss)*10))+"p", Time[highest_bar],trade_SL+LblDst*iATR(Symbol(),TF[0],7,highest_bar), SwingLabelsFontSize, Fonts, SwingLabelsColor, 3); //High[highest_bar]
         drawTrendLine(g_sPrefix+"TLSwing"+TimeToStr(Time[trade_open_bar]), Time[trade_open_bar], trade_open_price, Time[highest_bar], trade_SL, SwingLabelsColor, STYLE_DOT, 0);
         drawOrderArrow(g_sPrefix+"EndSwing"+TimeToStr(Time[trade_open_bar]), Time[highest_bar], trade_SL, 3, SwingLabelsColor, 2);

         _curr_consecutive_losses += 1;
         _curr_consecutive_wins = 0;
         closed_shorts_loss+=loss; 
         total_losses+=loss;
         num_losses+=1;
         if (_box_total_trades >= MaxBreakoutTradesPerBox) 
         {
            _trade_loss_set += 1;
         }

      }
      if (lowest_bar>=0) 
      {
         _bounce_counts[_box_total_trades]+=1; 
         wins_bounce_counts[_box_total_trades]+=1; // TP
         num_closed_shorts=num_total_shorts; 
         best_sell_1*=trade_size; 
         LastTradeCloseTime=iTime(Symbol(),TF[0],t8_1); 
         LastTakeProfitTime=iTime(Symbol(),TF[0],t8_1);        
         drawLbl(g_sPrefix+"SwingLow"+TimeToStr(Time[trade_open_bar]), DoubleToStr(best_sell_1,(MathRound(best_sell_1*10)!=MathRound(best_sell_1)*10))+"p", Time[lowest_bar], lowest_price-LblDst*iATR(Symbol(),TF[0],7,lowest_bar), SwingLabelsFontSize, Fonts, SwingLabelsColor, 3); //q
         drawTrendLine(g_sPrefix+"TLSwing"+TimeToStr(Time[trade_open_bar]), Time[trade_open_bar], trade_open_price, Time[lowest_bar], lowest_price, SwingLabelsColor, STYLE_DOT, 0);
         drawOrderArrow(g_sPrefix+"EndSwing"+TimeToStr(Time[trade_open_bar]), Time[lowest_bar], lowest_price, 3, SwingLabelsColor, 2);
         num_wins+=1; 
         closed_shorts_profit+=best_sell_1; 
         _trade_win_set+=1; 
         _curr_consecutive_losses = 0; 
         _curr_consecutive_wins +=1;
      }
      break;

   }

   if (_curr_consecutive_losses > _consecutive_losses) 
   {
      _consecutive_losses = _curr_consecutive_losses;
   }
   if (_curr_consecutive_wins > _consecutive_wins) 
   {
      _consecutive_wins = _curr_consecutive_wins;
   }
}

//************************************************************************************************************************************************************

void manage_signals(int t8_1)
{
   trigger_direction =-1; 
   if (BoxStart[t8_1]!=_box_time)
   {
      _box_time= (datetime)BoxStart[t8_1]; 
      _box_curr_trade=0; 
      _box_curr_trade_dir=-1; 
      _box_total_trades=0; 
      _box_profit_trades=0;
   } 

   if (LastTakeProfitTime==iTime(Symbol(),TF[0],t8_1)) 
   {
      _box_total_trades=MaxBreakoutTradesPerBox+2;
   } 
   if (_box_total_trades>=MaxBreakoutTradesPerBox) 
   {
      return;
   }
   if (BoxStart[t8_1]==0 || has_open_trade() || (LastTradeCloseTime==iTime(Symbol(),TF[0],t8_1) && MinBarsClosedOutsideBO>0)) 
   {
      return;
   }
   
   // Trading Signal Alerts: a minimum number of bars should have closed outside of the BO area 
   // MinBarsClosedOutsideBO set to 0 means we can start the sequence as soon as the breakout occurs
   if (MinBarsClosedOutsideBO==0) 
   {  // special case: we want to trigger the trade as soon as price break out of the DB Box
      if (Close[t8_1+1]<=highBOcont[t8_1] && High[t8_1]>highBOcont[t8_1]) 
      {
         trigger_direction=OP_BUY; trigger_price=highBOcont[t8_1]+Point;
      }
      if (Close[t8_1+1]>=lowBOcont[t8_1] && Low[t8_1]<lowBOcont[t8_1]) 
      {
         trigger_direction=OP_SELL; trigger_price=lowBOcont[t8_1]+Point;
      }
   } 
   
   if (MinBarsClosedOutsideBO>=1) 
   {
      ArrayCopySeries(d,MODE_CLOSE,Symbol(),TF[0]); 
      d1=iClose(Symbol(),TF[0],t8_1+MinBarsClosedOutsideBO+1);
      Temp[0][1]=d[ArrayMinimum(d,MinBarsClosedOutsideBO,t8_1+1)]; 
      Temp[0][2]=d[ArrayMaximum(d,MinBarsClosedOutsideBO,t8_1+1)];
      Temp[0][3]=highBOcont[t8_1]; 
      Temp[0][4]=lowBOcont[t8_1]; 
      t4=0; 
      t1=1; 
      while (t1<=2 && t4==0) 
      {
         t5=(3-t1*2);
         t4= (int)(t5*(Temp[0][t1]-Temp[0][t1+2])>0 && t5*(Temp[0][t1+2]-d1)>=0 && d1>0 && Temp[0][t1]>0 && Temp[0][t1+2]>0)*t1; t1++;
      }
      if (t4==1) 
      {
         trigger_direction=OP_BUY; trigger_price=Open[t8_1];
      } 
      if (t4==2) 
      {
         trigger_direction=OP_SELL; trigger_price=Open[t8_1];
      }
   }

   if (trigger_direction==OP_BUY && LongTrades && (InitialBreakoutDirection==OP_BUY || !InitialBreakoutDirectionOnly || _box_total_trades==0))
   {
      BuySignal[t8_1]=trigger_price; // make the arrow point to the trade open price      
      last_trigger_direction=OP_BUY;
      _box_curr_trade=Time[t8_1];
      _box_curr_trade_dir=OP_BUY;
      _box_total_trades+=1; 
      if (_box_total_trades==1) 
      {
         InitialBreakoutDirection=OP_BUY;
      }
      num_total_longs+=1; 
      s1=StringConcatenate(g_sPrefix,"BUY",TimeToStr(Time[t8_1]));
      drawOrderArrow(s1,Time[t8_1],trigger_price,BuySignalArrowCode,BuySignalArrowColor, 2);
      if (t8_1==0) 
      {
         send_trading_signal(OP_BUY,Ask);
      }
   }
  
   if (trigger_direction==OP_SELL && ShortTrades && (InitialBreakoutDirection==OP_SELL || !InitialBreakoutDirectionOnly || _box_total_trades==0))
   {
      SellSignal[t8_1] = trigger_price; // make the arrow point to the trade open price
      last_trigger_direction=OP_SELL;
      _box_curr_trade=Time[t8_1];
      _box_curr_trade_dir=OP_SELL;
      _box_total_trades+=1; 
      if (_box_total_trades==1) 
      {
         InitialBreakoutDirection=OP_SELL;
      }
      num_total_shorts +=1; 
      s1=StringConcatenate(g_sPrefix,"SELL",TimeToStr(Time[t8_1]));
      drawOrderArrow(s1, Time[t8_1], trigger_price, SellSignalArrowCode, SellSignalArrowColor, 2);
      if (t8_1==0) 
      {
         send_trading_signal(OP_SELL,Bid);
      }
   }
}

//************************************************************************************************************************************************************

void send_trading_signal(int type, double price)
{
   s1=StringConcatenate(WindowExpertName(),":",StringSubstr(Symbol(),0,6)," ",op_str[type]," Signal");
   if (SignalMail)  
   {
      SendMail(s1,StringConcatenate(StringSubstr(Symbol(),0,6),":",op_str[type]," @ ",DoubleToStr(price,Digits)));
   }
   if (SignalAlert) 
   {
      Alert(s1);
   }
}

//************************************************************************************************************************************************************

bool has_open_trade()
{
   return(num_total_longs>num_closed_longs || num_total_shorts>num_closed_shorts);
}

//************************************************************************************************************************************************************

int GetPeriodForMinRange(int shift, int MinP, int MaxP, double MinRange, int prevP)
{
  int P;

  // calc P so that the Price Range (=Hi-Lo) remains in a "reasonably large value" over the P
  P=prevP; // start with previous P
  if (P<MinP) P=MinP;
  if (P>MaxP) P=MaxP;
  if (_get_range(P,shift) > MinRange) 
  {   //range is OK for this P value: try shorter P values
      for (; P>=MinP; P--) 
      {
         if (_get_range(P,shift) <= MinRange) return(P+1);//previous P value was the limit
      }
    return(P);
  }
  //try higher P values
  for (P=prevP+1; P<MaxP; P++) 
  {
    if (_get_range(P,shift) > MinRange) return(P);
  }
  return(MaxP);
}

//************************************************************************************************************************************************************

double _get_range(int period, int shift)
{
   return(High[iHighest(Symbol(),0,MODE_HIGH,period,shift)] - Low[iLowest(Symbol(),0,MODE_LOW,period,shift)]);
}

//************************************************************************************************************************************************************

void display_stats()
{  // Compute the average BestBuy and BestSell expectation per Session

   num_weeks= (int)(Time[0]-Time[BarsBack])/(3600*24*7); num_weeks+=(num_weeks==0);
  
   // Display the total number of Buys and Sells, total maximum pips, and average pips per session
   if (ChartDisplay>0) 
   {
      int y=0,dy=20,x=10;
      int space_y=5;
     
      d1=NormalizeDouble(BoxRange,1);
      y+=dy;
      drawFixedLbl(g_sPrefix+"infoBox", "DB Box="+DoubleToStr(d1,(mult==10 && MathFloor(d1)!=d1))+" pips x "+IntegerToString(BoxLength)+" bars on "+TimeFrame[btf], StatsCorner, x, y,  DisplayPanelFontSize, Fonts, StatsColor, false);
      drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
      
      d1=NormalizeDouble(num_boxes/num_weeks,1);
      y+=dy;
      drawFixedLbl(g_sPrefix+"numBox", DoubleToStr(num_boxes,0)+" DB's ("+DoubleToStr(d1,(MathFloor(d1)!=d1))+" per Week)", StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
      drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);

      y+=dy;
      drawFixedLbl(g_sPrefix+"boBars", "MinClosedBars="+ IntegerToString(MinBarsClosedOutsideBO) , StatsCorner, x, y,  DisplayPanelFontSize, Fonts, StatsColor, false);
      drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);

      y+=dy;
      drawFixedLbl(g_sPrefix+"MaxTradesPerSet", "MaxTradesPerSet="+IntegerToString(MaxBreakoutTradesPerBox), StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
      drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);

      d1=NormalizeDouble(TakeProfit,1); 
      s2=""; 
      if (_box_total_trades==0 || (_box_total_trades==1 && has_open_trade())) 
      {
         s2="Quick";
      }
      y+=dy;
      drawFixedLbl(g_sPrefix+"TakeProfit",s2+"TakeProfit="+DoubleToStr(d1,(mult==10 && MathFloor(d1)!=d1))+" pips", StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
      drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);

      StopLoss=(StopLossOverride==0)*((highBOcont[1]-lowBOcont[1]-BPips+Point)/(mult*Point))+StopLossOverride; d1=NormalizeDouble(StopLoss,1);
      y+=dy;
      drawFixedLbl(g_sPrefix+"StopLoss", "StopLoss="+DoubleToStr(d1,(mult==10 && MathFloor(d1)!=d1))+" pips", StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
      drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);

      d1=NormalizeDouble(MarketInfo(Symbol(),MODE_SPREAD)/mult,1);
      y+=dy;
      drawFixedLbl(g_sPrefix+"spread", "Spread="+DoubleToStr(d1,(mult==10 && MathFloor(d1)!=d1))+" pips", StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
      drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);


      if (ChartDisplay>1) 
      {
         y+=dy;
         drawFixedLbl(g_sPrefix+"space" + IntegerToString(y), " ", StatsCorner, x, y,  DisplayPanelFontSize, Fonts, StatsColor, false);
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);

         if (num_long_boxes>0) 
         {
            d1=NormalizeDouble((LongBO/num_long_boxes)/(mult*Point),1);
            s1=StringConcatenate("Longs=",num_long_boxes,"=Avg ",DoubleToStr(d1,(MathFloor(d1)!=d1)),"p");
            y+=dy;
            drawFixedLbl(g_sPrefix+"ttB",s1, StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
            drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
            avgBuys=closed_longs_profit/num_closed_longs;
         }

         if (num_short_boxes>0) 
         {
            d1=NormalizeDouble((ShortBO/num_short_boxes)/(mult*Point),1);
            s1=StringConcatenate("Shorts=",num_short_boxes,"=Avg ",DoubleToStr(d1,(MathFloor(d1)!=d1)),"p");
            y+=dy;
            drawFixedLbl(g_sPrefix+"ttS",s1, StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
            drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
            avgSells = closed_shorts_profit/num_closed_shorts;
         }

         t1=1; 
         while(t1<=MaxBreakoutTradesPerBox) 
         {
            s6=StringConcatenate("Closed trade ",t1," = ",_bounce_counts[t1]);
            if (_bounce_counts[t1]>0) 
            {
               d2=wins_bounce_counts[t1]; 
               d1=NormalizeDouble((d2/_bounce_counts[t1])*100,1);
               s6=StringConcatenate(s6,", Wins=",DoubleToStr(d1,(MathFloor(d1)!=d1)),"%");
            }
            y+=dy;
            drawFixedLbl(g_sPrefix+"ttBounce" +IntegerToString(t1), s6 , StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
            drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
            t1++;
         } 
      
         if (num_total_longs+num_total_shorts+num_losses>0)
         {
            double wins=num_total_longs+num_total_shorts; 
            double total_trades = num_total_longs+num_total_shorts+num_losses; 
            WinRatio=wins/total_trades;
         }
      }
      
      if (ChartDisplay>=3) 
      {
         y+=dy;
         drawFixedLbl(g_sPrefix+"space" + IntegerToString(y), " ", StatsCorner, x, y,  DisplayPanelFontSize, Fonts, StatsColor, false);
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
         y+=dy;
         drawFixedLbl(g_sPrefix+"tsWins", "Trade Set Wins=" + IntegerToString(_trade_win_set) , StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
         y+=dy;
         drawFixedLbl(g_sPrefix+"tsLoss", "Trade Set Losses="+IntegerToString(_trade_loss_set), StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
         y+=dy;
         drawFixedLbl(g_sPrefix+"ttIndiWins", "Individual Trades Won="+DoubleToStr(num_wins,0), StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
         y+=dy;
         drawFixedLbl(g_sPrefix+"ttIndiLoss", "Individual Trades Lost="+DoubleToStr(num_losses,0), StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
         y+=dy;
         drawFixedLbl(g_sPrefix+"tsCLoss", "Consecutive Trade Losses="+IntegerToString(_consecutive_losses), StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
         y+=dy;
         drawFixedLbl(g_sPrefix+"tsCWins", "Consecutive Trade Wins="+IntegerToString(_consecutive_wins), StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
      
         trade_set_win_ratio=0;
         d2=_trade_win_set+_trade_loss_set; 
         if (d2>0) 
         {
            trade_set_win_ratio=(_trade_win_set/(d2))*100;
         }
         d1=NormalizeDouble(trade_set_win_ratio,1);
         y+=dy;
         drawFixedLbl(g_sPrefix+"tsWinsRatio", "Trade Set Win Ratio=" +DoubleToStr(d1,(MathFloor(d1)!=d1))+"%" , StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
         d1=0; 
         d2=num_wins+num_losses; 
         if (d2>0) 
         {
            d1=NormalizeDouble((num_wins/d2)*100,1);
         }     
         y+=dy;
         drawFixedLbl(g_sPrefix+"ttWinRatio","Individual Trades Win Ratio="+DoubleToStr(d1,(MathFloor(d1)!=d1))+"%", StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y), bg_box_length, StatsCorner, x-5, y-space_y, space_font_size, "Webdings", StatsBGColor, true);
         d1=NormalizeDouble(closed_longs_profit+closed_shorts_profit+total_losses,1); 
         t1= (int)((d1>=0)*PipsProfitColor +(d1<0)*PipsLossColor);
         y+=dy; 
         if (StatsCorner==0 || StatsCorner==2) 
         {
            drawFixedLbl(g_sPrefix+"ttLoss","Net Pips=", StatsCorner, x, y, DisplayPanelFontSize, Fonts, StatsColor, false);
            drawFixedLbl(g_sPrefix+"Pips","Net Pips="+DoubleToStr(MathAbs(d1),(MathFloor(d1)!=d1)),StatsCorner,x,y,DisplayPanelFontSize,Fonts,t1,false);
         }
         if (StatsCorner==1 || StatsCorner==3) 
         {
            drawFixedLbl(g_sPrefix+"ttLoss",DoubleToStr(MathAbs(d1),(MathFloor(d1)!=d1)), StatsCorner, x, y, DisplayPanelFontSize, Fonts,t1,false);
            drawFixedLbl(g_sPrefix+"Pips","Net Pips="+DoubleToStr(MathAbs(d1),(MathFloor(d1)!=d1)),StatsCorner,x,y,DisplayPanelFontSize,Fonts,StatsColor,false);
         }
         drawFixedLbl(g_sPrefix+"numBoxbg"+IntegerToString(y),bg_box_length,StatsCorner,x-5,y-space_y, space_font_size, "Webdings", StatsBGColor, true);
      }  
   }
}

//************************************************************************************************************************************************************

void drawFixedLbl(string objname, string s, int Corner, int DX, int DY, int FSize, string Font, color c, bool bg)
{
   if (ObjectFind(objname) < 0) 
   {
      ObjectCreate(objname, OBJ_LABEL, 0, 0, 0);
   }
   
   ObjectSet(objname, OBJPROP_CORNER, Corner);
   ObjectSet(objname, OBJPROP_XDISTANCE, DX);
   ObjectSet(objname, OBJPROP_YDISTANCE, DY);
   ObjectSet(objname,OBJPROP_BACK, bg);      
   ObjectSetText(objname, s, FSize, Font, c);
}

//************************************************************************************************************************************************************

void drawLbl(string objname, string s, datetime LTime, double LPrice, int FSize, string Font, color c, int width)
{
  if (ObjectFind(objname) < 0) 
  {
    ObjectCreate(objname, OBJ_TEXT, 0, LTime, LPrice);
  } 
  else 
  {
    if (ObjectType(objname) == OBJ_TEXT) 
    {
      ObjectSet(objname, OBJPROP_TIME1, LTime);
      ObjectSet(objname, OBJPROP_PRICE1, LPrice);
    }
  }

  ObjectSet(objname, OBJPROP_FONTSIZE, FSize);
  ObjectSetText(objname, s, FSize, Font, c);
}

//************************************************************************************************************************************************************

void drawOrderArrow(string name, datetime t, double price, int arrowcode, color c, int width=1)
{
  if (ObjectFind(name) < 0) ObjectCreate(name, OBJ_ARROW, 0, t, price);
  else ObjectMove(name, 0, t, price);
  ObjectSet(name, OBJPROP_ARROWCODE,  arrowcode);
  ObjectSet(name, OBJPROP_COLOR, c);
  ObjectSet(name, OBJPROP_WIDTH, width); 
}

//************************************************************************************************************************************************************

void drawVLine(string objname, int time, color c, int style, int width, int win)
{
   if (ObjectFind(objname)==-1) 
   {
      ObjectCreate(objname,OBJ_VLINE,win,time,0);
   } 
   ObjectSet(objname, OBJPROP_TIME1, time);
   ObjectSet(objname, OBJPROP_COLOR, c);
   ObjectSet(objname, OBJPROP_STYLE, style);
   ObjectSet(objname, OBJPROP_WIDTH, width);
}

//************************************************************************************************************************************************************

void drawTrendLine(string objname, datetime t6_1, double d6_1, datetime t7_1, double d7_1, color c, int style, int width)
{
   if (ObjectFind(objname)==-1) 
   {
      ObjectCreate(objname,OBJ_TREND,0,0,0,0,0); ObjectSet(objname, OBJPROP_RAY, false);
   }
   ObjectSet(objname, OBJPROP_TIME1, t6_1);
   ObjectSet(objname, OBJPROP_TIME2, t7_1);
   ObjectSet(objname, OBJPROP_PRICE1, d6_1);
   ObjectSet(objname, OBJPROP_PRICE2, d7_1);
   ObjectSet(objname, OBJPROP_COLOR, c);
   ObjectSet(objname, OBJPROP_STYLE, style);
   ObjectSet(objname, OBJPROP_WIDTH, width);
}

//************************************************************************************************************************************************************

double Swing(int x7_1,int x8_1)
{
   x5=0; 
   x1=x8_1+1; 
   while(x5==0 && ((x7_1==1 && iHigh(Symbol(),TF[0],x8_1)>iHigh(Symbol(),TF[0],x8_1-1)) || (x7_1==2 && iLow(Symbol(),TF[0],x8_1)<iLow(Symbol(),TF[0],x8_1-1)) || x8_1==0)) 
   {
      x5=(int) (((x7_1==1 && iHigh(Symbol(),TF[0],x8_1)>iHigh(Symbol(),TF[0],x1)) || (x7_1==2 && iLow(Symbol(),TF[0],x8_1)<iLow(Symbol(),TF[0],x1)))-((x7_1==1 && iHigh(Symbol(),TF[0],x8_1)<iHigh(Symbol(),TF[0],x1)) || (x7_1==2 && iLow(Symbol(),TF[0],x8_1)>iLow(Symbol(),TF[0],x1)))); x1++;
   } 
   f5=(x5>0)*((x7_1==1)*iHigh(Symbol(),TF[0],x8_1)+(x7_1==2)*iLow(Symbol(),TF[0],x8_1)); 
   return(f5);
}

//************************************************************************************************************************************************************

void DrawGraphics(double m5_1,int q8_1,int q9_1)
{
   if (BoxStart[q8_1]>0 && highBO[q8_1]!=EMPTY_VALUE && lowBO[q8_1]!=EMPTY_VALUE) 
   {
      s8=StringConcatenate(Vs[32][21],TimeToStr((datetime)BoxStart[q8_1],3)); 
      if (ObjectFind(s8)==-1) 
      {
         ObjectCreate(s8,16,0,0,0,0,0);
         ObjectSet(s8,OBJPROP_COLOR,BoxColor); 
         ObjectSet(s8,OBJPROP_BACK,true); 
         ObjectSet(s8,OBJPROP_WIDTH,0); 
         ObjectSet(s8,OBJPROP_STYLE,STYLE_SOLID);
      }
      ObjectSet(s8,OBJPROP_TIME1,BoxStart[q8_1]); 
      ObjectSet(s8,OBJPROP_TIME2,BoxEnd[q8_1]); 
      ObjectSet(s8,OBJPROP_PRICE1,highBO[q8_1]-m5_1); 
      ObjectSet(s8,OBJPROP_PRICE2,lowBO[q8_1]+m5_1);

      s6=StringConcatenate(Vs[32][22],TimeToStr((datetime)BoxStart[q8_1],3)); 
      if (ObjectFind(s6)==-1) 
      {
         ObjectCreate(s6,2,0,0,0,0,0);
         ObjectSet(s6,OBJPROP_RAY,false); 
         ObjectSet(s6,OBJPROP_COLOR,BoxBufferLinesColor); 
         ObjectSet(s6,OBJPROP_WIDTH,BoxBufferLinesWidth); 
         ObjectSet(s6,OBJPROP_STYLE,STYLE_SOLID);
      }
      ObjectSet(s6,OBJPROP_TIME1,BoxStart[q8_1]); 
      ObjectSet(s6,OBJPROP_TIME2,BoxEnd[q8_1]); 
      ObjectSet(s6,OBJPROP_PRICE1,highBO[q8_1]); 
      ObjectSet(s6,OBJPROP_PRICE2,highBO[q8_1]);

      s7=StringConcatenate(Vs[32][23],TimeToStr((datetime)BoxStart[q8_1],3)); 
      if (ObjectFind(s7)==-1) 
      {
         ObjectCreate(s7,2,0,0,0,0,0); 
         ObjectSet(s7,OBJPROP_RAY,false);
         ObjectSet(s7,OBJPROP_COLOR,BoxBufferLinesColor); 
         ObjectSet(s7,OBJPROP_WIDTH,BoxBufferLinesWidth); 
         ObjectSet(s7,OBJPROP_STYLE,STYLE_SOLID);
      }
      ObjectSet(s7,OBJPROP_TIME1,BoxStart[q8_1]); 
      ObjectSet(s7,OBJPROP_TIME2,BoxEnd[q8_1]); 
      ObjectSet(s7,OBJPROP_PRICE1,lowBO[q8_1]); 
      ObjectSet(s7,OBJPROP_PRICE2,lowBO[q8_1]);

      s7=StringConcatenate(Vs[32][40],TimeToStr((datetime)BoxStart[q8_1],3)); 
      if (ObjectFind(s7)==-1) 
      {
         ObjectCreate(s7,OBJ_TEXT,0,0,0);
      }
      
      m1=NormalizeDouble((highBO[q8_1]-lowBO[q8_1]-m5_1*2)/(mult*Point),1);
      s1=StringConcatenate(DoubleToStr(m1,(mult==10 && MathFloor(m1)!=m1))," pips x ",DoubleToStr(iBarShift(Symbol(),Period(),(int)BoxStart[q8_1])-iBarShift(Symbol(),Period(),(int)BoxEnd[q8_1])+1,0)," bars");
      ObjectSetText(s7,s1,BoxFontSize,Fonts,BoxColor); 
      ObjectSet(s7,OBJPROP_TIME1,BoxStart[q8_1]+(BoxEnd[q8_1]-BoxStart[q8_1])*0.5); 
      ObjectSet(s7,OBJPROP_PRICE1,lowBO[q8_1]);
   }

   if (BoxEnd[q8_1]>0 && BoxEnd[q8_1]<=iTime(Symbol(),q9_1,q8_1) && highBOcont[q8_1]!=EMPTY_VALUE && lowBOcont[q8_1]!=EMPTY_VALUE) 
   {
      s8=StringConcatenate(Vs[32][31],TimeToStr((datetime)BoxStart[q8_1],3)); 
      if (ObjectFind(s8)==-1) 
      {
         ObjectCreate(s8,16,0,0,0,0,0);
      }
      ObjectSet(s8,OBJPROP_TIME1,BoxEnd[q8_1]); 
      ObjectSet(s8,OBJPROP_TIME2,iTime(Symbol(),q9_1,q8_1)); 
      ObjectSet(s8,OBJPROP_PRICE1,highBOcont[q8_1]-m5_1);
      ObjectSet(s8,OBJPROP_PRICE2,lowBOcont[q8_1]+m5_1); 
      ObjectSet(s8,OBJPROP_COLOR,ContBoxColor); 
      ObjectSet(s8,OBJPROP_BACK,ContBoxFullColored);
      ObjectSet(s8,OBJPROP_WIDTH,0); 
      ObjectSet(s8,OBJPROP_STYLE,STYLE_SOLID);

      s6=StringConcatenate(Vs[32][32],TimeToStr((datetime)BoxStart[q8_1],3)); 
      if (ObjectFind(s6)==-1) 
      {
         ObjectCreate(s6,2,0,0,0,0,0); 
         ObjectSet(s6,OBJPROP_RAY,false); 
         ObjectSet(s6,OBJPROP_COLOR,ContBoxBufferLinesColor); 
         ObjectSet(s6,OBJPROP_WIDTH,ContBoxBufferLinesWidth); 
         ObjectSet(s6,OBJPROP_STYLE,STYLE_SOLID);
      } 
      ObjectSet(s6,OBJPROP_TIME1,BoxEnd[q8_1]); 
      ObjectSet(s6,OBJPROP_TIME2,iTime(Symbol(),q9_1,q8_1)); 
      ObjectSet(s6,OBJPROP_PRICE1,highBOcont[q8_1]); 
      ObjectSet(s6,OBJPROP_PRICE2,highBOcont[q8_1]);

      s7=StringConcatenate(Vs[32][33],TimeToStr((datetime)BoxStart[q8_1],3)); 
      if (ObjectFind(s7)==-1) 
      {
         ObjectCreate(s7,2,0,0,0,0,0); 
         ObjectSet(s7,OBJPROP_RAY,false);
         ObjectSet(s7,OBJPROP_COLOR,ContBoxBufferLinesColor); 
         ObjectSet(s7,OBJPROP_WIDTH,ContBoxBufferLinesWidth); 
         ObjectSet(s7,OBJPROP_STYLE,STYLE_SOLID);
      }
      ObjectSet(s7,OBJPROP_TIME1,BoxEnd[q8_1]); 
      ObjectSet(s7,OBJPROP_TIME2,iTime(Symbol(),q9_1,q8_1)); 
      ObjectSet(s7,OBJPROP_PRICE1,lowBOcont[q8_1]);
      ObjectSet(s7,OBJPROP_PRICE2,lowBOcont[q8_1]);

      q1= (int)(1+(m5_1==0)); 
      while(q1<=2) 
      {
         q2=1; 
         while(q2<=2) 
         {
            s5=Vs[32][q1*10+q2+13]; 
            if (ObjectFind(s5)==-1) 
            {
               ObjectCreate(s5,22,0,0,0);
               q3=(q1==1)*ContBoxPriceColor+(q1==2)*BreakoutPriceColor;
               ObjectSet(s5,OBJPROP_ARROWCODE,SYMBOL_RIGHTPRICE); 
               ObjectSet(s5,OBJPROP_COLOR,q3); 
               ObjectSet(s5,OBJPROP_WIDTH,BreakoutPriceWidth);
            }
            m1=(q1==1 && q2==1)*(highBOcont[q8_1]-m5_1)+(q1==1 && q2==2)*(lowBOcont[q8_1]+m5_1)+(q1==2 && q2==1)*highBOcont[q8_1]+(q1==2 && q2==2)*lowBOcont[q8_1];
            ObjectMove(s5,0,iTime(Symbol(),Period(),0),m1); q2++;
         }
         q1++;
      }

      if (ShowFibs && q8_1==1) 
      {
         RemoveObjects(StringConcatenate(" Fib ",TimeToStr((datetime)CZone[num_boxes-1][1],3)));
         d[1]=highBOcont[q8_1]-m5_1; 
         d[2]=lowBOcont[q8_1]+m5_1; 
         m4=d[1]-d[2]; 
         q1=1; 
         while(q1<=2) 
         {
            q2=1; 
            while(q2<=19 && Fib[q2]>0) 
            {
               s7=StringConcatenate(Vs[32][q1*20+q2+20],TimeToStr((datetime)BoxStart[q8_1],3)); 
               if (ObjectFind(s7)==-1) 
               {
                  ObjectCreate(s7,2,0,0,0,0,0); 
                  ObjectSet(s7,OBJPROP_RAY,false);
                  ObjectSet(s7,OBJPROP_COLOR,FibsLinesColor); 
                  ObjectSet(s7,OBJPROP_WIDTH,FibsLinesWidth); 
                  ObjectSet(s7,OBJPROP_STYLE,STYLE_SOLID);
               }
               q4=iBarShift(Symbol(),Period(),(int)BoxStart[q8_1])-iBarShift(Symbol(),Period(),(int)BoxEnd[q8_1]);
               ObjectSet(s7,OBJPROP_TIME1,iTime(Symbol(),TF[0],q8_1+q4)); 
               ObjectSet(s7,OBJPROP_TIME2,iTime(Symbol(),TF[0],q8_1)); 
               m3=d[q1]+(3-q1*2)*m4*Fib[q2];
               ObjectSet(s7,OBJPROP_PRICE1,m3); 
               ObjectSet(s7,OBJPROP_PRICE2,m3);

               s7=StringConcatenate(Vs[32][q1*20+q2+20],TimeToStr((datetime)BoxStart[q8_1],3)," "); 
               if (ObjectFind(s7)==-1) 
               {
                  ObjectCreate(s7,OBJ_TEXT,0,0,0);
               }
               m2=NormalizeDouble((m4*Fib[q2])/(mult*Point),1); 
               s1=StringConcatenate(DoubleToStr(m2,(mult==10 && MathFloor(m2)!=m2))," pips, ",DoubleToStr(m3,Digits)); q3=(int)(StringLen(s1)*1.7);
               s1=StringConcatenate(s1,StringSubstr(Empty,0,q3));
               ObjectSetText(s7,s1,FibsFontSize,Fonts,FibsLinesColor); 
               ObjectSet(s7,OBJPROP_TIME1,iTime(Symbol(),TF[0],q8_1)); 
               ObjectSet(s7,OBJPROP_PRICE1,m3+(q1==1)*Tdist); q2++;
            } 
            q1++;
         }
      }

      if (ShowSwings && q8_1==1) 
      {
         RemoveObjects(StringConcatenate(Vs[30][2],"Swing ",TimeToStr((datetime)CZone[num_boxes-2][1],3)));
         q0=num_boxes-1; 
         while(q0<=num_boxes) 
         {
            d[1]=CZone[q0][4]-m5_1; 
            d[2]=CZone[q0][5]+m5_1; 
            q1=1; 
            while(q1<=2) 
            {
               q3=0; 
               q6=iBarShift(Symbol(),TF[0],(int)CZone[q0][3]); 
               q2=iBarShift(Symbol(),TF[0],(int)CZone[q0][2])-1; 
               while(q2>=q6+(q6==1)) 
               {
                  m1=Swing(q1,q2); 
                  m3=((3-q1*2)*(m1-d[q1])>0 && ((3-q1*2)*(m1-Temp[q1][q3])>0 || q3==0))*m1; 
                  if (m3>0) 
                  {
                     q3++; Temp[q1][q3]=m3; q5=q2;
                  } 
                  q2--;
               } 
               if (Temp[q1][q3]>0 && q3>0) 
               {
                  m3=Temp[q1][q3]; 
                  s7=StringConcatenate(Vs[30][2],"Swing ",TimeToStr((datetime)CZone[q0][1],3)," ",q1," ",q3-1); ObjectDelete(s7);
                  s7=StringConcatenate(Vs[30][2],"Swing ",TimeToStr((datetime)CZone[q0][1],3)," ",q1," ",q3); 
                  if (ObjectFind(s7)==-1) 
                  {
                     ObjectCreate(s7,2,0,0,0,0,0); 
                     ObjectSet(s7,OBJPROP_RAY,false); 
                     ObjectSet(s7,OBJPROP_COLOR,SwingsLinesColor); 
                     ObjectSet(s7,OBJPROP_WIDTH,SwingsLinesWidth); 
                     ObjectSet(s7,OBJPROP_STYLE,STYLE_SOLID);
                     ObjectSet(s7,OBJPROP_TIME1,iTime(Symbol(),TF[0],q5+13)); 
                     ObjectSet(s7,OBJPROP_TIME2,iTime(Symbol(),TF[0],q5)); 
                     ObjectSet(s7,OBJPROP_PRICE1,m3); ObjectSet(s7,OBJPROP_PRICE2,m3);
                  }

                  s7=StringConcatenate(Vs[30][2],"Swing ",TimeToStr((datetime)CZone[q0][1],3)," ",q1," ",q3-1," ");  ObjectDelete(s7);
                  s7=StringConcatenate(Vs[30][2],"Swing ",TimeToStr((datetime)CZone[q0][1],3)," ",q1," ",q3," "); 
                  if (ObjectFind(s7)==-1) 
                  {
                     ObjectCreate(s7,OBJ_TEXT,0,0,0);
                     m2=NormalizeDouble((3-q1*2)*(Temp[q1][q3]-d[q1])/(mult*Point),1); 
                     s1=StringConcatenate(DoubleToStr(m2,(mult==10 && MathFloor(m2)!=m2))," pips, ",DoubleToStr(m3,Digits)); 
                     q2=(int)(StringLen(s1)*1.7);
                     s1=StringConcatenate(s1,StringSubstr(Empty,0,q2)); 
                     ObjectSetText(s7,s1,SwingsFontSize,Fonts,SwingsLinesColor); 
                     ObjectSet(s7,OBJPROP_TIME1,iTime(Symbol(),TF[0],q5)); 
                     ObjectSet(s7,OBJPROP_PRICE1,m3+(q1==1)*Tdist);
                  }
               } 
               q1++;
            } 
            q0++;
         }
      }
   }
}

//************************************************************************************************************************************************************
      
void RemoveObjects(string sPrefix)
{
	string sName = "";
	
   for(int i = ObjectsTotal() - 1; i >= 0; i--)
   {
   	sName = ObjectName(i);
   	
		if (StringFind(sName, sPrefix, 0) > -1) 
		{
         ObjectDelete(sName);
		}
	}
}

//************************************************************************************************************************************************************
//************************************************************************************************************************************************************