Basket_Viewer

Author: LukeB
Price Data Components
Series array that contains open time of each barSeries array that contains the highest prices of each barSeries array that contains the lowest prices of each barSeries array that contains open prices of each barSeries array that contains close prices for each bar
Indicators Used
Indicator of the average true range
0 Views
0 Downloads
0 Favorites
Basket_Viewer
ÿþ//+-----------------------------------------------------------------------+

//|  Inspired by                       Ahmad samir Virtual Trade.mq4      |

//|  https://www.mql5.com/en/forum/303765                                 |

//|                                                                       |

//|  Other References:                                                    |

//|  https://www.forexfactory.com/showthread.php?t=334555 (PitBull)       |

//+-----------------------------------------------------------------------+

string indicator_name = "Basket_Viewer";

#property copyright   "LukeB"

#property link        "https://www.mql5.com/en/users/lukeb"

#property version     "1.00";

#property description "View a Buy and a Sell Basket"

#property strict

#property indicator_chart_window

#property indicator_buffers 1

double    atr_buf[];

#property indicator_plots  0

// #include <errordescription.mqh>  // errordescription.mqh is found at: https://www.mql5.com/en/code/79 

//+------------------------------------------------------------------+

//|        ======= User Control ==============                       |

//+------------------------------------------------------------------+

input uint uniquifier      = 3856; // Make Object Names Unique

input int  CycleWeekLimit  = 10;   // Limit for weeks looked back (10)

//

input string SampleSellStr  = "CHFJPY,GBPCHF,GBPUSD,AUDJPY,EURGBP,USDCHF,EURJPY";   // Sample Sell Pairs "CHFJPY,GBPCHF,GBPUSD,AUDJPY,EURGBP,USDCHF,EURJPY";

input string SampleBuyStr   = "CADJPY,USDJPY,GBPJPY,USDCAD,EURCHF,AUDUSD,EURUSD";   // Sample Buy Pairs "CADJPY,USDJPY,GBPJPY,USDCAD,EURCHF,AUDUSD,EURUSD";

input string SetForSell     = "==Symbol Pairs for SELL==";                          // "==Symbol Pairs for SELL==";

input string SellPairs      = "CHFJPY,GBPCHF,GBPUSD,AUDJPY,EURGBP,USDCHF,EURJPY";   // Sell Pairs String

input string SetForBuy      = "==Symbol Pairs for BUY==";                           // "==Symbol Pairs for BUY==";

input string BuyPairs       = "CADJPY,USDJPY,GBPJPY,USDCAD,EURCHF,AUDUSD,EURUSD";   // Buy Pairs String

//

input string Colors_Setting = "Colors";

input color TitleClr        = clrWhite;

input color HeadClr         = clrWheat;

input color LotsSellClr     = clrCoral;

input color LotsBuyClr      = clrChartreuse;

input color TotalClr        = clrLightGoldenrod;

input color ProfitClr       = clrLimeGreen;

input color LossClr         = clrOrangeRed;

//======= End User Control ==============

//======= Custome EVENT Definitiions CHARTEVENT_CUSTOM_LAST   the last acceptable ID of a custom event (CHARTEVENT_CUSTOM +65535).

const ushort CHARTEVENT_MAKECHART = 37;

//---- Global Convenience Variables -----

enum DISP_OBJ_IDX       {TITLE_IDX, STRTWK_IDX, ENDWK_IDX, LONG_HDR_IDX, SHORT_HDR_IDX,  BSKT_ROW_IDX, SUM_LINE_IDX, SUMS_IDX, INDI_LBL_IDX, WK_MRK_IDX, END_DISP_OBJ_IDX};

string disp_obj_nms[] = {"_TITLE",  "_STARTWK", "_ENDWK",  "_LNG_HDR",   "_SHRT_HDR",   "_BSKT_ROW",   "_SUM_LINE",  "_SUMS",  "_INDI_LBL",  "_WK_MRK"   };

enum SYMBOL_OPERATION { SYMB_BUY, SYMB_SELL, SYMB_LBUY, SYMB_LSELL, SYMB_SBUY, SYMB_SSELL };

string GetOpDescription(const SYMBOL_OPERATION symb_op)  // Helper utility for names associated with the symbol operations enumeration.

{

   string desc_str;

   switch (symb_op)

    {

      case SYMB_BUY:   desc_str  = "Buy";    break;

      case SYMB_SELL:  desc_str  = "Sell";   break;

      case SYMB_LBUY:  desc_str  = "Buy_L";  break;

      case SYMB_LSELL: desc_str  = "Sell_L"; break;

      case SYMB_SBUY:  desc_str  = "Buy_S";  break;

      case SYMB_SSELL: desc_str  = "Sell_S"; break;

      default: desc_str = "UKN"; break;

    }

   return desc_str;

}//========= End GetOpDescription =============

enum ENUM_ON_OFF { ON, OFF };

enum ENUM_CHART_PLACEMENT {X_PLCMNT_IDX, Y_PLCMNT_IDX };       // Global Variable Names for Chart Placement

const int CHART_WINDOW = 0;

const int NOSHIFT      = 0;

const int NOMODIFIER   = 0;

//

class C_bsktCtrl

 {

   private:

      long xOriginPos, yOriginPos, xDragOffset, yPos, xPos;

      int  lineNum, columnNum, fontSize, yOffset;

      int col_1_offset, col_2_offset, col_3_offset, col_4_offset;

      bool selectable;

      color  objClr;

      string objName, objDispStr;

      ENUM_BASE_CORNER  objCorner;

      ENUM_ANCHOR_POINT objAnchor;

      int objWindow;

      int weekNum;

      ENUM_ON_OFF markWeek;

      datetime weekStart, weekEnd;

      int rangePeriods;

   protected:

      void SetInitialOrigin( const long& x_pos, const long& y_pos ){

         double globalVariableValue;

         int xPosMax = (int)  ChartGetInteger(ChartID(),CHART_WIDTH_IN_PIXELS,CHART_WINDOW);  // find chart width in pixels.

         int yPosMax = (int)  ChartGetInteger(ChartID(),CHART_HEIGHT_IN_PIXELS,CHART_WINDOW); // find chart heigth in pixels.

         double globalVariableResult = GlobalVariableGet(GetPositionGlobalName(X_PLCMNT_IDX),globalVariableValue);  // Get the x placement location - supports drag and drop for placement

         if( (globalVariableResult>0) && (globalVariableValue>-1) && (globalVariableValue<(xPosMax-col_1_offset)) ){ // No Error and a valid value (between 0 and not offscreen)

            xOriginPos = (long) globalVariableValue;

          } // else leave xOriginPos at the value it was instantiated with

         globalVariableResult = GlobalVariableGet(GetPositionGlobalName(Y_PLCMNT_IDX),globalVariableValue);   // Get the y placement location - supports drag and drop for placement

         if( (globalVariableResult>0) && (globalVariableValue>-1) && (globalVariableValue<(yPosMax-20)) ){ // No Error and a valid value (0 and 1 line from disapearing)

            yOriginPos = (long) globalVariableValue;

          } // else leave o_DispCtrl.xOriginPos at the value it was instantiated with

       }

   public:

      C_bsktCtrl(long x_pos, long y_pos, int font_size, color obj_clr){ // Constructor, provide defaults on creation

         SetDefaults(x_pos, y_pos, font_size, obj_clr);  // Set up the defaults

         markWeek=OFF;  weekNum=0;

         xOriginPos = x_pos; yOriginPos=y_pos;

         xDragOffset = 170;

         SetInitialOrigin(x_pos, y_pos);

       }//======= End C_bsktCtrl Constructor ================

      void SetDefaults(long x_pos, long y_pos, int font_size, color obj_clr){

         yPos=y_pos; xPos=x_pos; lineNum=0; columnNum=0; fontSize=font_size; yOffset=15;

         col_1_offset=320; col_2_offset=240; col_3_offset=160; col_4_offset=80;

         selectable=false; objClr=obj_clr; objCorner=CORNER_RIGHT_UPPER; objAnchor=ANCHOR_RIGHT_UPPER;

         objName=NULL; objDispStr=NULL; objWindow=CHART_WINDOW;

         rangePeriods = PeriodSeconds(PERIOD_W1)/PeriodSeconds(PERIOD_CURRENT)+1;  // always at least one

       }//======= End SetDefaults( ================

      string GetPositionGlobalName(const ENUM_CHART_PLACEMENT plcIdx){  // Function for global variable name so its always the same

         string gName="";

         switch (plcIdx){

            case X_PLCMNT_IDX: gName = "X_PLCEMENT_IDX"+IntegerToString(uniquifier); break;

            case Y_PLCMNT_IDX: gName = "Y_PLCEMENT_IDX"+IntegerToString(uniquifier); break;

            default: Print(__FUNCTION__+" Invalid Placement Index: "+IntegerToString(plcIdx)); break;

          }

         return(gName);

       }//========== END GetPositionGlobalName ==================

      void AddToWeekNum(int addAmount){  // change the week number

         weekNum += addAmount;

         if(weekNum<0){

            weekNum=CycleWeekLimit;

          }else if(weekNum>CycleWeekLimit){

            weekNum=0;

          }

       }//======= End AddToWeekNum ================

      ENUM_ON_OFF ToggleMarkWeek(void){

         markWeek=(markWeek==ON)?OFF:ON; // toggle the rectangle draw indicator

         return markWeek;

       }//=== END ToggleMarkWeek ================

      void SetOrigins(long newXpos, long newYpos) {  // Change the origin for future drawing

         xOriginPos = newXpos; // Set all the new positions

         yOriginPos = newYpos; // Set all the new positions

       }//========= End SetOrigins ============

      //======= Getters and Setters ========

      int    GetWindowNum(void)    {return objWindow;}

      ENUM_BASE_CORNER  GetBaseCorner(void) { return objCorner; }

      ENUM_ANCHOR_POINT GetObjectAnchor(void){return objAnchor; }

      color  GetDispClr(void)      {return objClr;}

      int    GetFontSize(void)     {return fontSize;}

      bool   GetSelectable(void)   {return selectable;}

      long   GetXOrigins(void)     {return xOriginPos;}

      long   GetYOrigins(void)     {return yOriginPos;}

      int    GetYOffSet(void)      {return yOffset;}

      long   GetXDragOffset(void)  {return xDragOffset;}

      string GetObjName(void)      {return objName;}

      string GetDispString(void)   {return objDispStr;}

      long   GetXPos(void)         {return xPos;}

      long   GetYPos(void)         {return yPos;}

      int    GetRangePeriods(void) {return rangePeriods;}

      int    GetDispWeekNum(void)  {return weekNum;}

      datetime GetWeekStartTime(void) {return iTime(_Symbol, PERIOD_W1, weekNum); }

      datetime GetWeekEndTime(void)   {return GetWeekStartTime()+(PeriodSeconds(PERIOD_W1)); }

      int    GetDispLineNum(void)  {return lineNum;}

      int GetColumnOneOffset(void){   return col_1_offset; }

      int GetColumnTwoOffset(void){   return col_2_offset; }

      int GetColumnThreeOffset(void){ return col_3_offset; }

      int GetColumnFourOffset(void){  return col_4_offset; }

      ENUM_ON_OFF GetIfWeekShouldBeMarked(void)  {return markWeek;}

      void SetIfWeekShouldBeMarked(ENUM_ON_OFF markSet){markWeek=markSet;}

      void SetColor(color objectClr)         { objClr = objectClr; }

      void SetObjName(string objectName)     { objName = objectName; }

      void SetDispString( string dispString) { objDispStr = dispString; }

      void SetXDispPos( long xDispPos )      { xPos = xDispPos; }

      void SetYDispPos( long yDispPos )      { yPos = yDispPos; }

      void IncrementLineNum( int incNum )    { lineNum += incNum; } 

      void SetSelectable( bool trueOrFalse ) { selectable = trueOrFalse; }

 } *c_bsktDispCtrl=NULL;  // Make a global pointer for this objec type

//

class C_pairsArys

 {

   private:

      SYMBOL_OPERATION symb_op;

      int pairRangePeriods;

      string pairs_ary[];    // Array of Pairs in the Basket

      double baseVal_ary[];  // Array of Basket Period Starting Prices for the Basket

      datetime baseTm_ary[]; // Array to capture the time of the baseVal_ary bar

      double baseATR_ary[];  // Array of ATRs for the Basket, in Points

      double pairVal_ary[];  // Array of Current Prices in the Basket

      double posVal_ary[];   // Array of Order Profit values for the basket

      double posLots_ary[];  // Array of Order Lots Exposed for the basket

      int ATRhandles_ary[];  // Array to hold a handle to get the ATR value for each pair.

      ulong handleErrCount_ary[]; // Array to count the errors for the error display.

      double speedBarOne_ary[];   // Array to hold value of speed calculation open price

      double speedBarZero_ary[];  // Array to hold value of speed calculation close price

      int atrPeriod;

      ENUM_ON_OFF USE_TERMINAL_ATR;

   protected:

      ENUM_INIT_RETCODE LoadInputPairs(const string& sourceString, const ENUM_INIT_RETCODE& init_status){ // Put delimited 'Input String' into the array

         ENUM_INIT_RETCODE result = init_status;

         if(result==INIT_SUCCEEDED){  // The pairs array is ready to accept symbol pairs

            const string delimitChar=",";  // Pairs are separated by comma

            string workString=sourceString;  // work with an independent string from user input

            // condition the workstring

            if(StringSubstr(workString,0,1)== delimitChar)   // Start with a pair, no leading delimiter character.

               workString += StringSubstr(workString,1,StringLen(workString)-1);

            if(StringSubstr(workString,StringLen(workString)-1,1)!= delimitChar)   // End with a delimiter character to assist with gettng the last pair out of the string.

               workString += delimitChar;

            //===== Increnment thru the strings deliminting characters and extract the pair identifiers between them.

            int startPos=0, foundPos, aryIdx=0, finalCharPos = StringLen(workString)-1;

            int aryRange = ArrayRange(pairs_ary,0);

            while (startPos < finalCharPos) {

               if(aryIdx>aryRange){ // Grew too large - could put an ArrayResizse here to grow the array.

                  Print(__FUNCTION__+"Pairs Input String contains too many pair identifications, initialiation failed");

                  break;

                }

               foundPos=StringFind(workString,delimitChar,startPos);

               pairs_ary[aryIdx]=StringSubstr(workString,startPos,foundPos-startPos);  // Extract Pair string an place in array

               aryIdx++;

               startPos=foundPos+1;

             }

          }

         return result;

       }// ====== END LoadInputPairs ============

      void CheckMarketWatch( void ) { // ensure the pairs are in the Market-Watch list

         for(int i=0; i<ArrayRange(pairs_ary,0); i++) {

            bool symbolFound=false;

            if(StringLen(pairs_ary[i])>0){  // The entry has something

               int countOfMarketWatchSymbols = SymbolsTotal(true); 

               for(int count=0; count < countOfMarketWatchSymbols; count++) {

                  int foundString = StringFind(SymbolName(count,true),pairs_ary[i],0);

                  if( foundString>-1 ) { // a matching string was found

                     pairs_ary[i]= SymbolName(count,true);  // Replace the input name with the market watch name (may have additional characters)

                     symbolFound=true;

                     break;  // don't look any further

                   }

                }

               if( (symbolFound==false) ){  // Symbol not found in MarketWatch - Give the user some feedback in the log

                  Print(GetOpDescription(symb_op)," Symbol: "+pairs_ary[i]+" was not found in MarketWatch (size: ",IntegerToString(StringLen(pairs_ary[i])),").");

                }

             }

          }

       }// =========== END CheckMarketWatch ===========

      ENUM_INIT_RETCODE CompressArray( void ){  // Take out any Null entries

         ENUM_INIT_RETCODE init_result = INIT_SUCCEEDED;

         int i=0;

         for(int j=0; j<ArrayRange(pairs_ary,0); i++,j++){

            while ( (StringLen(pairs_ary[j])<1) ) {

               j++;

               if(j==ArrayRange(pairs_ary,0)) break;

             }

            if( j<ArrayRange(pairs_ary,0) ) {

               pairs_ary[i]=pairs_ary[j];

             }

          }

         if(ArrayResize(pairs_ary,i-1)!=(i-1)) {

            int errCode=GetLastError();

            Print(GetOpDescription(symb_op)+" "__FUNCTION__" Array Resize Failed, Error: "+ IntegerToString(errCode));// +", "+ErrorDescription(error_code);

            init_result=INIT_FAILED;

          }

         return init_result;

      }//============ END CompressArray ===========

      ENUM_INIT_RETCODE SizePairArrays( const ENUM_INIT_RETCODE& init_status ){  // function for OnInit to call to size to the number of the user supplied pairs 

         ENUM_INIT_RETCODE result = init_status;

         int pairsSize = ArrayRange(pairs_ary,0);

         result = ResizeArray<double>(baseVal_ary,          pairsSize, result);

         result = ResizeArray<datetime>(baseTm_ary,         pairsSize, result);

         result = ResizeArray<double>(pairVal_ary,          pairsSize, result);

         result = ResizeArray<double>(posLots_ary,          pairsSize, result);

         result = ResizeArray<double>(posVal_ary,           pairsSize, result);

         result = ResizeArray<double>(baseATR_ary,          pairsSize, result);

         result = ResizeArray<int>(ATRhandles_ary,          pairsSize, result);

         result = ResizeArray<ulong>(handleErrCount_ary,    pairsSize, result);

         result = ResizeArray<double>(speedBarOne_ary,      pairsSize, result);

         result = ResizeArray<double>(speedBarZero_ary,     pairsSize, result);

         // Print(GetOpDescription(symb_op),", ",__FUNCTION__," Pairs Array Size: ",IntegerToString(pairsSize),", ATRhandels Array Size: ",IntegerToString(ArrayRange(ATRhandles_ary,0)));

         return result;

       }// == END SizePairArrays ============

      template <typename T>  // http://www.cplusplus.com/doc/tutorial/functions2/  templat allows one code block to be replicated by the compiler for all data types

      ENUM_INIT_RETCODE ResizeArray(T& array[], const int& ary_size, const ENUM_INIT_RETCODE& init_status){ // SizePairArrays Helper function to do the actual array resizing

         ENUM_INIT_RETCODE result = init_status;

         if(ary_size>0){ // There is some work to do

            if(ArrayResize(array,ary_size)!=ary_size){

               int errCode=GetLastError();

               result=INIT_FAILED; 

               Print(GetOpDescription(symb_op)+" array resize failed, error: "+IntegerToString(errCode)); // +", "+ErrorDescription(error_code);

             } else ArrayInitialize(array,NULL);

          }

         return result;

       }// ========== END ResizeArray ================

      int GetSymbolArrayIdx(string& matchString ){

         int retValue=-1;

         for(int idx=0; idx<ArrayRange(pairs_ary,0); idx++){

            if(pairs_ary[idx]==matchString){

               retValue=idx;

               break;

             }

          }

         return retValue;

       }//==== END GetSymbolArrayIdx ==========

      void SetATRHandle(const int& idx){  // Set One ATR Handle

               ATRhandles_ary[idx]=iATR(pairs_ary[idx], PERIOD_CURRENT, pairRangePeriods); // Get a Handle for the iATR terminal data

               if( ATRhandles_ary[idx]==INVALID_HANDLE ){

                  int error_code = GetLastError();

                  comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+" failed to find an ATR_Handle for "+pairs_ary[idx]+", Error: "+IntegerToString(error_code); // +", "+ErrorDescription(error_code);

                  Comment(comment_string); Print(comment_string);

                  // result=false; Just leave as invalid handle and don't get an ATR for the symbol

                }

       }// ======= END SetATRHandle ===================

      void SetTerminalATR(C_bsktCtrl* c_dispCtrl, double& indiValsBuf[], const ulong& callCounter){ // Use the Terminal iATR to get the ATR

         int weekEndBar = c_dispCtrl.GetRangePeriods()*c_dispCtrl.GetDispWeekNum();

         for(int idx=0; idx<ArrayRange(pairs_ary,0); idx++){

            long bars = Bars(pairs_ary[idx],PERIOD_CURRENT);

            if(ATRhandles_ary[idx] != INVALID_HANDLE){

               if(CopyBuffer(ATRhandles_ary[idx],0, weekEndBar,1,indiValsBuf)<=0){ // atr_buf // (handle, buffer Number, start pos, count, buffer[])

                  handleErrCount_ary[idx]++;

                  int errCode = GetLastError();

                  comment_string = GetOpDescription(symb_op)+" Getting Term ATR data (Call "+IntegerToString(callCounter)+") for "+pairs_ary[idx]+", Index: "+IntegerToString(idx)+", Handle: "

                                   +IntegerToString(ATRhandles_ary[idx])+" failed ("+IntegerToString(handleErrCount_ary[idx])

                                   +" times), Bar: "+IntegerToString(weekEndBar)+" of "+IntegerToString(bars)+", "+TimeToString(iTime(pairs_ary[idx],PERIOD_CURRENT,weekEndBar),TIME_DATE|TIME_MINUTES)

                                   +", Using 1 for the ATR, Error: "+IntegerToString(errCode); //+", "+ErrorDescription(errCode);

                  Comment(comment_string); Print(comment_string);

                  baseATR_ary[idx] = 1;  // never divide by zero.

                } else {

                  baseATR_ary[idx] = indiValsBuf[0]/SymbolInfoDouble(pairs_ary[idx],SYMBOL_POINT);

                  if(baseATR_ary[idx]<1){

                     comment_string= GetOpDescription(symb_op)+" Term ATR Call (Call "+IntegerToString(callCounter)+") for "+pairs_ary[idx]

                                    +" Bar "+IntegerToString(weekEndBar)+" of "+IntegerToString(bars)+" Bars, Time: "

                                    +TimeToString(iTime(pairs_ary[idx],PERIOD_CURRENT,weekEndBar),TIME_DATE|TIME_MINUTES)

                                    +", Calculed ATR: "+DoubleToString(baseATR_ary[idx],2)+", Using 1";

                     Comment(comment_string); Print(comment_string);

                     baseATR_ary[idx] = 1;  // never divide by zero.

                   }

                }

             }else{  // Is Equal to INVALID_HANDEL

               baseATR_ary[idx] = NULL;

               SetATRHandle(idx); // attempt to recover

             }

          }

       }// ======== End SetTerminalATR ==========

      void SetInternalATR(C_bsktCtrl* c_dispCtrl, const ulong& callCounter){ // Calculate the ATR

         int weekEndBar = c_dispCtrl.GetRangePeriods()*c_dispCtrl.GetDispWeekNum();

         for(int idx=0; idx<ArrayRange(pairs_ary,0); idx++){

            double high, low, range=0;

            static ulong callCount = 0; callCount++;

            long bars=Bars(pairs_ary[idx],PERIOD_CURRENT);

            for(int workBar=0; workBar<atrPeriod; workBar++){

               int valueBar=(weekEndBar+workBar);   //bars-(weekendBar+workBar) // (weekendBar-workBar); 

               if( valueBar < (bars-1) ){ // Haven't stepped past the oldest bar of the timeseries  // valueBar < (bars-1) // valueBar > (-1)

                  high = iHigh(pairs_ary[idx],PERIOD_CURRENT,valueBar);

                  if(high==0){

                     int errCode = GetLastError();

                     comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+", "+pairs_ary[idx]+"Call: "+IntegerToString(callCount)+", Bar: "+IntegerToString(valueBar)+", iHigh{"+IntegerToString(callCount)+") returned error: "+IntegerToString(errCode)+", using 1"; //, "+ErrorDescription(errCode);

                     Comment(comment_string); Print(comment_string);

                     high = 1;

                   }

                  low  = iLow(pairs_ary[idx],PERIOD_CURRENT,valueBar);

                  if(low==0){

                     int errCode = GetLastError();

                     comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+", "+pairs_ary[idx]+"Call: "+IntegerToString(callCount)+", Bar: "+IntegerToString(valueBar)+", iLow{"+IntegerToString(callCount)+") returned error: "+IntegerToString(errCode)+", using 1"; //, "+ErrorDescription(errCode);

                     Comment(comment_string); Print(comment_string);

                     low = 1;

                   }

                }else{

                  high = iHigh(pairs_ary[idx],PERIOD_CURRENT,0);

                  if(high==0){

                     int errCode = GetLastError();

                     comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+", "+pairs_ary[idx]+"Call: "+IntegerToString(callCount)+", Bar: 0, iHigh{"+IntegerToString(callCount)+") returned error: "+IntegerToString(errCode)+", using 1"; // , "+ErrorDescription(errCode);

                     Comment(comment_string); Print(comment_string);

                     high = 1;

                   }

                  low  = iLow(pairs_ary[idx],PERIOD_CURRENT,0);

                  if(low==0){

                     int errCode = GetLastError();

                     comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+", "+pairs_ary[idx]+"Call: "+IntegerToString(callCount)+", Bar: 0, iLow{"+IntegerToString(callCount)+") returned error: "+IntegerToString(errCode)+", using 1"; // , "+ErrorDescription(errCode);

                     Comment(comment_string); Print(comment_string);

                     high = 1;

                   }

                }

               range += MathAbs(high-low);  // Always Positve.

             }

            baseATR_ary[idx] = (int) ((range/atrPeriod)/SymbolInfoDouble(pairs_ary[idx],SYMBOL_POINT));

            if(baseATR_ary[idx]<1){

               comment_string= GetOpDescription(symb_op)+" Indi ATR Calc (Call "+IntegerToString(callCounter)+") for "+pairs_ary[idx]

                              +" Bar "+IntegerToString(weekEndBar)+" of "+IntegerToString(bars)+" Bars, Time: "

                              +TimeToString(iTime(pairs_ary[idx],PERIOD_CURRENT,weekEndBar),TIME_DATE|TIME_MINUTES)

                              +", Calculed ATR: "+DoubleToString(baseATR_ary[idx],2)+", Using 1";

               Comment(comment_string); Print(comment_string);

               baseATR_ary[idx] = 1;  // never divide by zero.

             }

          }

       } //==== END SetInternalATR ========

   public:

      void C_pairsArys(SYMBOL_OPERATION sym_op){  // constructot, set initial size and the oeration type for the pairs.

         symb_op = sym_op;

         atrPeriod = 14;

         USE_TERMINAL_ATR = ON;

         pairRangePeriods = PeriodSeconds(PERIOD_W1)/PeriodSeconds(PERIOD_CURRENT)+1;  // its a calendar weeks seconds, not a trading weeks seconds

       }//=== END C_pairsArys Constructor

      void ~C_pairsArys(void){ // Destructor, take actions to clean up after the object

         for(int idx=0; idx<ArrayRange(ATRhandles_ary,0); idx++){

            if(ATRhandles_ary[idx] != INVALID_HANDLE){ IndicatorRelease( ATRhandles_ary[idx] ); ATRhandles_ary[idx]=INVALID_HANDLE;}

          }

       }

      ENUM_INIT_RETCODE LoadPairsAry(int initialSize, const string& symbPairs){  // Insert User Control Values into the array

         ENUM_INIT_RETCODE result = INIT_SUCCEEDED;

         if(ArrayResize(pairs_ary,initialSize)!=initialSize){

            int errCode = GetLastError();

            Print(GetOpDescription(symb_op)+" ArrayResize of pairs_ary in C_pairsArys constructor failed, error: "+IntegerToString(errCode)); //+", "+ErrorDescription(errCode));

          } else { // Pairs array is prepared to accept symbols

            LoadInputPairs(symbPairs, result); // Put extern 'Input String' into the short symbol array

            CheckMarketWatch();          // ensure the pairs are in the Market-Watch list, set values to NULL that are not valid

            result = CompressArray();    // Take out any Null entries

            result = SizePairArrays(result);   // Size remaining arrays to match the pairs array size

          }

         if(result==INIT_SUCCEEDED){   // put this in to see if it will initialize iOpen and iClose such that the first 'Points' display is correct

            LoadBasePrices(1);         // The only reason to do this is observation that iOpen and iClose seem to need an 'initialization' before giving correct values.

            LoadSpeedBases(atrPeriod); // The only reason to do this is observation that iOpen and iClose seem to need an 'initialization' before giving correct values.

            SetCurrentSpeedPrices();   // The only reason to do this is observation that iOpen and iClose seem to need an 'initialization' before giving correct values.

          }

         return result;

       }//========== END LoadPairsAry =================

      void LoadBasePrices(const int weekNum){

         static ulong callCount=0; callCount++;

         for(int idx=0; idx<ArrayRange(pairs_ary,0); idx++){

            baseVal_ary[idx] = iOpen(pairs_ary[idx], PERIOD_W1, weekNum);

            if(baseVal_ary[idx]==0){

               int errCode = GetLastError();

               comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+", "+pairs_ary[idx]+", Bar: "+IntegerToString(weekNum)+", iOpen{"+IntegerToString(callCount)+") returned error: "+IntegerToString(errCode)+", using 1"; //, "+ErrorDescription(errCode);

               Comment(comment_string); Print(comment_string);

               baseVal_ary[idx] = 1;

             }

            baseTm_ary[idx]  = iTime(pairs_ary[idx], PERIOD_W1, weekNum);

          }

       }//========== END LoadBasePrices ==================

      void SetBasketCurrentPrices(C_bsktCtrl* c_dispCtrl){

         static ulong callCount=0; callCount++;

         for(int idx=0; idx<ArrayRange(pairs_ary,0); idx++){

            pairVal_ary[idx] = iClose(pairs_ary[idx], PERIOD_W1, c_dispCtrl.GetDispWeekNum());

            if(pairVal_ary[idx]==0){

               int errCode = GetLastError();

               comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+", "+pairs_ary[idx]+", Bar: "+IntegerToString(c_dispCtrl.GetDispWeekNum())+", iClose{"+IntegerToString(callCount)+") returned ereror: "+IntegerToString(errCode)+", using 1"; //, "+ErrorDescription(errCode);

               Comment(comment_string); Print(comment_string);

               pairVal_ary[idx] = 1;

             }

          }

       } // ====== END SetBasketCurrentPrices ==============

      void LoadSpeedBases(const int barNum){

         static ulong callCount=0; callCount++;

         for(int idx=0; idx<ArrayRange(pairs_ary,0); idx++){

            speedBarOne_ary[idx] = iOpen(pairs_ary[idx], PERIOD_CURRENT, barNum);

            if(speedBarOne_ary[idx]==0){

               int errCode = GetLastError();

               comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+", "+pairs_ary[idx]+", Bar: "+IntegerToString(barNum)+", iOpen{"+IntegerToString(callCount)+") returned error: "+IntegerToString(errCode)+", using 1"; //, "+ErrorDescription(errCode);

               Comment(comment_string); Print(comment_string);

               speedBarOne_ary[idx] = 1;

             }

          }

       }//========== END LoadSpeedBases ==================

      void SetCurrentSpeedPrices(void){

         static ulong callCount=0; callCount++;

         for(int idx=0; idx<ArrayRange(pairs_ary,0); idx++){

            speedBarZero_ary[idx] = iClose(pairs_ary[idx], PERIOD_CURRENT, 0);

            if(speedBarZero_ary[idx]==0){

               int errCode = GetLastError();

               comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+", "+pairs_ary[idx]+", Bar: 0, iClose{"+IntegerToString(callCount)+") returned error: "+IntegerToString(errCode)+", using 1"; //, "+ErrorDescription(errCode);

               Comment(comment_string); Print(comment_string);

               speedBarZero_ary[idx] = 1;

             }

          }

       }//========== END LoadCurrentSpeedPrice ==================

      double GetSpeedAngle(const int& pairIdx){

         static const double ninetyRatio=1.5;

         double speedRatio;

         static ulong callCount=0; callCount++;

         if( (speedBarOne_ary[pairIdx]==1) && (speedBarZero_ary[pairIdx]==1) ){

            speedRatio = 0;

            LoadSpeedBases(1); // Try to Recover (speedBarZero will be refreshed with the next call.

            comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+", "+pairs_ary[pairIdx]+", Bar One value is 0, using 0 for the angle{"+IntegerToString(callCount)+")";

            Comment(comment_string); Print(comment_string);

          }else{

            double pointVal = SymbolInfoDouble(pairs_ary[pairIdx],SYMBOL_POINT);

            if( pointVal==0 || baseATR_ary[pairIdx]==0){

               comment_string = GetOpDescription(symb_op)+" "+__FUNCTION__+", Call Count: ("+IntegerToString(callCount)+") Pair "+pairs_ary[pairIdx]

                                +", ATR Value: "+DoubleToString(baseATR_ary[pairIdx],2)+", Point Value: "+DoubleToString(pointVal,5);

               Comment(comment_string); Print(comment_string);

               speedRatio = 0;

             }else{

               speedRatio = (speedBarZero_ary[pairIdx]-speedBarOne_ary[pairIdx])/(baseATR_ary[pairIdx]*pointVal);

             }

          }

         double speedAngle;

         if(speedRatio > ninetyRatio){

            speedAngle = 90.0;

          }else if(speedRatio < -ninetyRatio){

            speedAngle = -90.0;

          }else {

            speedAngle = (speedRatio/ninetyRatio)*90.0;

          }

         return speedAngle;

       }//========== END GetSpeedAngle ==================

      //+------------------------------------------------------------------+

      //| Basekt Values Functions                                          |

      //+------------------------------------------------------------------+

      void SetBasketATRValues(C_bsktCtrl* c_dispCtrl, double& indiValsBuf[] ){

         static ulong callCounter=0;

         callCounter++;

         switch (USE_TERMINAL_ATR){

            case ON:  SetTerminalATR(c_dispCtrl, indiValsBuf, callCounter);  break;

            case OFF: SetInternalATR(c_dispCtrl, callCounter); break;

            default: SetInternalATR(c_dispCtrl, callCounter); break;

          }

       }//=========== END SetBasketATRValues =============

      void SetATRHandles(void){ // Get a Handle for each PAIR to access terminal ATR data

         // Print(GetOpDescription(symb_op),", ",__FUNCTION__,", ",GetOpDescription(symb_op)," Pairs Array Size: ",IntegerToString(ArrayRange(pairs_ary,0)),", ATRhandels Array Size: ",IntegerToString(ArrayRange(ATRhandles_ary,0)));

         for(int idx=0; idx<ArrayRange(pairs_ary,0); idx++){

            if( (USE_TERMINAL_ATR==ON) && ((ATRhandles_ary[idx]==INVALID_HANDLE) || (ATRhandles_ary[idx]==NULL)) ){

               SetATRHandle(idx);  // Set the handle

             }else{ // (USE_TERMINAL_ATR==OFF)

               if(ATRhandles_ary[idx] != INVALID_HANDLE){ IndicatorRelease( ATRhandles_ary[idx] ); ATRhandles_ary[idx]=INVALID_HANDLE;}

             }

          }

       } // ======== END SetATRHandles =========

      void SetPositionValues(void){

         ArrayInitialize(posVal_ary,0);   // Start with zero and add to it

         ArrayInitialize(posLots_ary,0);   // Start with zero and add to it

         int aryIdx; string positionSymbol;

         for(int i=PositionsTotal()-1; i>=0; i--){

            positionSymbol = PositionGetSymbol(i);

            aryIdx=GetSymbolArrayIdx(positionSymbol);

            if(aryIdx>-1){ // Found in the array

               posVal_ary[aryIdx]   += PositionGetDouble(POSITION_PROFIT);

               posLots_ary[aryIdx]  += PositionGetDouble(POSITION_VOLUME);

             }

          }

       }//======= END SetPositionValue ========

      //  Getters and Setters 

      void SetTerminalATRSouceSwitch(ENUM_ON_OFF useTerminal){USE_TERMINAL_ATR = useTerminal;}

      ENUM_ON_OFF GetATRSourceSwitchValue(void){return USE_TERMINAL_ATR;}

      string GetPairSymbol(int idx){ return pairs_ary[idx]; }

      SYMBOL_OPERATION GetSymbolOp(void){ return symb_op; }

      double GetSymbStartVal(int idx){ return baseVal_ary[idx]; }

      double GetSymbolEndVal(int idx){  return pairVal_ary[idx]; }

      double GetSymbolATRVal(int idx){  return baseATR_ary[idx]; }

      double GetSymbolPosVal(int idx){  return posVal_ary[idx]; }

      double GetSymbolLotsVal(int idx){ return posLots_ary[idx]; }

      int    GetPairArraySize(void){ return ArrayRange(pairs_ary,0); }

      datetime GetWeekTm(const int& idx){ return baseTm_ary[idx]; }

      //

 } *c_sellPairs=NULL, *c_buyPairs=NULL;  // make Global pointers to this object type

string comment_string="";  // for displaying and printing comments, gets cleaned up when indi is removed from chart.

datetime lastPostTime = NULL;

//+------------------------------------------------------------------+

//| Custom indicator initialization function                         |

//+------------------------------------------------------------------+

int OnInit() 

{ 

   ENUM_INIT_RETCODE init_result = INIT_SUCCEEDED;

   indicator_name = indicator_name+IntegerToString(uniquifier);  // Make name unigue to user suppliable instance identifier

   IndicatorSetString(INDICATOR_SHORTNAME,indicator_name);  // Give the indicator a name

   EventSetTimer(1);    //--- create a timer with a 1 second period

   init_result    = InitializeGlobalObjects(init_result); // Display Control, Buy Basket and Sell Basket creation and pointer initialization

   if( init_result==INIT_SUCCEEDED ){ // the objects got created

      init_result    = c_sellPairs.LoadPairsAry(50, SellPairs);        // Insert User Control Values into the work symbol array

      init_result    = c_buyPairs.LoadPairsAry(50, BuyPairs);          // Insert User Control Values into the work symbol array

      if( !HandlesSet( c_buyPairs, c_sellPairs) ){                     // set handles for the sybmols

         init_result = INIT_FAILED;

       }

    }

   SetIndexBuffer(0, atr_buf, INDICATOR_CALCULATIONS);  // Establish buffer for indicator buffer

   ArraySetAsSeries(atr_buf,true);   // make it as series so [0] is the newest value

   return(init_result);

}//========= END OnInit ==========

bool HandlesSet(C_pairsArys* buyStruc, C_pairsArys* sellStruc)  // Initialize handles used to get needed terminal data

{

   buyStruc.SetATRHandles();

   sellStruc.SetATRHandles();

   return true;  // decided not to fail, just handle invalid handle.

}//======== End HandlesSet =======

ENUM_INIT_RETCODE InitializeGlobalObjects( const ENUM_INIT_RETCODE& initCode) // Display Control, Buy Basket and Sell Basket creation and pointer initialization

{

   ENUM_INIT_RETCODE objectCreationResult = initCode;

   if( objectCreationResult == INIT_SUCCEEDED ){

      for(DISP_OBJ_IDX idx=0; idx<END_DISP_OBJ_IDX; idx++){ // Add uniquifier to Object Names to make them unique to this indicator

         disp_obj_nms[idx] = IntegerToString(uniquifier)+disp_obj_nms[idx];

       }

      if( c_bsktDispCtrl == NULL ){

         c_bsktDispCtrl = new C_bsktCtrl(40,40,11,clrNONE);

         if( c_bsktDispCtrl == NULL ){

            int errCode=GetLastError();

            Print(__FUNCTION__+" Failed to create a new Display Control Object, error: "+IntegerToString(errCode)); // +ErrorDescription(errCode));

            objectCreationResult = INIT_FAILED;

          }

       }

      if( c_sellPairs == NULL ){

         c_sellPairs=new C_pairsArys(SYMB_SELL);

         if( c_sellPairs == NULL ){

            int errCode=GetLastError();

            Print(__FUNCTION__+" Failed to create a new Sell Pairs object, error: "+IntegerToString(errCode)); // +ErrorDescription(errCode));

            objectCreationResult = INIT_FAILED;

          }

       }

      if( c_buyPairs == NULL ){

         c_buyPairs =new C_pairsArys(SYMB_BUY);

         if( c_buyPairs == NULL ){

            int errCode=GetLastError();

            Print(__FUNCTION__+" Failed to create a new Buy Pairs object, error: "+IntegerToString(errCode)); // +ErrorDescription(errCode));

            objectCreationResult = INIT_FAILED;

          }

       }

   }

   return objectCreationResult;

}//======== END InitializeGlobalObjects =============

//+------------------------------------------------------------------+

//| Custom indicator de-initialization function                      |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)  // Clean-up on exit

{

   EventKillTimer(); // Kill the timer

   if(c_bsktDispCtrl != NULL){ delete c_bsktDispCtrl; c_bsktDispCtrl=NULL; }

   if(c_sellPairs != NULL){ delete c_sellPairs; c_sellPairs=NULL; }

   if(c_buyPairs != NULL){ delete c_buyPairs;  c_buyPairs=NULL; }

   if(StringLen(comment_string)>0){  // Clean up the Comment if this indicator made one.

      Comment("");

    }

   for(int i = ObjectsTotal(ChartID()) - 1; i >= 0; i--)

    {

      string label = ObjectName(ChartID(),i);

      if(StringSubstr(label,0,StringLen(IntegerToString(uniquifier)))==IntegerToString(uniquifier)){  // Only delete objects with this indicators identifier on them

         ObjectDelete(ChartID(),label);

       }

    }

   ChartRedraw(ChartID());

}// ========= END OnDeinit ==========

//+------------------------------------------------------------------+

//| Chart Event Handler                                              |

//+------------------------------------------------------------------+

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)

 {

    if(id==CHARTEVENT_OBJECT_CLICK){

      Comment("");  // Clear old comment displays to ensure new are clear.

      if(sparam==disp_obj_nms[STRTWK_IDX]){   //  Increment the week

         c_bsktDispCtrl.AddToWeekNum(+1);

         c_buyPairs.LoadBasePrices(c_bsktDispCtrl.GetDispWeekNum());

         c_sellPairs.LoadBasePrices(c_bsktDispCtrl.GetDispWeekNum());

         LoadDashboardValuesAndDraw();

       }else if(sparam==disp_obj_nms[ENDWK_IDX]){  // Decrement the week

         c_bsktDispCtrl.AddToWeekNum(-1);

         c_buyPairs.LoadBasePrices(c_bsktDispCtrl.GetDispWeekNum());

         c_sellPairs.LoadBasePrices(c_bsktDispCtrl.GetDispWeekNum());

         LoadDashboardValuesAndDraw();

       }else if(sparam==disp_obj_nms[LONG_HDR_IDX]){ // Highlight the week (or turn of highlighting)

         if(c_bsktDispCtrl.ToggleMarkWeek()==OFF){

            ObjectDelete(ChartID(),disp_obj_nms[WK_MRK_IDX]);

          }else{  // == ON

            DrawRectangle(c_bsktDispCtrl, WK_MRK_IDX);

          }

         ChartRedraw(ChartID());

       }else if( StringSubstr(sparam,0,StringLen(disp_obj_nms[BSKT_ROW_IDX])) == disp_obj_nms[BSKT_ROW_IDX] ){  // Change the Chart Symbol

         int endPos     = StringFind(sparam, "PAIR", WHOLE_ARRAY);

         int startPos   = StringLen(disp_obj_nms[BSKT_ROW_IDX]);

         string pairStr = StringSubstr(sparam, startPos, endPos-startPos);

         if( pairStr != ChartSymbol(ChartID())){

            ChartSetSymbolPeriod(ChartID(),pairStr,PERIOD_CURRENT);

            ChartRedraw(ChartID());

          }

       }else if(sparam==disp_obj_nms[SHORT_HDR_IDX]){  // Toggle gettin ATR from the Terminal or from internal calculation

         ENUM_ON_OFF toggledSwitch = (c_buyPairs.GetATRSourceSwitchValue()==OFF?ON:OFF); // Get Toggled Value

         if(toggledSwitch==OFF){

            c_buyPairs.SetTerminalATRSouceSwitch(OFF);

            c_sellPairs.SetTerminalATRSouceSwitch(OFF);

          }else{ // Toggled to ON

            c_buyPairs.SetTerminalATRSouceSwitch(ON);

            c_sellPairs.SetTerminalATRSouceSwitch(ON);

          }

         c_buyPairs.SetATRHandles();

         c_sellPairs.SetATRHandles();

         LoadDashboardValuesAndDraw();

       }

    }else if(id==CHARTEVENT_CUSTOM+CHARTEVENT_MAKECHART){  // Request to Draw the Indicator Dashboard

      if(lparam==uniquifier){

         lastPostTime = TimeLocal();

         LoadDashboardValuesAndDraw();

       }

    }else if(id==CHARTEVENT_OBJECT_DRAG){  //sparam = Name of the moved graphical object

      if( sparam==disp_obj_nms[TITLE_IDX] ){  // This is the drage object, the pannel has been drug to a new location, display the panel at that location.

         long newXpos, newYpos;

         newXpos = ObjectGetInteger( ChartID(), sparam, OBJPROP_XDISTANCE, NOMODIFIER );   // Get after-drag Move Object Position

         newYpos = ObjectGetInteger( ChartID(), sparam, OBJPROP_YDISTANCE, NOMODIFIER );   // Get after-drag Move Object Position

         newXpos = newXpos - c_bsktDispCtrl.GetXDragOffset();                              // Adjust for the xOffset to the drag object (there is no y offset to the drag object

         c_bsktDispCtrl.SetOrigins(newXpos, newYpos);

         GlobalVariableSet(c_bsktDispCtrl.GetPositionGlobalName(X_PLCMNT_IDX), c_bsktDispCtrl.GetXOrigins());

         GlobalVariableSet(c_bsktDispCtrl.GetPositionGlobalName(Y_PLCMNT_IDX), c_bsktDispCtrl.GetYOrigins());

         DrawDisplay(c_sellPairs, c_buyPairs, c_bsktDispCtrl);                            // Display at the new position

         ChartRedraw(ChartID());

       }

    }

 }

//+------------------------------------------------------------------+

//| Custom indicator Timer Event Processin                           |

//+------------------------------------------------------------------+

void OnTimer()

{

   if((TimeLocal()-lastPostTime)>1 ){  // Update the chart at least every second.

      EventChartCustom(ChartID(),CHARTEVENT_MAKECHART, uniquifier, NULL, NULL);

    }

}

//+------------------------------------------------------------------+

//| Custom indicator iteration function                              |

//+------------------------------------------------------------------+

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& tick_volume[], const long& volume[], const int& spread[] )

{

   bool newWeek = ThereIsNewWeekBar();  // Detect if a new week is starting

   bool newBar  =  ThereIsNewChartBar();     // Detect if a new bar is starting on the Chart

   if( newWeek || (prev_calculated<1) || (rates_total<prev_calculated) ){

      if(newWeek){

         c_buyPairs.LoadBasePrices(c_bsktDispCtrl.GetDispWeekNum());  // Set the week's starting values

         c_sellPairs.LoadBasePrices(c_bsktDispCtrl.GetDispWeekNum()); // Set the week's starting values

       }

    }

   if( newBar || (prev_calculated<1) || (rates_total<prev_calculated) ){

      if(newWeek){

         c_buyPairs.LoadSpeedBases(1);  // Set the week's starting values

         c_sellPairs.LoadSpeedBases(1); // Set the week's starting values

       }

    }

   //

   EventChartCustom(ChartID(),CHARTEVENT_MAKECHART, uniquifier, NULL, NULL);  // Post an event to refresh the display.

   //

   return rates_total;

}//====== END OnCalculate ==============

bool ThereIsNewWeekBar(void) // Determine if there is a new week starting.

{

   bool result=false;

   static datetime lastBarTime=NULL;

   datetime currBarTime = iTime(_Symbol,PERIOD_W1,NOSHIFT);  // Get the Bar Zero Time

   if(currBarTime != lastBarTime){  // Week Bar has changed

      lastBarTime = currBarTime;

      result=true;

    }

   return result;

}//====== END ThereIsNewWeekBar ======================

bool ThereIsNewChartBar(void) // Determine if there is a new bar starting.

{

   bool result=false;

   static datetime lastBarTime=NULL;

   datetime currBarTime = iTime(_Symbol,PERIOD_CURRENT,NOSHIFT);  // Get the Bar Zero Time

   if(currBarTime != lastBarTime){  // chart Bar 0 has changed

      lastBarTime = currBarTime;

      result=true;

    }

   return result;

}//====== END ThereIsNewWeekBar ======================

//+------------------------------------------------------------------+

//| Indicator Custom Event Action                                    |

//+------------------------------------------------------------------+

void LoadDashboardValuesAndDraw(void)  // Get the current values and draw the dashboard

{

   c_sellPairs.SetBasketATRValues( c_bsktDispCtrl, atr_buf );  // Find the Value of the sell Basket for the week

   c_buyPairs.SetBasketATRValues( c_bsktDispCtrl, atr_buf );  // Find the Value of the buy Basket for the week

   //

   c_sellPairs.SetBasketCurrentPrices(c_bsktDispCtrl);    // Find the Value of the sell Basket for the week

   c_buyPairs.SetBasketCurrentPrices(c_bsktDispCtrl);    // Find the Value of the buy Basket for the week

   //

   c_sellPairs.SetPositionValues();     // Find the Value of the sell orders

   c_buyPairs.SetPositionValues();     // Find the Value of the buy orders

   //

   c_sellPairs.SetCurrentSpeedPrices(); // Get the most recent price

   c_buyPairs.SetCurrentSpeedPrices();  // Get the most recent price

   //

   DrawDisplay(c_sellPairs, c_buyPairs, c_bsktDispCtrl);

   ChartRedraw(ChartID());

}//======== END LoadDashboardValuesAndDraw ===============

//+------------------------------------------------------------------+

//| Draw Display Functions - Set up each label object and draw it    |

//+------------------------------------------------------------------+

void DrawDisplay(C_pairsArys* sell_arys, C_pairsArys* buy_arys, C_bsktCtrl* o_DispCtrl) // Make the display

{

   o_DispCtrl.SetDefaults(o_DispCtrl.GetXOrigins(),o_DispCtrl.GetYOrigins(),11,clrNONE);  // Start Fresh (Line zero)

   //

   DisplayHeaderLine( o_DispCtrl );  // Draw the first line

   //

   DisplayABasket( buy_arys, o_DispCtrl );  // Display a basket

   //

   DisplayABasket( sell_arys, o_DispCtrl );  // Display a Basket

   //

   if(o_DispCtrl.GetIfWeekShouldBeMarked()==ON){  // Highlight a week

      DrawRectangle(o_DispCtrl, WK_MRK_IDX);

    }

   //

}//=== END DrawDisplay ========================

void DisplayHeaderLine(C_bsktCtrl* o_DispCtrl)

{

   // =======  First Line; Draw Title =========

   o_DispCtrl.SetObjName( disp_obj_nms[TITLE_IDX] );  // The Drag object, and the Title display for the indicator

   o_DispCtrl.SetDispString( "Basket Viewer (wk "+IntegerToString(o_DispCtrl.GetDispWeekNum())+"): " );

   o_DispCtrl.SetYDispPos( o_DispCtrl.GetYOrigins()+(o_DispCtrl.GetDispLineNum()*o_DispCtrl.GetYOffSet()) );

   o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins() + o_DispCtrl.GetXDragOffset() );

   o_DispCtrl.SetColor( TitleClr );

   o_DispCtrl.SetSelectable( true );  // Must be true so it can be dragged and dropped

   ManageALabel(o_DispCtrl);

   o_DispCtrl.SetSelectable( false );  // Don't want any other objects to be selectable.

   // --------- Draw Start Week on first line

   o_DispCtrl.SetObjName( disp_obj_nms[STRTWK_IDX] );  // Display the Start of the Week for the Weekly values - this object increments the week # when clicked.

   o_DispCtrl.SetDispString( TimeToString(o_DispCtrl.GetWeekStartTime(),TIME_DATE)+"  - " );

   o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins()+80 );

   o_DispCtrl.SetColor( TitleClr );

   ManageALabel(o_DispCtrl);

   // ------------ Draw End Week on first line

   o_DispCtrl.SetObjName( disp_obj_nms[ENDWK_IDX] );   // Display the End of the Week for the Weekly values - this object decrements the week # when clicked.

   o_DispCtrl.SetDispString( TimeToString(o_DispCtrl.GetWeekEndTime(),TIME_DATE) );

   o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins() );

   o_DispCtrl.SetColor( TitleClr );

   ManageALabel(o_DispCtrl);

}// END DisplayheaderLines =================

void DisplayABasket( C_pairsArys* c_pairs, C_bsktCtrl* o_DispCtrl )

{

   // ======= 2nd Line, Make a Basket Header ============

   o_DispCtrl.IncrementLineNum(1);

   switch (c_pairs.GetSymbolOp()) {

      case SYMB_BUY:

         o_DispCtrl.SetObjName( disp_obj_nms[LONG_HDR_IDX] ); // Display Header for the Long Basket

         break;

      case SYMB_SELL:

         o_DispCtrl.SetObjName( disp_obj_nms[SHORT_HDR_IDX] ); // Display Header for the Short Basket

         break;

      default:

         o_DispCtrl.SetObjName( disp_obj_nms[SHORT_HDR_IDX]+IntegerToString( c_pairs.GetSymbolOp() ) );

         break;

    }

   o_DispCtrl.SetDispString(GetBasketHeaderLine(c_pairs));

   o_DispCtrl.SetYDispPos( o_DispCtrl.GetYOrigins()+(o_DispCtrl.GetDispLineNum()*o_DispCtrl.GetYOffSet()) );

   o_DispCtrl.SetColor( HeadClr );

   ManageALabel(o_DispCtrl);

   // ========= Buy Details; 3rd Line sharts the Basket Display ======

   DisplayPairsValues(o_DispCtrl, c_pairs);

} // ========= END DisplayABasket ===========

string GetBasketHeaderLine(C_pairsArys* c_pairs)

{

   string dispString;

   switch (c_pairs.GetSymbolOp()) {

      case SYMB_BUY:

         if(c_pairs.GetATRSourceSwitchValue()==ON){

            dispString = "BUY BASKET      Points    Term_ATR    Pos_Prft    Pos_Lots";

          }else{ // == OFF

            dispString = "BUY BASKET      Points      Indi_ATR    Pos_Prft    Pos_Lots";

          }

         break;

      case SYMB_SELL:

         if(c_pairs.GetATRSourceSwitchValue()==ON){

            dispString = "SELL BASKET      Points    Term_ATR    Pos_Prft    Pos_Lots";

          }else{ // == OFF

            dispString = "SELL BASKET      Points      Indi_ATR    Pos_Prft    Pos_Lots";

          }

         break;

      default:

         dispString = __FUNCTION__+" called with invalid operration, "+IntegerToString(c_pairs.GetSymbolOp());

         break;

    }

   return dispString;

} // ======= End GetBasketHeaderLin ==============

void DisplayPairsValues(C_bsktCtrl* o_DispCtrl, C_pairsArys* c_pairs)  // Draw a line for each Basket pair

{

   double bsktTtl=0, prftTtl=0, lotsTtl=0, atrTtl=0, positionPoints;  // Hold Basket Totals

   int arySize = c_pairs.GetPairArraySize();

   for(int idx=0; idx<arySize; idx++){ // Increment htrue the basket array, and increment the display line for each row.

      o_DispCtrl.IncrementLineNum(1);  // Increment the line # and start drawing a row

      o_DispCtrl.SetYDispPos( o_DispCtrl.GetYOrigins()+(o_DispCtrl.GetDispLineNum()*o_DispCtrl.GetYOffSet()) );

      //======= Column 1, Display the Pair Strings ================

      DisplayPairString(o_DispCtrl, c_pairs, idx);

      //======= Column 1.5, Display the Pair Speed Arrow ================

      DisplaySpeedArrow(o_DispCtrl, c_pairs, idx);

      //======= Column 2, Display the Pair Movement in Points from the Week Start ================

      DisplayPointsMovement(o_DispCtrl, c_pairs, idx, positionPoints);

      //======= Column 3, Display the Pair's ATR (how significant is the movement?) ================

      DisplayATR(o_DispCtrl,c_pairs,idx);

      //======= Column 4, Display the Profit or loss associated with any trades for each symbol pair ================

      DisplayPositionGainLoss(o_DispCtrl, c_pairs, idx);

      //======= Column 5 (last column, no offset), Display the # of lots exposed in trades fore each symbol pair ================

      DisplayPositionLots(o_DispCtrl,c_pairs, idx);

      //

      // Sum it up for display

      bsktTtl += positionPoints;

      prftTtl += c_pairs.GetSymbolPosVal(idx);

      lotsTtl += c_pairs.GetSymbolLotsVal(idx);

      atrTtl  += c_pairs.GetSymbolATRVal(idx);

    }

   //===== Dispaly a Total Separation Line ===========

   o_DispCtrl.IncrementLineNum(1);

      o_DispCtrl.SetYDispPos( o_DispCtrl.GetYOrigins()+(o_DispCtrl.GetDispLineNum()*o_DispCtrl.GetYOffSet()) );

      o_DispCtrl.SetObjName( disp_obj_nms[SUM_LINE_IDX]+GetOpDescription(c_pairs.GetSymbolOp()) );

      o_DispCtrl.SetDispString( "=================================" );

      o_DispCtrl.SetColor( HeadClr );

      ManageALabel(o_DispCtrl);

   //===== Dispaly the Column Totals, 4 values all on the next line ===========

   o_DispCtrl.IncrementLineNum(1); // Increment the line # and start drawing a row

      // Column 5 totals, no offset, Lots Exposure

      o_DispCtrl.SetObjName( disp_obj_nms[SUMS_IDX]+"LOT_SUM"+GetOpDescription(c_pairs.GetSymbolOp()) );  // Column 5, the position exposure lots total.

      o_DispCtrl.SetYDispPos( o_DispCtrl.GetYOrigins()+(o_DispCtrl.GetDispLineNum()*o_DispCtrl.GetYOffSet()) );

      o_DispCtrl.SetDispString( DoubleToString(lotsTtl,2) );

      o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins() );

      o_DispCtrl.SetColor( TotalClr );

      ManageALabel(o_DispCtrl);

   // collumn 4 Totals, Postion Points Movement

      o_DispCtrl.SetObjName( disp_obj_nms[SUMS_IDX]+"PFT_SUM"+GetOpDescription(c_pairs.GetSymbolOp()) );   // Column 4, the Basket Profit or loss.

      o_DispCtrl.SetDispString( DoubleToString(prftTtl,2) );

      o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins()+o_DispCtrl.GetColumnFourOffset() );

      if(prftTtl>=0.0){  // o_DispCtrl.objClr     = ((prftTtl>=0.0)?ProfitClr:LossClr);

         o_DispCtrl.SetColor( ProfitClr );

       }else o_DispCtrl.SetColor(LossClr );

      ManageALabel(o_DispCtrl);

   // column 3 totals, Sum of ATRS, probably has no value except for display continuity

      o_DispCtrl.SetObjName(  disp_obj_nms[SUMS_IDX]+"ATR_SUM"+GetOpDescription(c_pairs.GetSymbolOp()) );    // Column 3, the Basket's total ATR - Seems like a useless sum.

      o_DispCtrl.SetDispString( IntegerToString( (int) atrTtl) );

      o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins()+o_DispCtrl.GetColumnThreeOffset() );

      o_DispCtrl.SetColor( TotalClr );

      ManageALabel(o_DispCtrl);

   // Column 2 totals, Sum of the Points Movement for the Week.

      o_DispCtrl.SetObjName( disp_obj_nms[SUMS_IDX]+"BSKT_SUM"+GetOpDescription(c_pairs.GetSymbolOp()) );     // Column 2, the Basket's total Points movement for the week

      o_DispCtrl.SetDispString( IntegerToString( (int) bsktTtl) );

      o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins()+o_DispCtrl.GetColumnTwoOffset() );

      if(bsktTtl>=0.0){

         o_DispCtrl.SetColor( ProfitClr );

       }else o_DispCtrl.SetColor( LossClr );

      ManageALabel(o_DispCtrl);

   //

   // Done, return the xPos and yPos to the original position before exiting.

   o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins());

   o_DispCtrl.SetYDispPos( o_DispCtrl.GetYOrigins() );

}//====== END DisplayPairsValues ===========

void DisplayPairString(C_bsktCtrl* o_DispCtrl, C_pairsArys* c_pairs, const int& idx)

{

   o_DispCtrl.SetObjName( GetRowPairObjName( disp_obj_nms[BSKT_ROW_IDX], c_pairs.GetPairSymbol(idx), o_DispCtrl.GetDispLineNum(), c_pairs.GetSymbolOp() ) );

   o_DispCtrl.SetDispString( c_pairs.GetPairSymbol(idx) ); // + ": "+DoubleToStr(c_pairs.baseVal_ary[i],_Digits)+":";

   if(c_pairs.GetSymbolOp()==SYMB_SELL){              // o_DispCtrl.objClr = (c_pairs.symb_op==SYMB_SELL)?SlotsSellClr:SlotsBuyClr;

      o_DispCtrl.SetColor( LotsSellClr );

    }else o_DispCtrl.SetColor( LotsBuyClr );           // c_pairs.symb_op==SYMB_BUY

   o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins()+o_DispCtrl.GetColumnOneOffset() );

   ManageALabel(o_DispCtrl);

}//========= DisplayPairString =============

void DisplaySpeedArrow(C_bsktCtrl* o_DispCtrl, C_pairsArys* c_pairs, const int& idx)

{

   double arrowAngle = c_pairs.GetSpeedAngle(idx);

   o_DispCtrl.SetObjName( disp_obj_nms[BSKT_ROW_IDX]+"ARROW"+IntegerToString(o_DispCtrl.GetDispLineNum())+GetOpDescription(c_pairs.GetSymbolOp()) );

   if( c_pairs.GetSymbolOp()==SYMB_SELL ){

      o_DispCtrl.SetColor((arrowAngle<0)?ProfitClr:LossClr);

    }else{ //c_pairs.symb_op==SYMB_BUY

      o_DispCtrl.SetColor((arrowAngle<0)?LossClr:ProfitClr);

    }

   o_DispCtrl.SetDispString( DoubleToString(arrowAngle,1) );  // Wingding arrow angle

   o_DispCtrl.SetXDispPos( (o_DispCtrl.GetXOrigins()+o_DispCtrl.GetColumnOneOffset())-15);

   ManageAnArrow(o_DispCtrl, arrowAngle);

}

void DisplayPointsMovement(C_bsktCtrl* o_DispCtrl, C_pairsArys* c_pairs, const int& idx, double& positionPoints)

{

   o_DispCtrl.SetObjName( disp_obj_nms[BSKT_ROW_IDX]+IntegerToString(o_DispCtrl.GetDispLineNum())+GetOpDescription(c_pairs.GetSymbolOp())+"PAIRVAL");

   if(c_pairs.GetSymbolOp()==SYMB_SELL){

      positionPoints = ((c_pairs.GetSymbStartVal(idx)-c_pairs.GetSymbolEndVal(idx))/SymbolInfoDouble(c_pairs.GetPairSymbol(idx),SYMBOL_POINT))-SymbolInfoInteger(c_pairs.GetPairSymbol(idx),SYMBOL_SPREAD); // MODE_SPREAD is in Points, and you will always pay the spread

    }else{ //c_pairs.symb_op==SYMB_BUY

      positionPoints = ((c_pairs.GetSymbolEndVal(idx)-c_pairs.GetSymbStartVal(idx))/SymbolInfoDouble(c_pairs.GetPairSymbol(idx),SYMBOL_POINT))+SymbolInfoInteger(c_pairs.GetPairSymbol(idx),SYMBOL_SPREAD); // MODE_SPREAD is in Points, and you will always pay the spread

    }

   o_DispCtrl.SetDispString( IntegerToString((int)positionPoints) );  // Time for the value  +", "+TimeToString(c_pairs.GetWeekTm(idx),TIME_DATE) );

   o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins()+o_DispCtrl.GetColumnTwoOffset());

   if(positionPoints>=0.0){  // o_DispCtrl.objClr     = ((positionVal>=0.0)?ProfitClr:LossClr);

      o_DispCtrl.SetColor(ProfitClr);

    }else o_DispCtrl.SetColor(LossClr);

   ManageALabel(o_DispCtrl);

} // ======== END DisplayPointsMovement ==========

void DisplayATR(C_bsktCtrl* o_DispCtrl, C_pairsArys* c_pairs, const int& idx)

{

   o_DispCtrl.SetObjName( disp_obj_nms[BSKT_ROW_IDX]+IntegerToString(o_DispCtrl.GetDispLineNum())+GetOpDescription(c_pairs.GetSymbolOp())+"PAIRATR");

   o_DispCtrl.SetDispString( IntegerToString((int)c_pairs.GetSymbolATRVal(idx)) );

   o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins()+o_DispCtrl.GetColumnThreeOffset());

   o_DispCtrl.SetColor(TotalClr);

   ManageALabel(o_DispCtrl);

} // ======= END DisplayATR ==================

void DisplayPositionGainLoss(C_bsktCtrl* o_DispCtrl, C_pairsArys* c_pairs, const int& idx)

{

   o_DispCtrl.SetObjName( disp_obj_nms[BSKT_ROW_IDX]+IntegerToString(o_DispCtrl.GetDispLineNum())+GetOpDescription(c_pairs.GetSymbolOp())+"POSVAL" );

   o_DispCtrl.SetDispString( DoubleToString(c_pairs.GetSymbolPosVal(idx),2) );

   o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins()+o_DispCtrl.GetColumnFourOffset() );

   if(c_pairs.GetSymbolPosVal(idx)>=0.0){  // o_DispCtrl.objClr     = ((c_pairs.posVal_ary[i]>=0.0)?ProfitClr:LossClr);

      o_DispCtrl.SetColor(ProfitClr);

    }else o_DispCtrl.SetColor(LossClr);

   ManageALabel(o_DispCtrl);

} // ============= END DisplayPositionGainLoss ===========

void DisplayPositionLots(C_bsktCtrl* o_DispCtrl, C_pairsArys* c_pairs, const int& idx)

{

   o_DispCtrl.SetObjName( disp_obj_nms[BSKT_ROW_IDX]+IntegerToString(o_DispCtrl.GetDispLineNum())+GetOpDescription(c_pairs.GetSymbolOp())+"PLOTS" );

   o_DispCtrl.SetDispString( DoubleToString(c_pairs.GetSymbolLotsVal(idx),2) );

   o_DispCtrl.SetXDispPos( o_DispCtrl.GetXOrigins() );

   o_DispCtrl.SetColor( TotalClr );

   ManageALabel(o_DispCtrl);

} // ========== END DisplayPositionLots ==========

void ManageALabel( C_bsktCtrl*& o_DispCtrl)  // display a Label with paramaters in the structure

{

   static long chartID = ChartID();

   if ( ObjectFind(chartID,o_DispCtrl.GetObjName()) < 0 ) // Create if it's not already there.

    {

      ObjectCreate    (chartID, o_DispCtrl.GetObjName(), OBJ_LABEL, o_DispCtrl.GetWindowNum(),  0, 0);

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_FONTSIZE,  o_DispCtrl.GetFontSize());

      ObjectSetString (chartID, o_DispCtrl.GetObjName(), OBJPROP_FONT,      "Arial");

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_CORNER,    o_DispCtrl.GetBaseCorner());

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_ANCHOR,    o_DispCtrl.GetObjectAnchor());

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_BACK,      true); 

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_SELECTABLE,o_DispCtrl.GetSelectable()); 

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_SELECTED,  false); 

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_HIDDEN,    false);

    }

   ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_COLOR,     o_DispCtrl.GetDispClr());

   ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_XDISTANCE, o_DispCtrl.GetXPos() );

   ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_YDISTANCE, o_DispCtrl.GetYPos() );

   ObjectSetString (chartID, o_DispCtrl.GetObjName(), OBJPROP_TEXT,      o_DispCtrl.GetDispString() );

} // ========= END ManageALabel ==========

void DrawRectangle(C_bsktCtrl* o_DispCtrl, DISP_OBJ_IDX objNameIdx)  // Set parameters for drawing the rectangle

{

   o_DispCtrl.SetObjName(disp_obj_nms[objNameIdx]);

   o_DispCtrl.SetColor(C'154,101,129');

   ManageARectangle(o_DispCtrl);

} // ========= END DrawRectangle ===========

void ManageARectangle(C_bsktCtrl* o_DispCtrl)   // display a rectangle with paramaters in the structure

{

   static long chartID = ChartID();

   double weekHigh = iHigh(_Symbol,PERIOD_W1,o_DispCtrl.GetDispWeekNum() );

   double weekLow  = iLow(_Symbol,PERIOD_W1,o_DispCtrl.GetDispWeekNum() );

   if ( ObjectFind(chartID,o_DispCtrl.GetObjName()) < 0 )

    {

      ObjectCreate    (chartID, o_DispCtrl.GetObjName(), OBJ_RECTANGLE, o_DispCtrl.GetWindowNum(),  o_DispCtrl.GetWeekStartTime(), weekHigh, o_DispCtrl.GetWeekEndTime(), weekLow);

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_STYLE,     STYLE_SOLID);

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_WIDTH,     1);

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_FILL,      true);

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_BACK,      true);

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_COLOR,     o_DispCtrl.GetDispClr());

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_SELECTABLE,o_DispCtrl.GetSelectable()); 

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_SELECTED,  false); 

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_HIDDEN,    false);

    }

   ObjectMove(chartID, o_DispCtrl.GetObjName(), 0, o_DispCtrl.GetWeekStartTime(), weekHigh);

   ObjectMove(chartID, o_DispCtrl.GetObjName(), 1, o_DispCtrl.GetWeekEndTime(),   weekLow);

} // ========= END ManageARectangle ==========

void ManageAnArrow( C_bsktCtrl*& o_DispCtrl, const double arrowAngle = 0)  // display a Label with paramaters in the structure

{

   static long chartID = ChartID();

   if ( ObjectFind(chartID,o_DispCtrl.GetObjName()) < 0 ) // Create if it's not already there.

    {

      ObjectCreate    (chartID, o_DispCtrl.GetObjName(), OBJ_LABEL, o_DispCtrl.GetWindowNum(),  0, 0);

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_FONTSIZE,  o_DispCtrl.GetFontSize());

      ObjectSetString (chartID, o_DispCtrl.GetObjName(), OBJPROP_FONT,      "Wingdings");

      ObjectSetString (chartID, o_DispCtrl.GetObjName(), OBJPROP_TEXT,      "\224" );

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_CORNER,    o_DispCtrl.GetBaseCorner());

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_ANCHOR,    ANCHOR_CENTER);

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_BACK,      true); 

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_SELECTABLE,o_DispCtrl.GetSelectable()); 

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_SELECTED,  false); 

      ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_HIDDEN,    false);

    }

   ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_COLOR,     o_DispCtrl.GetDispClr());

   ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_XDISTANCE, o_DispCtrl.GetXPos() );

   ObjectSetInteger(chartID, o_DispCtrl.GetObjName(), OBJPROP_YDISTANCE, o_DispCtrl.GetYPos()+10 ); // modify to adjust for anchor center.

   ObjectSetDouble (chartID, o_DispCtrl.GetObjName(), OBJPROP_ANGLE,     arrowAngle);

} // ========= END ManageAnArrow ==========

//+------------------------------------------------------------------+

//| End Draw Display Functions                                       |

//+------------------------------------------------------------------+

//+------------------------------------------------------------------+

//| START Helper Functions                                           |

//+------------------------------------------------------------------+

string GetRowPairObjName( const string objNmPrefix, const string pairName, int lineNum, const SYMBOL_OPERATION symb_op )  // constructed to use in OnChartEvent to change chart symbol

{

   string theName = objNmPrefix+pairName+"PAIR"+IntegerToString(lineNum)+GetOpDescription(symb_op);

   return theName;

} // ========= END GetRowPairObjName ====================

//+------------------------------------------------------------------+

//| END Helper Functions                                             |

//+------------------------------------------------------------------+

//

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---