//+------------------------------------------------------------------+
//|                                       PositionSizeCalculator.mq4 |
//|                             Copyright © 2012-2015, Andriy Moraru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2012-2015, Andriy Moraru"
#property link      "http://www.earnforex.com"
#property version   "1.15"

#property description "Calculates position size based on account balance/equity,"
#property description "currency, currency pair, given entry level, stop-loss level"
#property description "and risk tolerance (set either in percentage points or in base currency)."
#property description "Can display reward/risk ratio based on take-profit."
#property description "Can also show total portfolio risk based on open trades and pending orders."
#property description "2015-01-30, ver. 1.15 - values read from lines are now rounded. DeleteLines also clears old lines when attaching."
// 2014-12-19, ver. 1.14 - fixed minor bug when restarting MT5; also, lines are no longer hidden from object list."
// 2014-10-03, ver. 1.13 - added portfolio risk calculation."
// 2014-09-17, ver. 1.12 - position size is now rounded down.
// 2014-04-11, ver. 1.11 - added potential reward display and color/style input parameters.
// 2013-11-11, ver. 1.10 - added optional Ask/Bid tracking for Entry line.
// 2013-02-11, ver. 1.8 - completely revamped calculation process.
// 2013-01-14, ver. 1.7 - fixed "division by zero" error.
// 2012-12-10, ver. 1.6 - will use local values if both Entry and SL are missing.
// 2012-11-02, ver. 1.5 - a more intelligent name prefix/postfix detection.
// 2012-10-13, ver. 1.4 - fixed contract size in lot size calculation.
// 2012-10-13, ver. 1.3 - proper lot size calculation for gold, silver and oil.
// 2012-09-29, ver. 1.2 - improved account currency and reference pair detection.
// 2012-05-10, ver. 1.1 - added support for setting risk in money.

#property indicator_chart_window

extern double EntryLevel = 0;
extern double StopLossLevel = 0;
extern double TakeProfitLevel = 0; // Optional
extern double Risk = 4; // Risk tolerance in percentage points
extern double MoneyRisk = 0; // Risk tolerance in account currency
extern bool UseMoneyInsteadOfPercentage = false;
extern bool UseEquityInsteadOfBalance = false;
extern bool DeleteLines = false; // If true, will delete lines on deinitialization. Otherwise will leave lines, so levels can be restored.
extern bool UseAskBidForEntry = true; // If true, Entry level will be updated to current Ask/Bid price automatically.
extern bool ShowPortfolioRisk = false; // If true, current portfolio risk and potential portfolio risk will be shown.
extern bool CountPendingOrders = false; // If true, portfolio risk calculation will also involve pending orders.
extern bool IgnoreOrdersWithoutStopLoss = false; // If true, portfolio risk calculation will skip orders without stop-loss.
extern bool CalculateHedgedRisk = true; // If true, hedged positions and orders will be properly calculated in portfolio risk.

extern color entry_font_color = clrDeepSkyBlue;
extern color sl_font_color = clrCrimson;
extern color tp_font_color = clrGold;
extern color ps_font_color = clrGold;
extern color rp_font_color = clrLightBlue;
extern color balance_font_color = clrLightBlue;
extern color rmm_font_color = clrLightBlue;
extern color pp_font_color = clrLightBlue;
extern color rr_font_color = clrYellow;
extern int font_size = 12;
extern string font_face = "Courier";
extern int corner = 0; //0 - for top-left corner, 1 - top-right, 2 - bottom-left, 3 - bottom-right
extern int distance_x = 10;
extern int distance_y = 15;
extern int rrdistance_x = 10;
extern int rrdistance_y = 15;
extern color entry_line_color = clrGray;
extern color stoploss_line_color = clrCrimson;
extern color takeprofit_line_color = clrGold;
extern ENUM_LINE_STYLE entry_line_style = STYLE_SOLID;
extern ENUM_LINE_STYLE stoploss_line_style = STYLE_DOT;
extern ENUM_LINE_STYLE takeprofit_line_style = STYLE_DOT;
extern int entry_line_width = 1;
extern int stoploss_line_width = 1;
extern int takeprofit_line_width = 1;

string SizeText;
double Size, RiskMoney;
double PositionSize;
double StopLoss;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   if (!DeleteLines)
   {
      if (ObjectFind("EntryLine") > -1)
      {
         EntryLevel = Round(ObjectGet("EntryLine", OBJPROP_PRICE1), _Digits);
         ObjectSet("EntryLine", OBJPROP_STYLE, entry_line_style);
         ObjectSet("EntryLine", OBJPROP_COLOR, entry_line_color);
         ObjectSet("EntryLine", OBJPROP_WIDTH, entry_line_width);
      }
      if (ObjectFind("StopLossLine") > -1)
      {
         StopLossLevel = Round(ObjectGet("StopLossLine", OBJPROP_PRICE1), _Digits);
         ObjectSet("StopLossLine", OBJPROP_STYLE, stoploss_line_style);
         ObjectSet("StopLossLine", OBJPROP_COLOR, stoploss_line_color);
         ObjectSet("StopLossLine", OBJPROP_WIDTH, stoploss_line_width);
      }
      if (ObjectFind("TakeProfitLine") > -1)
      {
         TakeProfitLevel = Round(ObjectGet("TakeProfitLine", OBJPROP_PRICE1), _Digits);
         ObjectSet("TakeProfitLine", OBJPROP_STYLE, takeprofit_line_style);
         ObjectSet("TakeProfitLine", OBJPROP_COLOR, takeprofit_line_color);
         ObjectSet("TakeProfitLine", OBJPROP_WIDTH, takeprofit_line_width);
      }
   }
   else
   {
      ObjectDelete("EntryLine");
      ObjectDelete("StopLossLine");
      ObjectDelete("TakeProfitLine");
   }
   
   if ((EntryLevel == 0) && (StopLossLevel == 0))
   {
      Print(Symbol() + ": Entry and Stop-Loss levels not given. Using local values.");
      EntryLevel = High[0];
      StopLossLevel = Low[0];
      if (EntryLevel == StopLossLevel) StopLossLevel -= Point;
   }
   if (EntryLevel - StopLossLevel == 0)
   {
      Alert("Entry and Stop-Loss levels should be different and non-zero.");
      return(-1);
   }

   if (UseAskBidForEntry)
   {
      RefreshRates();
      if ((Ask > 0) && (Bid > 0))
      {
         // Long entry
         if (StopLossLevel < Bid) EntryLevel = Ask;
         // Short entry
         else if (StopLossLevel > Ask) EntryLevel = Bid;
      }
   }

   ObjectCreate("EntryLevel", OBJ_LABEL, 0, 0, 0);
   ObjectSet("EntryLevel", OBJPROP_CORNER, corner);
   ObjectSet("EntryLevel", OBJPROP_XDISTANCE, distance_x);
   ObjectSet("EntryLevel", OBJPROP_YDISTANCE, distance_y);
   ObjectSetText("EntryLevel", "Entry Lvl:    " + DoubleToStr(EntryLevel, Digits), font_size, font_face, entry_font_color);

   if (ObjectFind("EntryLine") == -1) 
   {
      ObjectCreate("EntryLine", OBJ_HLINE, 0, Time[0], EntryLevel);
      ObjectSet("EntryLine", OBJPROP_STYLE, entry_line_style);
      ObjectSet("EntryLine", OBJPROP_COLOR, entry_line_color);
      ObjectSet("EntryLine", OBJPROP_WIDTH, entry_line_width);
      ObjectSet("EntryLine", OBJPROP_WIDTH, 1);
   }

   ObjectCreate("StopLoss", OBJ_LABEL, 0, 0, 0);
   ObjectSet("StopLoss", OBJPROP_CORNER, corner);
   ObjectSet("StopLoss", OBJPROP_XDISTANCE, distance_x);
   ObjectSet("StopLoss", OBJPROP_YDISTANCE, distance_y + 15);
   ObjectSetText("StopLoss", "Stop-Loss:    " + DoubleToStr(StopLossLevel, Digits), font_size, font_face, sl_font_color);
      
   if (ObjectFind("StopLossLine") == -1)
   {
      ObjectCreate("StopLossLine", OBJ_HLINE, 0, Time[0], StopLossLevel);
      ObjectSet("StopLossLine", OBJPROP_STYLE, stoploss_line_style);
      ObjectSet("StopLossLine", OBJPROP_COLOR, stoploss_line_color);
      ObjectSet("StopLossLine", OBJPROP_WIDTH, stoploss_line_width);
      ObjectSet("StopLossLine", OBJPROP_WIDTH, 1);
   }
   StopLoss = MathAbs(EntryLevel - StopLossLevel);
   
   int y_shift = 30;
   
   if (TakeProfitLevel > 0)  // Show TP line and RR ratio only if TakeProfitLevel input parameter is set by user or found via chart object.
   {
      ObjectCreate("TakeProfit", OBJ_LABEL, 0, 0, 0);
      ObjectSet("TakeProfit", OBJPROP_CORNER, corner);
      ObjectSet("TakeProfit", OBJPROP_XDISTANCE, distance_x);
      ObjectSet("TakeProfit", OBJPROP_YDISTANCE, distance_y + y_shift);
      ObjectSetText("TakeProfit", "Take-Profit:  " + DoubleToStr(TakeProfitLevel, Digits), font_size, font_face, tp_font_color);
      y_shift += 15;

      if (ObjectFind("TakeProfitLine") == -1) 
      {
         ObjectCreate("TakeProfitLine", OBJ_HLINE, 0, Time[0], TakeProfitLevel);
         ObjectSet("TakeProfitLine", OBJPROP_STYLE, takeprofit_line_style);
         ObjectSet("TakeProfitLine", OBJPROP_COLOR, takeprofit_line_color);
         ObjectSet("TakeProfitLine", OBJPROP_WIDTH, takeprofit_line_width);
         ObjectSet("TakeProfitLine", OBJPROP_WIDTH, 1);
      }
   }
   
   if (UseEquityInsteadOfBalance)
   {
      SizeText = "Equity";
      Size = AccountEquity();
   }
   else
   {
      SizeText = "Balance";
      Size = AccountBalance();
   }
   ObjectCreate("AccountSize", OBJ_LABEL, 0, 0, 0);
   ObjectSet("AccountSize", OBJPROP_CORNER, corner);
   ObjectSet("AccountSize", OBJPROP_XDISTANCE, distance_x);
   ObjectSet("AccountSize", OBJPROP_YDISTANCE, distance_y + y_shift);
   ObjectSetText("AccountSize", "Acc. " + SizeText + ": " + DoubleToStr(Size, 2), font_size, font_face, balance_font_color);
   y_shift += 15;
   
   if (!UseMoneyInsteadOfPercentage)
   {
      ObjectCreate("Risk", OBJ_LABEL, 0, 0, 0);
      ObjectSet("Risk", OBJPROP_CORNER, corner);
      ObjectSet("Risk", OBJPROP_XDISTANCE, distance_x);
      ObjectSet("Risk", OBJPROP_YDISTANCE, distance_y + y_shift);
      ObjectSetText("Risk", "Risk:         " + DoubleToStr(Risk, 2) + "%", font_size, font_face, rp_font_color);
      y_shift += 15;
   }
   
   ObjectCreate("RiskMoney", OBJ_LABEL, 0, 0, 0);
   ObjectSet("RiskMoney", OBJPROP_CORNER, corner);
   ObjectSet("RiskMoney", OBJPROP_XDISTANCE, distance_x);
   ObjectSet("RiskMoney", OBJPROP_YDISTANCE, distance_y + y_shift);
   y_shift += 15;

   if (TakeProfitLevel > 0)
   {
      ObjectCreate("PotentialProfit", OBJ_LABEL, 0, 0, 0);
      ObjectSet("PotentialProfit", OBJPROP_CORNER, corner);
      ObjectSet("PotentialProfit", OBJPROP_XDISTANCE, distance_x);
      ObjectSet("PotentialProfit", OBJPROP_YDISTANCE, distance_y + y_shift);
      y_shift += 15;

      ObjectCreate("RR", OBJ_LABEL, 0, 0, 0);
      ObjectSet("RR", OBJPROP_CORNER, corner);
      ObjectSet("RR", OBJPROP_XDISTANCE, rrdistance_x);
      ObjectSet("RR", OBJPROP_YDISTANCE, rrdistance_y + y_shift);
      ObjectSetText("RR", "Reward/Risk:  " + DoubleToStr(MathAbs((TakeProfitLevel - EntryLevel) / (EntryLevel - TakeProfitLevel)), 1), font_size, font_face, rr_font_color);
      y_shift += 15;
   }

   ObjectCreate("PositionSize", OBJ_LABEL, 0, 0, 0);
   ObjectSet("PositionSize", OBJPROP_CORNER, corner);
   ObjectSet("PositionSize", OBJPROP_XDISTANCE, distance_x);
   ObjectSet("PositionSize", OBJPROP_YDISTANCE, distance_y + y_shift);
   y_shift += 15;
   
   if (ShowPortfolioRisk)
   {
      y_shift += 15; // One blank line.
      
      ObjectCreate("CurrentPortfolioMoneyRisk", OBJ_LABEL, 0, 0, 0);
      ObjectSet("CurrentPortfolioMoneyRisk", OBJPROP_CORNER, corner);
      ObjectSet("CurrentPortfolioMoneyRisk", OBJPROP_XDISTANCE, distance_x);
      ObjectSet("CurrentPortfolioMoneyRisk", OBJPROP_YDISTANCE, distance_y + y_shift);
      ObjectSetText("CurrentPortfolioMoneyRisk", "", font_size, font_face, rmm_font_color);
      y_shift += 15;

      ObjectCreate("CurrentPortfolioRisk", OBJ_LABEL, 0, 0, 0);
      ObjectSet("CurrentPortfolioRisk", OBJPROP_CORNER, corner);
      ObjectSet("CurrentPortfolioRisk", OBJPROP_XDISTANCE, distance_x);
      ObjectSet("CurrentPortfolioRisk", OBJPROP_YDISTANCE, distance_y + y_shift);
      ObjectSetText("CurrentPortfolioRisk", "", font_size, font_face, rmm_font_color);
      y_shift += 15;

      ObjectCreate("PotentialPortfolioMoneyRisk", OBJ_LABEL, 0, 0, 0);
      ObjectSet("PotentialPortfolioMoneyRisk", OBJPROP_CORNER, corner);
      ObjectSet("PotentialPortfolioMoneyRisk", OBJPROP_XDISTANCE, distance_x);
      ObjectSet("PotentialPortfolioMoneyRisk", OBJPROP_YDISTANCE, distance_y + y_shift);
      ObjectSetText("PotentialPortfolioMoneyRisk", "", font_size, font_face, rmm_font_color);
      y_shift += 15;
    
      ObjectCreate("PotentialPortfolioRisk", OBJ_LABEL, 0, 0, 0);
      ObjectSet("PotentialPortfolioRisk", OBJPROP_CORNER, corner);
      ObjectSet("PotentialPortfolioRisk", OBJPROP_XDISTANCE, distance_x);
      ObjectSet("PotentialPortfolioRisk", OBJPROP_YDISTANCE, distance_y + y_shift);
      ObjectSetText("PotentialPortfolioRisk", "", font_size, font_face, rmm_font_color);
   }

   CalculateRiskAndPositionSize();

   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   ObjectDelete("EntryLevel");
   if (DeleteLines) ObjectDelete("EntryLine");
   ObjectDelete("StopLoss");
   if (DeleteLines) ObjectDelete("StopLossLine");
   if (!UseMoneyInsteadOfPercentage) ObjectDelete("Risk"); // Otherwise wasn't created.
   ObjectDelete("AccountSize");
   ObjectDelete("RiskMoney");
   ObjectDelete("PositionSize");
   if (TakeProfitLevel > 0)
   {
      ObjectDelete("TakeProfit");
      if (DeleteLines) ObjectDelete("TakeProfitLine");
      ObjectDelete("RR");
      ObjectDelete("PotentialProfit");
   }
   if (ShowPortfolioRisk)
   {
      ObjectDelete("CurrentPortfolioMoneyRisk");
      ObjectDelete("CurrentPortfolioRisk");
      ObjectDelete("PotentialPortfolioMoneyRisk");
      ObjectDelete("PotentialPortfolioRisk");
   }
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   RecalculatePositionSize();
   return(0);
}

//+------------------------------------------------------------------+
//| Object dragging handler                                          |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // Event ID
                  const long& lparam,   // Parameter of type long event
                  const double& dparam, // Parameter of type double event
                  const string& sparam  // Parameter of type string events
)
{
   if (id != CHARTEVENT_OBJECT_DRAG) return;
   if ((sparam != "EntryLine") && (sparam != "StopLossLine") && (sparam != "TakeProfitLine")) return;
   RecalculatePositionSize();
   ChartRedraw();   
}

//+------------------------------------------------------------------+
//| Trade event handler                                              |
//+------------------------------------------------------------------+
void OnTrade()
{
   RecalculatePositionSize();
}

//+------------------------------------------------------------------+
//| Main recalculation function used on every tick and on entry/SL   |
//| line drag                                                        |
//+------------------------------------------------------------------+
void RecalculatePositionSize()
{
   double tEntryLevel, tStopLossLevel, tTakeProfitLevel;
   // Update Entry to Ask/Bid if needed.
   if (UseAskBidForEntry)
   {
      RefreshRates();
      if ((Ask > 0) && (Bid > 0))
      {
         tStopLossLevel = Round(ObjectGet("StopLossLine", OBJPROP_PRICE1), _Digits);
         // Long entry
         if (tStopLossLevel < Bid) tEntryLevel = Ask;
         // Short entry
         else if (tStopLossLevel > Ask) tEntryLevel = Bid;
         ObjectSet("EntryLine", OBJPROP_PRICE1, tEntryLevel);
      }
   }
   
   if (EntryLevel - StopLossLevel == 0) return;

   // If could not find account currency, probably not connected.
   if (AccountCurrency() == "") return;

   tEntryLevel = Round(ObjectGet("EntryLine", OBJPROP_PRICE1), _Digits);
   tStopLossLevel = Round(ObjectGet("StopLossLine", OBJPROP_PRICE1), _Digits);
   tTakeProfitLevel = Round(ObjectGet("TakeProfitLine", OBJPROP_PRICE1), _Digits);
   ObjectSetText("EntryLevel", "Entry Lvl:    " + DoubleToStr(tEntryLevel, Digits), font_size, font_face, entry_font_color);
   ObjectSetText("StopLoss", "Stop-Loss:    " + DoubleToStr(tStopLossLevel, Digits), font_size, font_face, sl_font_color);
   if (tTakeProfitLevel > 0) ObjectSetText("TakeProfit", "Take-Profit:  " + DoubleToStr(tTakeProfitLevel, Digits), font_size, font_face, tp_font_color);

   StopLoss = MathAbs(tEntryLevel - tStopLossLevel);

   if (tTakeProfitLevel > 0)
   {
      string RR;
      // Have valid take-profit level that is above entry for SL below entry, or below entry for SL above entry.
      if (((tTakeProfitLevel > tEntryLevel) && (tEntryLevel > tStopLossLevel)) || ((tTakeProfitLevel < tEntryLevel) && (tEntryLevel < tStopLossLevel)))
         RR = DoubleToStr(MathAbs((tTakeProfitLevel - tEntryLevel) / StopLoss), 1);
      else RR = "Invalid TP.";
      ObjectSetText("RR", "Reward/Risk:  " + RR, font_size, font_face, rr_font_color);
      ObjectSetText("PotentialProfit", "Reward:       " + DoubleToStr(RiskMoney * MathAbs((tTakeProfitLevel - tEntryLevel) / StopLoss), 2), font_size, font_face, pp_font_color);
   }
   
   if (UseEquityInsteadOfBalance) Size = AccountEquity();
   else Size = AccountBalance();
   ObjectSetText("AccountSize", "Acc. " + SizeText + ": " + DoubleToStr(Size, 2), font_size, font_face, balance_font_color);

   CalculateRiskAndPositionSize();
}

//+------------------------------------------------------------------+
//| Calculates risk size and position size. Sets object values.      |
//+------------------------------------------------------------------+
void CalculateRiskAndPositionSize()
{
   if (!UseMoneyInsteadOfPercentage) RiskMoney = Size * Risk / 100;
   else RiskMoney = MoneyRisk;
   ObjectSetText("RiskMoney", "Risk, money:  " + DoubleToStr(RiskMoney, 2), font_size, font_face, rmm_font_color);

   double UnitCost = MarketInfo(Symbol(), MODE_TICKVALUE);
   double TickSize = MarketInfo(Symbol(), MODE_TICKSIZE);
   if ((StopLoss != 0) && (UnitCost != 0) && (TickSize != 0)) PositionSize = RiskMoney / (StopLoss * UnitCost / TickSize);
   
   ObjectSetText("PositionSize", "Pos. Size:    " + DoubleToStr(RoundDown(PositionSize, 2), 2), font_size + 1, font_face, ps_font_color);

   if (ShowPortfolioRisk) CalculatePortfolioRisk();
}

//+------------------------------------------------------------------+
//| Round down a double value to a given decimal place.              |
//+------------------------------------------------------------------+
double RoundDown(double value, double digits)
{
   int norm = MathPow(10, digits);
   return(MathFloor(value * norm) / norm);
}

//+------------------------------------------------------------------+
//| Round a double value to a given decimal place.                   |
//+------------------------------------------------------------------+
double Round(double value, double digits)
{
   int norm = MathPow(10, digits);
   return(MathRound(value * norm) / norm);
}

//+------------------------------------------------------------------+
//| Calculates risk size and position size. Sets object values.      |
//+------------------------------------------------------------------+
void CalculatePortfolioRisk()
{
   double PortfolioLossMoney = 0;
   int total = OrdersTotal();
   for (int i = 0; i < total; i++)
   {
      double PipsLoss = 0;
      // Select an order.
      if (!OrderSelect(i, SELECT_BY_POS)) continue;
      // No stop-loss.
      if (OrderStopLoss() == 0)
      {
         if (IgnoreOrdersWithoutStopLoss) continue;
         // Buy orders
         if (OrderType() == ORDER_TYPE_BUY)
         {
            // Losing all the current value
            PipsLoss = OrderOpenPrice();
         }
         // Sell orders
         else if (OrderType() == ORDER_TYPE_SELL)
         {
            // Potential loss is infinite
            PipsLoss = DBL_MAX;
         }
         else if (CountPendingOrders)
         {
            // Buy orders
            if ((OrderType() == ORDER_TYPE_BUY_LIMIT) || (OrderType() == ORDER_TYPE_BUY_STOP))
            {
               // Losing all the current value
               PipsLoss = OrderOpenPrice();
            }
            // Sell orders
            else if ((OrderType() == ORDER_TYPE_SELL_LIMIT) || (OrderType() == ORDER_TYPE_SELL_STOP))
            {
               // Potential loss is infinite
               PipsLoss = DBL_MAX;
            }
         }
      }
      else
      // Some sotp-loss
      {
         // Buy orders
         if (OrderType() == ORDER_TYPE_BUY)
         {
            // Stop-loss below open price.
            PipsLoss = OrderOpenPrice() - OrderStopLoss();
         }
         // Sell orders
         else if (OrderType() == ORDER_TYPE_SELL)
         {
            // Stop-loss above open price.
            PipsLoss = OrderStopLoss() - OrderOpenPrice();
         }
         else if (CountPendingOrders)
         {
            // Buy orders
            if ((OrderType() == ORDER_TYPE_BUY_LIMIT) || (OrderType() == ORDER_TYPE_BUY_STOP))
            {
               // Stop-loss below open price.
               PipsLoss = OrderOpenPrice() - OrderStopLoss();
            }
            // Sell orders
            else if ((OrderType() == ORDER_TYPE_SELL_LIMIT) || (OrderType() == ORDER_TYPE_SELL_STOP))
            {
               // Stop-loss above open price.
               PipsLoss = OrderStopLoss() - OrderOpenPrice();
            }
         }
      }
      
      if (PipsLoss != DBL_MAX)
      {
         double UnitCost = MarketInfo(OrderSymbol(), MODE_TICKVALUE);
         double TickSize = MarketInfo(OrderSymbol(), MODE_TICKSIZE);
         PortfolioLossMoney += OrderLots() * PipsLoss * UnitCost / TickSize;
      }
      else
      // Infinite loss
      {
         PortfolioLossMoney = DBL_MAX;
         break;
      }
   }
   
   // If account size did not load yet.
   if (Size == 0) return;
   
   string PLM;
   if (PortfolioLossMoney == DBL_MAX) PLM = "Infinity";
   else PLM = DoubleToString(PortfolioLossMoney, 2);
   ObjectSetText("CurrentPortfolioMoneyRisk", "Current Portfolio Money Risk:   " + PLM, font_size + 1, font_face, rmm_font_color);
   string CPR;
   if (PortfolioLossMoney == DBL_MAX) CPR = "Infinity";
   else CPR = DoubleToString(PortfolioLossMoney / Size * 100, 2);
   ObjectSetText("CurrentPortfolioRisk", "Current Portfolio Risk, %:      " + CPR, font_size + 1, font_face, rp_font_color);

   string PPMR;
   if (PortfolioLossMoney == DBL_MAX) PPMR = "Infinity";
   else PPMR = DoubleToString(PortfolioLossMoney + RiskMoney, 2);
   ObjectSetText("PotentialPortfolioMoneyRisk", "Potential Portfolio Money Risk: " + PPMR, font_size + 1, font_face, rmm_font_color);
   string PPR;
   if (PortfolioLossMoney == DBL_MAX) PPR = "Infinity";
   else PPR = DoubleToString((PortfolioLossMoney + RiskMoney) / Size * 100, 2);
   ObjectSetText("PotentialPortfolioRisk", "Potential Portfolio Risk, %:    " + PPR, font_size + 1, font_face, rp_font_color);
}
//+------------------------------------------------------------------+