哪位大神知道统计插件怎么显示不全?

| 发表于 2026-2-26 21:52:18 | 显示全部楼层 |复制链接
哪位大神知道统计插件怎么显示不全?

谁知道这是什么原因,怎么看不到完整信息?

谁知道这是什么原因,怎么看不到完整信息?
举报

评论 使用道具

精彩评论5

anby
DD
| 发表于 2026-2-26 22:01:55 | 显示全部楼层
桌面找到MT4或者5图标,右键属性,选择兼容性,选更改高DPI设置,找到底下替代高DPI缩放,选择系统,确定,重启MT4就可以了。
举报

点赞 1 评论 使用道具

z0922638423
DD
| 发表于 2026-2-26 22:26:31 | 显示全部楼层
內容 相容性問題
举报

点赞 评论 使用道具

小钱天天赚
D
 楼主 | 发表于 2026-2-27 03:35:21 | 显示全部楼层
微信图片_20260226215027_26_31.png 修改后是这个样子,还是看不全信息
举报

点赞 评论 使用道具

wdx12345
D
| 发表于 2026-10-14 14:06:43 | 显示全部楼层
字体问题
举报

点赞 评论 使用道具

westwuwei
DDD
| 发表于 2026-10-14 15:33:13 | 显示全部楼层
//+------------------------------------------------------------------+
//|                          DailyTradeStats.mq5                     |
//| 复刻MTCommander日统计,首行持仓汇总,导出CSV,本地持久化存储      |
//| 【无外部mqh依赖,原生图表按钮,直接编译】                          |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026"
#property link      ""
#property version   "1.03"
#property strict

//---- 配置参数
input string PersistFileName = "DailyStatsData.bin"; //持久化数据文件名称
input int    ButtonX = 20;    //导出按钮X坐标
input int    ButtonY = 20;    //导出按钮Y坐标

//---- 单日统计结构体
struct DayStat
{
   datetime dayStart;         //服务器日期零点
   double totalLots;          //当日总手数
   double maxSingleLot;       //当日单笔最大手数
   int    tradeCount;         //当日平仓次数
   double netProfit;          //当日净盈亏
   double depositWithdraw;    //当日出入金
   double endBalance;         //当日收盘账户余额
   double maxFloatLoss;       //当日最大浮亏金额
   double maxFloatLossPct;    //当日最大浮亏比例
   double maxFloatProfit;     //当日最大浮盈金额
   double maxFloatProfitPct;  //当日最大浮盈比例
};

//----全局变量
DayStat g_days[];
int g_dayCount = 0;
datetime g_lastSaveTime = 0;
const string BUTTON_NAME = "BTN_EXPORT_CSV";

//+------------------------------------------------------------------+
//| 初始化                                                           |
//+------------------------------------------------------------------+
int OnInit()
{
   // 创建原生图表按钮(不需要mqh库)
   if(!ObjectCreate(0,BUTTON_NAME,OBJ_BUTTON,0,0,0))
   {
      Print("按钮创建失败,err=",GetLastError());
      return(INIT_FAILED);
   }
   ObjectSetInteger(0,BUTTON_NAME,OBJPROP_XDISTANCE,ButtonX);
   ObjectSetInteger(0,BUTTON_NAME,OBJPROP_YDISTANCE,ButtonY);
   ObjectSetInteger(0,BUTTON_NAME,OBJPROP_XSIZE,140);
   ObjectSetInteger(0,BUTTON_NAME,OBJPROP_YSIZE,30);
   ObjectSetString(0,BUTTON_NAME,OBJPROP_TEXT,"导出CSV报表");
   ObjectSetInteger(0,BUTTON_NAME,OBJPROP_STATE,0); //初始弹起

   //加载本地持久化文件
   LoadDataFromFile();
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 反初始化                                                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   SaveDataToFile();
   ObjectDelete(0,BUTTON_NAME);
}

//+------------------------------------------------------------------+
//| 图表事件:捕获按钮点击                                           |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
   if(id == CHARTEVENT_OBJECT_CLICK && sparam == BUTTON_NAME)
   {
      ExportToCSV();
      Print("✅ CSV报表导出完成,文件路径:"+TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\DailyReport.csv");
      ObjectSetInteger(0,BUTTON_NAME,OBJPROP_STATE,0); //强制弹起
   }
}

//+------------------------------------------------------------------+
//| Tick主循环:实时更新当日浮盈浮亏峰值,自动保存数据                |
//+------------------------------------------------------------------+
void OnTick()
{
   UpdateCurrentDayFloatPeak();
   //每60秒自动持久化一次
   if(TimeCurrent() - g_lastSaveTime > 60)
   {
      SaveDataToFile();
      g_lastSaveTime = TimeCurrent();
   }
}

//====================================================================
// 【持久化 读写本地数据文件】
//====================================================================
bool SaveDataToFile()
{
   int hFile = FileOpen(PersistFileName,FILE_WRITE|FILE_BIN);
   if(hFile == INVALID_HANDLE)
   {
      Print("保存文件失败,err=",GetLastError());
      return false;
   }
   FileWriteInteger(hFile,g_dayCount);
   for(int i=0; i<g_dayCount; i++)
   {
      FileWriteLong(hFile,g_days[i].dayStart);
      FileWriteDouble(hFile,g_days[i].totalLots);
      FileWriteDouble(hFile,g_days[i].maxSingleLot);
      FileWriteInteger(hFile,g_days[i].tradeCount);
      FileWriteDouble(hFile,g_days[i].netProfit);
      FileWriteDouble(hFile,g_days[i].depositWithdraw);
      FileWriteDouble(hFile,g_days[i].endBalance);
      FileWriteDouble(hFile,g_days[i].maxFloatLoss);
      FileWriteDouble(hFile,g_days[i].maxFloatLossPct);
      FileWriteDouble(hFile,g_days[i].maxFloatProfit);
      FileWriteDouble(hFile,g_days[i].maxFloatProfitPct);
   }
   FileClose(hFile);
   return true;
}

bool LoadDataFromFile()
{
   if(!FileIsExist(PersistFileName)) return true;
   int hFile = FileOpen(PersistFileName,FILE_READ|FILE_BIN);
   if(hFile == INVALID_HANDLE)
   {
      Print("读取文件失败");
      return false;
   }
   g_dayCount = FileReadInteger(hFile);
   ArrayResize(g_days,g_dayCount);
   for(int i=0; i<g_dayCount; i++)
   {
      g_days[i].dayStart = (datetime)FileReadLong(hFile);
      g_days[i].totalLots = FileReadDouble(hFile);
      g_days[i].maxSingleLot = FileReadDouble(hFile);
      g_days[i].tradeCount = FileReadInteger(hFile);
      g_days[i].netProfit = FileReadDouble(hFile);
      g_days[i].depositWithdraw = FileReadDouble(hFile);
      g_days[i].endBalance = FileReadDouble(hFile);
      g_days[i].maxFloatLoss = FileReadDouble(hFile);
      g_days[i].maxFloatLossPct = FileReadDouble(hFile);
      g_days[i].maxFloatProfit = FileReadDouble(hFile);
      g_days[i].maxFloatProfitPct = FileReadDouble(hFile);
   }
   FileClose(hFile);
   return true;
}

//====================================================================
// 【辅助函数:获取服务器当日零点时间 替代TimeStartOfDay】
//====================================================================
datetime GetDayStart(datetime t)
{
   MqlDateTime dt;
   TimeToStruct(t,dt);
   dt.hour=0; dt.min=0; dt.sec=0;
   return StructToTime(dt);
}

//====================================================================
// 【实时更新当日持仓浮盈浮亏峰值】
//====================================================================
void UpdateCurrentDayFloatPeak()
{
   datetime today = GetDayStart(TimeCurrent());
   int idx = FindDayIndex(today);
   if(idx == -1)
   {
      //新建当日记录
      AddNewDayRecord(today);
      idx = g_dayCount-1;
   }

   //遍历全部持仓,计算当前总浮盈
   double totalFloat = 0;
   double bal = AccountInfoDouble(ACCOUNT_BALANCE);
   for(int p=0; p<PositionsTotal(); p++)
   {
      ulong posTicket = PositionGetTicket(p);
      if(PositionSelectByTicket(posTicket))
      {
         totalFloat += PositionGetDouble(POSITION_PROFIT);
      }
   }
   double equity = bal + totalFloat;
   double floatPct = (bal>0) ? (equity - bal)/bal *100 : 0;

   //更新最大浮亏 / 浮盈
   if(totalFloat < g_days[idx].maxFloatLoss)
   {
      g_days[idx].maxFloatLoss = totalFloat;
      g_days[idx].maxFloatLossPct = floatPct;
   }
   if(totalFloat > g_days[idx].maxFloatProfit)
   {
      g_days[idx].maxFloatProfit = totalFloat;
      g_days[idx].maxFloatProfitPct = floatPct;
   }
   g_days[idx].endBalance = bal;
}

//====================================================================
// 【历史成交汇总:读取全部已平仓Deal,按服务器日期分组】
//====================================================================
void CalcHistoryDeals()
{
   //重置所有历史交易统计(浮盈峰值保留,因为是实时记录)
   for(int i=0; i<g_dayCount; i++)
   {
      g_days[i].totalLots=0;
      g_days[i].maxSingleLot=0;
      g_days[i].tradeCount=0;
      g_days[i].netProfit=0;
      g_days[i].depositWithdraw=0;
   }

   //读取全部历史成交
   if(!HistorySelect(0,TimeCurrent())) return;
   long dealTotal = HistoryDealsTotal();
   for(long i=0; i<dealTotal; i++)
   {
      //强制转换消除long→uint警告
      ulong ticket = HistoryDealGetTicket((uint)i);
      if(ticket == 0) continue;
      MqlDateTime dtDeal;
      datetime dTime = (datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
      TimeToStruct(dTime,dtDeal);
      datetime day = GetDayStart(dTime);

      long entryType = HistoryDealGetInteger(ticket,DEAL_ENTRY);
      long dealType = HistoryDealGetInteger(ticket,DEAL_TYPE);
      double lot = HistoryDealGetDouble(ticket,DEAL_VOLUME);
      double profit = HistoryDealGetDouble(ticket,DEAL_PROFIT);

      int idx = FindDayIndex(day);
      if(idx == -1)
      {
         AddNewDayRecord(day);
         idx = g_dayCount-1;
      }

      //开仓记录:统计手数,更新单笔最大手数
      if(entryType == DEAL_ENTRY_IN)
      {
         g_days[idx].totalLots += lot;
         if(lot>g_days[idx].maxSingleLot) g_days[idx].maxSingleLot = lot;
      }
      //平仓记录:统计次数 + 净盈亏
      if(entryType == DEAL_ENTRY_OUT)
      {
         g_days[idx].tradeCount++;
         g_days[idx].netProfit += profit;
      }
      //出入金:MQL5用 DEAL_TYPE_BALANCE
      if(dealType == DEAL_TYPE_BALANCE)
      {
         g_days[idx].depositWithdraw += profit;
      }
   }
}

//====================================================================
// 【导出CSV主函数】
//====================================================================
void ExportToCSV()
{
   CalcHistoryDeals(); //每次导出前重新计算历史成交

   int hFile = FileOpen("DailyReport.csv",FILE_WRITE|FILE_CSV|FILE_ANSI);
   if(hFile == INVALID_HANDLE)
   {
      Print("CSV创建失败,err=",GetLastError());
      return;
   }

   //CSV表头
   FileWriteString(hFile,"日期,手数,最大手数,次数,盈亏金额,百分比%,出入金,余额,最大浮亏金额,最大浮亏比例,最大浮盈金额,最大浮盈比例\n");

   //===== 第一行:当前持仓汇总(和截图第一行【持仓】保持一致)=====
   double posTotalLots=0;
   double posMaxLot=0;
   int posCount=0;
   double posFloatTotal=0;
   double bal = AccountInfoDouble(ACCOUNT_BALANCE);
   for(int p=0;p<PositionsTotal();p++)
   {
      ulong t = PositionGetTicket(p);
      if(PositionSelectByTicket(t))
      {
         double l = PositionGetDouble(POSITION_VOLUME);
         posTotalLots += l;
         if(l>posMaxLot) posMaxLot = l;
         posCount++;
         posFloatTotal += PositionGetDouble(POSITION_PROFIT);
      }
   }
   double posPct = bal>0 ? posFloatTotal / bal * 100 : 0;
   FileWriteString(hFile,
      StringFormat("持仓,%.2f,%.2f,%d,%.2f,%.2f%%,%.2f,%.2f,%.2f,%.2f%%,%.2f,%.2f%%\n",
      posTotalLots,posMaxLot,posCount,posFloatTotal,posPct,0.0,bal,posFloatTotal,posPct,0,0));

   //===== 遍历每日历史记录,按时间倒序输出(新日期在前,和截图顺序一致)=====
   for(int i = g_dayCount-1; i>=0; i--)
   {
      DayStat ds = g_days[i];
      if(ds.dayStart == GetDayStart(TimeCurrent())) continue; //当日实时记录跳过
      double pct = ds.endBalance>0 ? ds.netProfit / ds.endBalance *100 :0;
      FileWriteString(hFile,
         StringFormat("%s,%.2f,%.2f,%d,%.2f,%.2f%%,%.2f,%.2f,%.2f,%.2f%%,%.2f,%.2f%%\n",
         TimeToString(ds.dayStart,TIME_DATE),
         ds.totalLots,
         ds.maxSingleLot,
         ds.tradeCount,
         ds.netProfit,
         pct,
         ds.depositWithdraw,
         ds.endBalance,
         ds.maxFloatLoss,
         ds.maxFloatLossPct,
         ds.maxFloatProfit,
         ds.maxFloatProfitPct
         ));
   }
   FileClose(hFile);
}

//====================================================================
// 辅助函数:查找日期索引
//====================================================================
int FindDayIndex(datetime dayTime)
{
   for(int i=0; i<g_dayCount; i++)
   {
      if(g_days[i].dayStart == dayTime) return i;
   }
   return -1;
}

//新增一条日期记录
void AddNewDayRecord(datetime dayTime)
{
   ArrayResize(g_days,g_dayCount+1);
   g_days[g_dayCount].dayStart = dayTime;
   g_days[g_dayCount].totalLots=0;
   g_days[g_dayCount].maxSingleLot=0;
   g_days[g_dayCount].tradeCount=0;
   g_days[g_dayCount].netProfit=0;
   g_days[g_dayCount].depositWithdraw=0;
   g_days[g_dayCount].endBalance=0;
   g_days[g_dayCount].maxFloatLoss=0;
   g_days[g_dayCount].maxFloatLossPct=0;
   g_days[g_dayCount].maxFloatProfit=0;
   g_days[g_dayCount].maxFloatProfitPct=0;
   g_dayCount++;
}
//+------------------------------------------------------------------+
举报

点赞 评论 使用道具

发新帖
EA交易
您需要登录后才可以评论 登录 | 立即注册