//+------------------------------------------------------------------+
//|                                         Basket_Stats_Modern.mq4 |
//|                     Updated for post-600 builds (2025 edition) |
//|       Fully Dynamic Layout with Column Weights                 |
//+------------------------------------------------------------------+
#property copyright "Updated 2025"
#property link      ""
#property version   "2.2"
#property strict
#property indicator_chart_window
#property indicator_buffers 1

//---- user inputs
input string  NonPropFont   = "Lucida Console"; // Font type
input int     BaseFontSize  = 12;              // Base font size
input bool    AutoScaleFont = true;            // Auto-scale font when panel resized
input int     RowSpacing    = 4;               // Extra space between rows
input int     MagicNumber   = 0;               // Magic number filter
input ENUM_BASE_CORNER DisplayCorner = CORNER_LEFT_UPPER; // Corner selection
input int     CornerXOffset = 10;             // Horizontal offset from corner
input int     CornerYOffset = 10;             // Vertical offset from corner
input color   ExtHeaderColor= clrGold;
input color   ExtLineColor  = clrWhite;
input color   ExtProfitColorPos = clrLime;     // Positive profit color
input color   ExtProfitColorNeg = clrRed;      // Negative profit color
input color   PanelBgColor = clrBlack;         // Background panel color
input int     PanelWidth    = 2000;             // Panel width
input int     PanelHeight   = 200;             // Minimum panel height

//---- buffers
double ExtMapBuffer[];

//---- global vars
string shortName;
string almostUniqueIndex;
int    ExtVertShift;
int    ExtVertOffset;
int    maxLineCount = 0;
int    FontSize;

double columnWeights[7] = {1.0, 1.0, 1.0, 1.5, 1.5, 1.0, 1.2}; // weight for each column
int columnX[7];
string ExtCols[7] = {"Symbol", "Type", "Lots", "OpenPrice", "Current", "Pips", "Profit"};

//+------------------------------------------------------------------+
int OnInit()
{
   shortName = "Basket_Stats";
   if (MagicNumber != 0)
      shortName = shortName + " (" + IntegerToString(MagicNumber) + ")";
   IndicatorShortName(shortName);

   SetIndexBuffer(0, ExtMapBuffer);
   SetIndexStyle(0, DRAW_NONE);
   SetIndexEmptyValue(0, 0.0);

   almostUniqueIndex = IntegerToString(TimeCurrent() % 1000) + IntegerToString(MagicNumber);

   CalculateDynamicLayout();
   EventSetTimer(1);
   return INIT_SUCCEEDED;
}

void CalculateDynamicLayout()
{
   double totalWeight = 0;
   for (int i = 0; i < 7; i++) totalWeight += columnWeights[i];

   double currentX = 0;
   for (int i = 0; i < 7; i++)
   {
      columnX[i] = (int)currentX;
      currentX += (PanelWidth * (columnWeights[i] / totalWeight));
   }

   if(AutoScaleFont)
      FontSize = MathMax(8, (int)MathMin(PanelWidth / 60, BaseFontSize * 1.5));
   else
      FontSize = BaseFontSize;

   ExtVertShift = FontSize + RowSpacing + 4;
   ExtVertOffset = CornerYOffset;
}

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   EventKillTimer();
   ObjectsDeleteAll(0, "Header_" + almostUniqueIndex);
   ObjectsDeleteAll(0, "Line_" + almostUniqueIndex);
   ObjectsDeleteAll(0, "Footer_" + almostUniqueIndex);
   if(ObjectFind(0,"BasketPanel_"+almostUniqueIndex)!=-1) ObjectDelete(0,"BasketPanel_"+almostUniqueIndex);
}

//+------------------------------------------------------------------+
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[])
{
   RefreshDisplay();
   return rates_total;
}

void OnTimer()
{
   RefreshDisplay();
}

void RefreshDisplay()
{
   CalculateDynamicLayout();
   maxLineCount = CountOpenTrades();
   DrawBackgroundPanel();
   DrawHeader();
   DrawOpenTrades();
   DrawFooter();
}

int CountOpenTrades()
{
   int count = 0;
   for (int i = 0; i < OrdersTotal(); i++)
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         if (MagicNumber == 0 || OrderMagicNumber() == MagicNumber)
            count++;
   return count;
}

void DrawBackgroundPanel()
{
   string name = "BasketPanel_" + almostUniqueIndex;
   int panelHeight = MathMax(PanelHeight, (maxLineCount + 3) * ExtVertShift + 10);
   if(ObjectFind(0,name)==-1)
      ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
   ObjectSetInteger(0, name, OBJPROP_CORNER, DisplayCorner);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, CornerXOffset - 5);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, CornerYOffset - 5);
   ObjectSetInteger(0, name, OBJPROP_XSIZE, PanelWidth);
   ObjectSetInteger(0, name, OBJPROP_YSIZE, panelHeight);
   ObjectSetInteger(0, name, OBJPROP_BGCOLOR, PanelBgColor);
   ObjectSetInteger(0, name, OBJPROP_COLOR, PanelBgColor);
   ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
   ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
   ObjectSetInteger(0, name, OBJPROP_BACK, true);
   ObjectSetInteger(0, name, OBJPROP_FILL, true);
}

void DrawHeader()
{
   for (int col = 0; col < 7; col++)
   {
      string name = "Header_" + almostUniqueIndex + "_" + IntegerToString(col);
      if (ObjectFind(0, name) == -1)
         ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
      ObjectSetInteger(0, name, OBJPROP_CORNER, DisplayCorner);
      ObjectSetInteger(0, name, OBJPROP_XDISTANCE, CornerXOffset + columnX[col]);
      ObjectSetInteger(0, name, OBJPROP_YDISTANCE, ExtVertOffset);
      ObjectSetString(0, name, OBJPROP_TEXT, ExtCols[col]);
      ObjectSetInteger(0, name, OBJPROP_COLOR, ExtHeaderColor);
      ObjectSetInteger(0, name, OBJPROP_FONTSIZE, FontSize);
      ObjectSetString(0, name, OBJPROP_FONT, NonPropFont);
   }
}

void DrawOpenTrades()
{
   int total = OrdersTotal();
   int line = 0;
   for (int i = 0; i < total; i++)
   {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if (MagicNumber != 0 && OrderMagicNumber() != MagicNumber) continue;
         if (!SymbolSelect(OrderSymbol(), true)) continue;

         string prefix = "Line_" + almostUniqueIndex + "_" + IntegerToString(line);
         DrawCell(prefix + "_sym", 0, line, OrderSymbol(), ExtLineColor);
         DrawCell(prefix + "_type", 1, line, (OrderType() == OP_BUY ? "BUY" : "SELL"), ExtLineColor);
         DrawCell(prefix + "_lots", 2, line, DoubleToString(OrderLots(), 2), ExtLineColor);
         DrawCell(prefix + "_open", 3, line, DoubleToString(OrderOpenPrice(), Digits), ExtLineColor);

         double price = (OrderType() == OP_BUY ? SymbolInfoDouble(OrderSymbol(), SYMBOL_BID)
                                              : SymbolInfoDouble(OrderSymbol(), SYMBOL_ASK));
         DrawCell(prefix + "_cur", 4, line, DoubleToString(price, Digits), ExtLineColor);

         double pips = (OrderType() == OP_BUY ? price - OrderOpenPrice() : OrderOpenPrice() - price) / SymbolInfoDouble(OrderSymbol(), SYMBOL_POINT);
         DrawCell(prefix + "_pips", 5, line, DoubleToString(pips, 1), ExtLineColor);

         color profitColor = (OrderProfit() >= 0) ? ExtProfitColorPos : ExtProfitColorNeg;
         DrawCell(prefix + "_profit", 6, line, DoubleToString(OrderProfit(), 2), profitColor);
         line++;
      }
   }
}

void DrawFooter()
{
   string name = "Footer_" + almostUniqueIndex + "_total";
   double totalProfit = 0.0;
   for (int i = 0; i < OrdersTotal(); i++)
   {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if (MagicNumber != 0 && OrderMagicNumber() != MagicNumber) continue;
         totalProfit += OrderProfit();
      }
   }
   if (ObjectFind(0, name) == -1)
      ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, name, OBJPROP_CORNER, DisplayCorner);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, CornerXOffset + columnX[6]);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, ExtVertShift * (maxLineCount + 1) + ExtVertOffset + 5);
   ObjectSetString(0, name, OBJPROP_TEXT, "TOTAL: " + DoubleToString(totalProfit, 2));
   ObjectSetInteger(0, name, OBJPROP_COLOR, (totalProfit >= 0 ? ExtProfitColorPos : ExtProfitColorNeg));
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, FontSize + 2);
   ObjectSetString(0, name, OBJPROP_FONT, NonPropFont);
}

void DrawCell(string name, int col, int line, string text, color clr)
{
   if (ObjectFind(0, name) == -1)
      ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, name, OBJPROP_CORNER, DisplayCorner);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, CornerXOffset + columnX[col]);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, ExtVertShift * (line + 1) + ExtVertOffset);
   ObjectSetString(0, name, OBJPROP_TEXT, text);
   ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, FontSize);
   ObjectSetString(0, name, OBJPROP_FONT, NonPropFont);
}