Download MetaTrader 5

HELP in coding for assign divergence in indicator " Awesome_Oscillator "

To add comments, please log in or register
Enable MQL5 Storage to store your source codes. It is free!
Mehrdad Shiri
4480
Mehrdad Shiri 2013.05.14 12:41 

hi;

PROBLEM ABOUT delete trend line's when change time frame.

in main chart trend line will be delete , but in separate window there is problem

in separate window where trend line have arrow , that is correct & other should be deleted.


//+------------------------------------------------------------------+
//|                                           Awesome_Oscillator.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//---- indicator settings
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots   3
#property indicator_type1   DRAW_COLOR_HISTOGRAM
#property indicator_color1  Green,Red
#property indicator_width1  1
#property indicator_label1  "AO"
//+----------------------------------------------+
//|  Bullish indicator drawing parameters        |
//+----------------------------------------------+
//---- drawing the indicator 4 as a symbol
#property indicator_type2   DRAW_ARROW
//---- lime color is used as the color of the bullish line of the indicator
#property indicator_color2  Lime
//---- thickness of the indicator 4 line is equal to 4
#property indicator_width2  1
//---- displaying the indicator label
#property indicator_label2 "Buy"
//+----------------------------------------------+
//|  Bearish indicator drawing parameters        |
//+----------------------------------------------+
//---- drawing the indicator 5 as a symbol
#property indicator_type3   DRAW_ARROW
//---- magenta color is used for the indicator bearish line
#property indicator_color3  Magenta
//---- thickness of the indicator 5 line is equal to 4
#property indicator_width3  1
//---- displaying the indicator label
#property indicator_label3  "Sell"
//--- indicator buffers
double ExtAOBuffer[];
double ExtColorBuffer[];
double ExtFastBuffer[];
double ExtSlowBuffer[];
//--- handles for MAs
int    ExtFastSMAHandle;
int    ExtSlowSMAHandle;
//--- bars minimum for calculation
#define DATA_LIMIT 33
//----------------------------------------------------------- Awesome_Oscillator divergens
#define arrowsDisplacement 0.0001
double bullishDivergence[];
double bearishDivergence[];
input bool drawIndicatorTrendLines=true;
input bool drawPriceTrendLines=true;
input bool displayAlert=true;
input color BulliDiverColor=Lime;
input color BearDiverColor=Red;
string   indicatorName;
datetime lastAlerttime;
//*************************************************************************
bool foreground;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//---- indicator buffers mapping
   SetIndexBuffer(0,ExtAOBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtColorBuffer,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(4,ExtFastBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,ExtSlowBuffer,INDICATOR_CALCULATIONS);
   
   ArraySetAsSeries(ExtAOBuffer,true);
   ArraySetAsSeries(ExtColorBuffer,true);
   ArraySetAsSeries(ExtFastBuffer,true);
   ArraySetAsSeries(ExtSlowBuffer,true);
   
//---- set bullishDivergence[] dynamic array as an indicator buffer
   SetIndexBuffer(2,bullishDivergence,INDICATOR_DATA);
//---- shifting the start of drawing of the indicator 4
   //PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,start);
//---- create a label to display in DataWindow
   PlotIndexSetString(1,PLOT_LABEL,"Buy");
//---- indicator symbol
   PlotIndexSetInteger(1,PLOT_ARROW,233);
//---- indexing elements in the buffer as timeseries
   ArraySetAsSeries(bullishDivergence,true);
//---- restriction to draw empty values for the indicator
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE);

//---- set bearishDivergence[] dynamic array as an indicator buffer
   SetIndexBuffer(3,bearishDivergence,INDICATOR_DATA);
//---- shifting the start of drawing of the indicator 5
   //PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,start);
//---- create a label to display in DataWindow
   PlotIndexSetString(2,PLOT_LABEL,"Sell");
//---- indicator symbol
   PlotIndexSetInteger(2,PLOT_ARROW,234);
//---- indexing elements in the buffer as timeseries
   ArraySetAsSeries(bearishDivergence,true);
//---- restriction to draw empty values for the indicator
   PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,EMPTY_VALUE);
   
//--- set accuracy
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,33);
//--- name for DataWindow 
   IndicatorSetString(INDICATOR_SHORTNAME,"AO");
//--- get handles
   ExtFastSMAHandle=iMA(NULL,0,5,0,MODE_SMA,PRICE_MEDIAN);
   ExtSlowSMAHandle=iMA(NULL,0,34,0,MODE_SMA,PRICE_MEDIAN);
//---- initialization done
  }
//+------------------------------------------------------------------+
//|  Awesome Oscillator                                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &TickVolume[],
                const long &Volume[],
                const int &Spread[])
  {
//--- check for rates total
   if(rates_total<=DATA_LIMIT)
      return(0);// not enough bars for calculation
//--- not all data may be calculated
   int calculated=BarsCalculated(ExtFastSMAHandle);
   if(calculated<rates_total)
     {
      Print("Not all data of ExtFastSMAHandle is calculated (",calculated,"bars ). Error",GetLastError());
      return(0);
     }
   calculated=BarsCalculated(ExtSlowSMAHandle);
   if(calculated<rates_total)
     {
      Print("Not all data of ExtSlowSMAHandle is calculated (",calculated,"bars ). Error",GetLastError());
      return(0);
     }
//--- we can copy not all data
   int to_copy;
   if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total;
   else
     {
      to_copy=rates_total-prev_calculated;
      if(prev_calculated>0) to_copy++;
     }
//--- get FastSMA buffer
   if(IsStopped()) return(0); //Checking for stop flag
   if(CopyBuffer(ExtFastSMAHandle,0,0,to_copy,ExtFastBuffer)<=0)
     {
      Print("Getting fast SMA is failed! Error",GetLastError());
      return(0);
     }
//--- get SlowSMA buffer
   if(IsStopped()) return(0); //Checking for stop flag
   if(CopyBuffer(ExtSlowSMAHandle,0,0,to_copy,ExtSlowBuffer)<=0)
     {
      Print("Getting slow SMA is failed! Error",GetLastError());
      return(0);
     }
//--- first calculation or number of bars was changed
   int i,limit;
   if(prev_calculated<=DATA_LIMIT)
     {
      for(i=0;i<DATA_LIMIT;i++)
         ExtAOBuffer[i]=0.0;
      limit=DATA_LIMIT;
     }
   else limit=prev_calculated-1;
//--- main loop of calculations
   //for(i=limit;i<rates_total ;i++)
   for(i=0;i<rates_total-1 ;i++)
     {
      ExtAOBuffer[i]=ExtFastBuffer[i]-ExtSlowBuffer[i];
      if(ExtAOBuffer[i]>ExtAOBuffer[i+1])ExtColorBuffer[i]=0.0; // set color Green
      else                               ExtColorBuffer[i]=1.0; // set color Red
     }
//---------------------------------------------------------------------------------------- Awesome_Oscillator divergens

//---- indexing elements in arrays as timeseries  
   ArraySetAsSeries(time,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);   
//---- declaration of integer variables
   int MaxBar1,MaxBar2,MaxBar3,limit1,limit2,limit3,bar;
//---- declaration of variables with a floating point  
   double price_;   
//---- initialization of the indicator in the OnCalculate() block
   if(prev_calculated>rates_total || prev_calculated<=0)// checking for the first start of the indicator calculation
     {
      limit1=rates_total-1-4; // starting index for calculation of all first loop bars
      limit2=limit1-1; // starting index for calculation of all second loop bars
      limit3=limit1; // starting index for calculation of all third loop bars
     }
   else // starting index for calculation of new bars
     {
      limit1=rates_total-prev_calculated;
      limit2=limit1;
      limit3=limit1;
     }
   MaxBar1=rates_total-1-4;
   MaxBar2=MaxBar1;
   MaxBar3=MaxBar1;
//---- main indicator calculation loop
   for(bar=limit1; bar>=0; bar--)
     {
      price_=PriceSeries(PRICE_CLOSE,bar,open,low,high,close);
     }
//---- main indicator calculation for Divergence loop

   for(bar=limit3+2; bar>=0; bar--)
     {
      bullishDivergence[bar]=EMPTY_VALUE;
      bearishDivergence[bar]=EMPTY_VALUE;

      CatchBullishDivergence(low,time,MaxBar3,bar);
      CatchBearishDivergence(high,time,MaxBar3,bar);
     }      
     
//----------------------------------------------------------------------------------------------------------//
   Comment(""
           ,"\nExtAOBuffer[0]=",ExtAOBuffer[0]
           ,"\nExtAOBuffer[1]=",ExtAOBuffer[1]
           ,"\nExtAOBuffer[2]=",ExtAOBuffer[2]
          );  
//----------------------------------------------------------------------------------------------------------//      
//--- return value of prev_calculated for next call
   return(rates_total);
  }

//+------------------------------------------------------------------+
//----------------------------------------------------------------------------------------------------------//
//+------------------------------------------------------------------+
//| The indicator maximum checking function                          |
//+------------------------------------------------------------------+
bool IsIndicatorPeak(int shift)
  {
   if(shift==0) return(false);
   if(ExtAOBuffer[shift]>=ExtAOBuffer[shift+1]
      && ExtAOBuffer[shift]>ExtAOBuffer[shift+2]
      && ExtAOBuffer[shift]>ExtAOBuffer[shift-1])  return(true);
   return(false);
  }
//+------------------------------------------------------------------+
//| The indicator last maximum searching function                    |
//+------------------------------------------------------------------+
int GetIndicatorLastPeak(int shift,int rates_total_)
  {
   for(int j=shift+5; j<rates_total_; j++)
      {
       if(ExtAOBuffer[j]>=ExtAOBuffer[j+1]
          && ExtAOBuffer[j]>ExtAOBuffer[j+2]
          && ExtAOBuffer[j]>=ExtAOBuffer[j-1]
          && ExtAOBuffer[j]>ExtAOBuffer[j-2])  return(j);
      }
   return(-1);
  }
//+------------------------------------------------------------------+
//| Bearish divergence searching function                            |
//+------------------------------------------------------------------+
void CatchBearishDivergence(const double &high[],const datetime &time[],int rates_total_,int shift)
  {
   if(IsIndicatorPeak(shift)==false)
      return;
   int currentPeak=shift;
   int lastPeak=GetIndicatorLastPeak(shift,rates_total_);
//----   
   if(lastPeak==-1)return;

   if(ExtAOBuffer[currentPeak]<ExtAOBuffer[lastPeak] && 
      high[currentPeak]>high[lastPeak])
     {
      bearishDivergence[currentPeak]=ExtAOBuffer[currentPeak]+
                                     arrowsDisplacement;
      if(drawIndicatorTrendLines==true)
         DrawIndicatorTrendLine(time[currentPeak],time[lastPeak],
                                ExtAOBuffer[currentPeak],
                                ExtAOBuffer[lastPeak],BearDiverColor,STYLE_SOLID);                          
      if(drawPriceTrendLines==true)
         DrawPriceTrendLine(time[currentPeak],time[lastPeak],
                            high[currentPeak],
                            high[lastPeak],BearDiverColor,STYLE_SOLID);
      if(displayAlert==true)
         DisplayAlert(time,"Classical bearish divergence on: ",currentPeak);
     }
//----     
   if(ExtAOBuffer[currentPeak]>ExtAOBuffer[lastPeak] && 
      high[currentPeak]<high[lastPeak])
     {
      bearishDivergence[currentPeak]=ExtAOBuffer[currentPeak]+
                                     arrowsDisplacement;
      if(drawIndicatorTrendLines==true)
         DrawIndicatorTrendLine(time[currentPeak],time[lastPeak],
                                ExtAOBuffer[currentPeak],
                                ExtAOBuffer[lastPeak],BearDiverColor,STYLE_DOT);                         
      if(drawPriceTrendLines==true)
         DrawPriceTrendLine(time[currentPeak],time[lastPeak],
                            high[currentPeak],
                            high[lastPeak],BearDiverColor,STYLE_DOT);
      if(displayAlert==true)
         DisplayAlert(time,"Reverse bearish divergence on: ",
                      currentPeak);
     }
  }
//+------------------------------------------------------------------+
//| The indicator minimum checking function                          |
//+------------------------------------------------------------------+
bool IsIndicatorTrough(int shift)
  {
   if(shift==0) return(false);
   if(ExtAOBuffer[shift]<=ExtAOBuffer[shift+1]
      && ExtAOBuffer[shift]<ExtAOBuffer[shift+2]
      && ExtAOBuffer[shift]<ExtAOBuffer[shift-1])  return(true);
   return(false);
  }
//+------------------------------------------------------------------+
//| The indicator last minimum searching function                    |
//+------------------------------------------------------------------+
int GetIndicatorLastTrough(int shift,int rates_total_)
  {
   for(int j=shift+5; j<rates_total_; j++)
     {
      if(ExtAOBuffer[j]<=ExtAOBuffer[j+1]
          && ExtAOBuffer[j]<ExtAOBuffer[j+2]
          && ExtAOBuffer[j]<=ExtAOBuffer[j-1]
          && ExtAOBuffer[j]<ExtAOBuffer[j-2])  return(j);
     }
   return(-1);
  }
//+------------------------------------------------------------------+
//| Bullish divergence searching function                            |
//+------------------------------------------------------------------+
void CatchBullishDivergence(const double &low[],const datetime &time[],int rates_total_,int shift)
  {
   if(IsIndicatorTrough(shift)==false) return;
   int currentTrough=shift;
   int lastTrough=GetIndicatorLastTrough(shift,rates_total_);
   if(lastTrough==-1)return;

   if(ExtAOBuffer[currentTrough]>ExtAOBuffer[lastTrough] && 
      low[currentTrough]<low[lastTrough])
     {
      bullishDivergence[currentTrough]=ExtAOBuffer[currentTrough]-
                                       arrowsDisplacement;
      if(drawPriceTrendLines==true)
         DrawPriceTrendLine(time[currentTrough],time[lastTrough],
                            low[currentTrough],low[lastTrough],BulliDiverColor,STYLE_SOLID);
      if(drawIndicatorTrendLines==true)
         DrawIndicatorTrendLine(time[currentTrough],time[lastTrough],
                                ExtAOBuffer[currentTrough],ExtAOBuffer[lastTrough],BulliDiverColor,STYLE_SOLID);
      if(displayAlert==true)
         DisplayAlert(time,"Classical bullish divergence on: ",currentTrough);
     }
//----   
   if(ExtAOBuffer[currentTrough]<ExtAOBuffer[lastTrough] && 
      low[currentTrough]>low[lastTrough])
     {
      bullishDivergence[currentTrough]=ExtAOBuffer[currentTrough]-arrowsDisplacement;
      if(drawPriceTrendLines==true)
         DrawPriceTrendLine(time[currentTrough],time[lastTrough],
                            low[currentTrough],low[lastTrough],BulliDiverColor,STYLE_DOT);
      if(drawIndicatorTrendLines==true)
         DrawIndicatorTrendLine(time[currentTrough],time[lastTrough],
                                ExtAOBuffer[currentTrough],ExtAOBuffer[lastTrough],BulliDiverColor,STYLE_DOT);
      if(displayAlert==true)
         DisplayAlert(time,"Reverse bullish divergence on: ",currentTrough);
     }
//----
  }
//+------------------------------------------------------------------+
//| Function for drawing a trend line in the indicator window        |
//+------------------------------------------------------------------+
void DrawIndicatorTrendLine(datetime x1,datetime x2,double y1,
                            double y2,color lineColor,int style)
  {
   int indicatorWindow=ChartWindowFind(0,indicatorName);
   if(indicatorWindow<0) return;
   string label="AO_DivergenceLine.0$# "+DoubleToString(x1,0);

   if(ObjectFind(0,label)==-1)
     {
      ObjectCreate(0,label,OBJ_TREND,indicatorWindow,x1,y1,x2,y2);
      ObjectSetInteger(0,label,OBJPROP_COLOR,lineColor);
      ObjectSetInteger(0,label,OBJPROP_STYLE,style);
      ObjectSetInteger(0,label,OBJPROP_WIDTH,1);
      ObjectSetInteger(0,label,OBJPROP_RAY,0);
      ObjectSetInteger(0,label,OBJPROP_BACK,true);
     }
   else
     {
      ObjectMove(0,label,0,x1,y1);
      ObjectMove(0,label,1,x2,y2);
     }
  }
//+------------------------------------------------------------------+
//| Function for drawing a trend line in a price chart window        |
//+------------------------------------------------------------------+
void DrawPriceTrendLine(datetime x1,datetime x2,double y1,
                        double y2,color lineColor,int style)
  {
   string label="AO_DivergenceLine.0# "+DoubleToString(x1,0);

   if(ObjectFind(0,label)==-1)
     {
      ObjectCreate(0,label,OBJ_TREND,0,x1,y1,x2,y2);
      ObjectSetInteger(0,label,OBJPROP_COLOR,lineColor);
      ObjectSetInteger(0,label,OBJPROP_STYLE,style);
      ObjectSetInteger(0,label,OBJPROP_WIDTH,1);
      ObjectSetInteger(0,label,OBJPROP_RAY,0);
      ObjectSetInteger(0,label,OBJPROP_BACK,true);
     }
   else
     {
      ObjectMove(0,label,0,x1,y1);
      ObjectMove(0,label,1,x2,y2);
     }
  }  
//+------------------------------------------------------------------+
//| Messages display function                                        |
//+------------------------------------------------------------------+
void DisplayAlert(const datetime &time[],string message,int shift)
  {
   if(shift<=2 && time[shift]!=lastAlerttime)
     {
      lastAlerttime=time[shift];
      Alert(message,Symbol()," , ",EnumToString(Period())," minutes chart");
     }
  }
//+------------------------------------------------------------------+   
//| PriceSeries() function                                           |
//+------------------------------------------------------------------+ 
double PriceSeries(uint applied_price,  // Price constant
                   uint   bar,          // Index of shift relative to the current bar for a specified number of periods back or forward).
                   const double &Open[],
                   const double &Low[],
                   const double &High[],
                   const double &Close[]
                  )
//PriceSeries(applied_price, bar, open, low, high, close)
//+------------------------------------------------------------------+
  {
//----
   switch(applied_price)
     {
      //---- Price constants from the ENUM_APPLIED_PRICE enumeration
      case  PRICE_CLOSE: return(Close[bar]);
      case  PRICE_OPEN: return(Open [bar]);
      case  PRICE_HIGH: return(High [bar]);
      case  PRICE_LOW: return(Low[bar]);
      case  PRICE_MEDIAN: return((High[bar]+Low[bar])/2.0);
      case  PRICE_TYPICAL: return((Close[bar]+High[bar]+Low[bar])/3.0);
      case  PRICE_WEIGHTED: return((2*Close[bar]+High[bar]+Low[bar])/4.0);

      //----                            
      case  8: return((Open[bar] + Close[bar])/2.0);
      case  9: return((Open[bar] + Close[bar] + High[bar] + Low[bar])/4.0);
      //----                                
      case 10:
        {
         if(Close[bar]>Open[bar])return(High[bar]);
         else
           {
            if(Close[bar]<Open[bar])
               return(Low[bar]);
            else return(Close[bar]);
           }
        }
      //----         
      case 11:
        {
         if(Close[bar]>Open[bar])return((High[bar]+Close[bar])/2.0);
         else
           {
            if(Close[bar]<Open[bar])
               return((Low[bar]+Close[bar])/2.0);
            else return(Close[bar]);
           }
         break;
        }
      //----
      default: return(Close[bar]);
     }
//----
//return(0);
  }
//+------------------------------------------------------------------+   
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+    
void OnDeinit(const int reason)
  {
   Comment("");
   ObjectsDeleteAll(0,0,OBJ_ARROW);
   ObjectsDeleteAll(0,0,OBJ_TREND);
   ChartRedraw();
   ChartSetInteger(0,CHART_FOREGROUND,foreground);
//----   
   string Name;
   for(int obj=ObjectsTotal(0,-1,-1)-1; obj>=0; obj--)
     {
      Name=ObjectName(0,obj,-1,-1);
      if(StringSubstr(Name,0,21)=="AO_DivergenceLine.0") ObjectDelete(0,Name);
     }
//----
  }
//+------------------------------------------------------------------+
Kourosh Davallou
40213
Kourosh Davallou 2013.05.14 13:34  

Hi Mehrdad

void OnInit()
  {
   .
   .
   .
   ObjectsDeleteAll(0);
Mehrdad Shiri
4480
Mehrdad Shiri 2013.05.14 13:46  
kourosh1347:

Hi Kourosh &

thank you.

Mehrdad Shiri
4480
Mehrdad Shiri 2013.05.14 16:37  
kourosh1347:
void OnInit()
  {
   .
   .
   .
   ObjectsDeleteAll(0);

this, will delete all object , also that object's create manually.

i try to fix in code;

any help ?

;-)

Mehrdad Shiri
4480
Mehrdad Shiri 2013.05.16 12:51  

I still have not solve the problem,

PROBLEM ABOUT delete trend line's when change time frame.

in main chart trend line will be delete , and it's very good & ok

but in separate window with change time frame trend line's does not delete.

in separate window where trend line have arrow , that is correct & other should be deleted ( they are belong to another time frame )

any help ?

Alain Verleyen
Moderator
30727
Alain Verleyen 2013.05.16 14:03  
TIMisthebest:

I still have not solve the problem,

PROBLEM ABOUT delete trend line's when change time frame.

in main chart trend line will be delete , and it's very good & ok

but in separate window with change time frame trend line's does not delete.

in separate window where trend line have arrow , that is correct & other should be deleted ( they are belong to another time frame )

any help ?

In your DeInit() function, change 0 with -1 as second parameter for ObjectsDeleteAll.

   ObjectsDeleteAll(0,-1,OBJ_ARROW);
   ObjectsDeleteAll(0,-1,OBJ_TREND);
Mehrdad Shiri
4480
Mehrdad Shiri 2013.05.16 15:06  
angevoyageur:

:-)

thank you again.

Kourosh Davallou
40213
Kourosh Davallou 2013.05.17 09:48  

hi again mehrdad

 int copy_Awesome_Oscillator_div_BUY_Divergence_LARGE=CopyBuffer(Awesome_Oscillator_div_handle_LARGE,2,0,rates_total,AO_BUY_bullishDivergence_Buffer_LARGE); 
   int copy_Awesome_Oscillator_div_SELL_Divergence_LARGE=CopyBuffer(Awesome_Oscillator_div_handle_LARGE,3,0,rates_total,AO_SELL_bearishDivergence_Buffer_LARGE);  
   for(int j=0; j<rates_total-2; j++)
      {
       if(AO_BUY_bullishDivergence_Buffer_LARGE[j]!=EMPTY_VALUE)  AO_BUY_bullishDivergence_Buffer_LARGE[j]=AO_BUY_Divergence_LARGE_LEVEL_DRAW;
       else AO_BUY_bullishDivergence_Buffer_LARGE[j]=0;
       if(AO_SELL_bearishDivergence_Buffer_LARGE[j]!=EMPTY_VALUE)  AO_SELL_bearishDivergence_Buffer_LARGE[j]=AO_SELL_Divergence_LARGE_LEVEL_DRAW; 
         else AO_SELL_bearishDivergence_Buffer_LARGE[j]=0;  
      }
Mehrdad Shiri
4480
Mehrdad Shiri 2013.05.17 10:20  
kourosh1347:

hi again mehrdad

hi

thank you.

To add comments, please log in or register