2026-03-23 15:33:27 +07:00
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 15:25:14 +07:00
|
|
|
//| Article-16233-MQL5-SQLite-Trade-Statistics-Panel.mq5 |
|
|
|
|
|
//| Copyright 2026, MetaQuotes Ltd. |
|
|
|
|
|
//| https://www.mql5.com |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 15:33:27 +07:00
|
|
|
#property indicator_buffers 0
|
|
|
|
|
#property indicator_plots 0
|
|
|
|
|
|
|
|
|
|
#include "Dashboard\Dashboard.mqh"
|
|
|
|
|
#include "SQLiteFunc.mqh"
|
|
|
|
|
|
|
|
|
|
#define PROGRAM_NAME (MQLInfoString(MQL_PROGRAM_NAME)) // Имя программы
|
|
|
|
|
#define DB_NAME (PROGRAM_NAME+"_DB.sqlite") // Имя базы данных
|
|
|
|
|
#define DATE_FROM 0 // Дата начала истории сделок
|
|
|
|
|
#define DATE_TO (TimeCurrent()) // Дата окончания истории сделок
|
|
|
|
|
|
|
|
|
|
//--- Ширина ячеек таблиц
|
|
|
|
|
#define CELL_W_TRADES 94 // Ширина ячеек таблицы истории торговли
|
|
|
|
|
#define CELL_W_SYMBOLS 62 // Ширина ячеек таблицы символов, используемых в торговле
|
|
|
|
|
#define CELL_W_MAGICS 62 // Ширина ячеек таблицы магиков, используемых в торговле
|
|
|
|
|
#define CELL_H 16 // Высота ячейки таблицы
|
|
|
|
|
//--- Размеры итоговой таблицы статистики
|
|
|
|
|
#define TABLE_STAT_ROWS 9 // Количество строк итоговой таблицы статистики
|
|
|
|
|
#define TABLE_STAT_COLS 4 // Количество столбцов итоговой таблицы статистики
|
|
|
|
|
//--- Таблицы
|
|
|
|
|
#define TABLE_TRADES 1 // Идентификатор таблицы истории торговли
|
|
|
|
|
#define TABLE_SYMBOLS 2 // Идентификатор таблицы символов, используемых в торговле
|
|
|
|
|
#define TABLE_MAGICS 3 // Идентификатор таблицы магиков, используемых в торговле
|
|
|
|
|
#define TABLE_ACCOUNT 4 // Идентификатор таблицы статистики счёта
|
|
|
|
|
#define TABLE_STATS 5 // Идентификатор итоговой таблицы статистики выбранного символа или магика
|
|
|
|
|
|
|
|
|
|
//--- Заголовки таблиц (полный/сокращённый)
|
|
|
|
|
#define H_TRADES "Trades"
|
|
|
|
|
#define H_TRADES_S "Trades"
|
|
|
|
|
|
|
|
|
|
#define H_LONG "Long"
|
|
|
|
|
#define H_LONG_S "Long"
|
|
|
|
|
|
|
|
|
|
#define H_SHORT "Short"
|
|
|
|
|
#define H_SHORT_S "Short"
|
|
|
|
|
|
|
|
|
|
#define H_GROSS_PROFIT "Gross Profit"
|
|
|
|
|
#define H_GROSS_PROFIT_S "Gross Profit"
|
|
|
|
|
|
|
|
|
|
#define H_GROSS_LOSS "Gross Loss"
|
|
|
|
|
#define H_GROSS_LOSS_S "Gross Loss"
|
|
|
|
|
|
|
|
|
|
#define H_COMMISSIONS "Commission total"
|
|
|
|
|
#define H_COMMISSIONS_S "Fees"
|
|
|
|
|
|
|
|
|
|
#define H_SWAPS "Swap total"
|
|
|
|
|
#define H_SWAPS_S "Swaps"
|
|
|
|
|
|
|
|
|
|
#define H_PROFITS "Profit Loss"
|
|
|
|
|
#define H_PROFITS_S "P/L"
|
|
|
|
|
|
|
|
|
|
#define H_NET_PROFIT "Net Profit"
|
|
|
|
|
#define H_NET_PROFIT_S "Net Profit"
|
|
|
|
|
|
|
|
|
|
#define H_WINS "Win trades"
|
|
|
|
|
#define H_WINS_S "Win"
|
|
|
|
|
|
|
|
|
|
#define H_LOST "Loss trades"
|
|
|
|
|
#define H_LOST_S "Lost"
|
|
|
|
|
|
|
|
|
|
#define H_EXP_PAYOFF "Expected Payoff"
|
|
|
|
|
#define H_EXP_PAYOFF_S "Avg $"
|
|
|
|
|
|
|
|
|
|
#define H_WIN_PRC "Win percent"
|
|
|
|
|
#define H_WIN_PRC_S "Win %"
|
|
|
|
|
|
|
|
|
|
#define H_LOSS_PRC "Loss percent"
|
|
|
|
|
#define H_LOSS_PRC_S "Loss %"
|
|
|
|
|
|
|
|
|
|
#define H_AVG_PROFIT "Average Profit"
|
|
|
|
|
#define H_AVG_PROFIT_S "Avg Profit"
|
|
|
|
|
|
|
|
|
|
#define H_AVG_LOSS "Average Loss"
|
|
|
|
|
#define H_AVG_LOSS_S "Avg Loss"
|
|
|
|
|
|
|
|
|
|
#define H_PRF_FACTOR "Profit factor"
|
|
|
|
|
#define H_PRF_FACTOR_S "PF"
|
|
|
|
|
|
|
|
|
|
//--- Массив расположения столбцов таблиц статистики слева-направо
|
|
|
|
|
string ArrayDataName[18]=
|
|
|
|
|
{
|
|
|
|
|
"HEADER",
|
|
|
|
|
H_NET_PROFIT_S,
|
|
|
|
|
H_TRADES_S,
|
|
|
|
|
H_GROSS_PROFIT_S,
|
|
|
|
|
H_GROSS_LOSS_S,
|
|
|
|
|
H_COMMISSIONS_S,
|
|
|
|
|
H_SWAPS_S,
|
|
|
|
|
H_PROFITS_S,
|
|
|
|
|
H_LONG_S,
|
|
|
|
|
H_SHORT_S,
|
|
|
|
|
H_WINS_S,
|
|
|
|
|
H_LOST_S,
|
|
|
|
|
H_EXP_PAYOFF_S,
|
|
|
|
|
H_WIN_PRC_S,
|
|
|
|
|
H_LOSS_PRC_S,
|
|
|
|
|
H_AVG_PROFIT_S,
|
|
|
|
|
H_AVG_LOSS_S,
|
|
|
|
|
H_PRF_FACTOR_S,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//--- input parameters
|
|
|
|
|
input int InpPanelX = 20; /* Dashboard X */ // Координата X панели
|
|
|
|
|
input int InpPanelY = 20; /* Dashboard Y */ // Координата Y панели
|
|
|
|
|
input int InpUniqID = 0; /* Unique ID */ // Уникальный идентификатор для объекта-панели
|
|
|
|
|
|
|
|
|
|
//--- global variables
|
|
|
|
|
int DBHandle; // Хэндл базы данных
|
|
|
|
|
int LPanelTable; // Активная панель в левом поле
|
|
|
|
|
int RPanelTable; // Активная панель в правом поле
|
|
|
|
|
long ArrayMagics[]; // Массив магиков
|
|
|
|
|
string ArraySymbols[]; // Массив символов
|
|
|
|
|
STrade ArrayTrades[]; // Массив трейдов
|
|
|
|
|
SSymbolStats ArraySymbolStats[]; // Массив статистики по символам
|
|
|
|
|
SMagicStats ArrayMagicStats[]; // Массив статистики по магикам
|
|
|
|
|
SAccountStats ArrayAccountStats[]; // Массив статистики по счёту
|
|
|
|
|
CDashboard *dashboard=NULL; // Указатель на экземпляр панели
|
2026-03-23 15:25:14 +07:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Custom indicator initialization function |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int OnInit()
|
|
|
|
|
{
|
2026-03-23 15:33:27 +07:00
|
|
|
//--- Проверим, что на счете используется хеджинг для учета открытых позиций
|
|
|
|
|
if((ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE)!=ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
|
|
|
|
|
{
|
|
|
|
|
//--- Если счёт неттинговый, то мы не можем преобразовать сделки в трейды простым способом через транзакции, поэтому завершаем работу
|
|
|
|
|
Print("For a Netting account, there is no way to convert deals into trades in a simple way.");
|
|
|
|
|
return INIT_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Указываем путь расположения и создаём БД (\MQL5\Files\StatisticsBy\Database\)
|
|
|
|
|
string path=PROGRAM_NAME+"\\Database\\";
|
|
|
|
|
DBHandle=DatabaseOpen(path+DB_NAME,DATABASE_OPEN_CREATE);
|
|
|
|
|
if(DBHandle==INVALID_HANDLE)
|
|
|
|
|
{
|
|
|
|
|
Print("DatabaseOpen() failed. Error ", GetLastError());
|
|
|
|
|
return(INIT_FAILED);
|
|
|
|
|
}
|
|
|
|
|
PrintFormat("Database \"%s\" successfully created at MQL5\\Files\\%s", DB_NAME, path);
|
2026-03-23 15:25:14 +07:00
|
|
|
|
2026-03-23 15:33:27 +07:00
|
|
|
//--- Создаём панель-окно программы
|
|
|
|
|
dashboard = new CDashboard(InpUniqID, InpPanelX, InpPanelY, 601, 300);
|
|
|
|
|
if(dashboard==NULL)
|
|
|
|
|
{
|
|
|
|
|
Print("Error. Failed to create dashboard object");
|
|
|
|
|
return INIT_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Отображаем панель с текстом названия программы в заголовке окна
|
|
|
|
|
dashboard.SetFontParams("Calibri",8);
|
|
|
|
|
dashboard.SetName("Main");
|
|
|
|
|
dashboard.View(PROGRAM_NAME);
|
|
|
|
|
|
|
|
|
|
//--- Рисуем рабочее пространство
|
|
|
|
|
//--- Кнопка для выбора символов
|
|
|
|
|
CDashboard *panel1=dashboard.InsertNewPanel(dashboard.ID()+1, 3, 20, 49, 21);
|
|
|
|
|
if(panel1!=NULL)
|
|
|
|
|
{
|
|
|
|
|
panel1.SetName("SymbolButton");
|
|
|
|
|
panel1.SetButtonCloseOff();
|
|
|
|
|
panel1.SetButtonMinimizeOff();
|
|
|
|
|
panel1.SetButtonPinOff();
|
|
|
|
|
panel1.View("");
|
|
|
|
|
panel1.Collapse();
|
|
|
|
|
panel1.SetHeaderNewParams("Symbol",clrLightGray,clrBlack,USHORT_MAX,5,-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Кнопка для выбора магиков
|
|
|
|
|
CDashboard *panel2=dashboard.InsertNewPanel(dashboard.ID()+2, 54, 20, 48, 21);
|
|
|
|
|
if(panel2!=NULL)
|
|
|
|
|
{
|
|
|
|
|
panel2.SetName("MagicButton");
|
|
|
|
|
panel2.SetButtonCloseOff();
|
|
|
|
|
panel2.SetButtonMinimizeOff();
|
|
|
|
|
panel2.SetButtonPinOff();
|
|
|
|
|
panel2.View("");
|
|
|
|
|
panel2.Collapse();
|
|
|
|
|
panel2.SetHeaderNewParams("Magic",clrLightGray,clrBlack,USHORT_MAX,8,-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Кнопка для создания списка трейдов
|
|
|
|
|
CDashboard *panel3=dashboard.InsertNewPanel(dashboard.ID()+3, 105, 20, 106, 21);
|
|
|
|
|
if(panel3!=NULL)
|
|
|
|
|
{
|
|
|
|
|
panel3.SetName("TradesButton");
|
|
|
|
|
panel3.SetButtonCloseOff();
|
|
|
|
|
panel3.SetButtonMinimizeOff();
|
|
|
|
|
panel3.SetButtonPinOff();
|
|
|
|
|
panel3.View("");
|
|
|
|
|
panel3.Collapse();
|
|
|
|
|
panel3.SetHeaderNewParams("Get trade history",clrLightGray,clrBlack,USHORT_MAX,10,-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Панель слева для вывода таблицы символов/магиков
|
|
|
|
|
CDashboard *panel4=dashboard.InsertNewPanel(dashboard.ID()+4, 2, 38, 101, dashboard.Height()-38-2);
|
|
|
|
|
if(panel4!=NULL)
|
|
|
|
|
{
|
|
|
|
|
panel4.SetName("FieldL");
|
|
|
|
|
panel4.SetButtonCloseOff();
|
|
|
|
|
panel4.SetButtonMinimizeOff();
|
|
|
|
|
panel4.SetButtonPinOff();
|
|
|
|
|
panel4.View("");
|
|
|
|
|
panel4.SetPanelHeaderOff(true);
|
|
|
|
|
panel4.SetFontParams("Calibri",8);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Панель справа для вывода заголовков статистики по списку трейдов и выбранному символу/магику
|
|
|
|
|
CDashboard *panel5=dashboard.InsertNewPanel(dashboard.ID()+5, 104, 38, dashboard.Width()-104-2, 20);
|
|
|
|
|
if(panel5!=NULL)
|
|
|
|
|
{
|
|
|
|
|
panel5.SetName("FieldH");
|
|
|
|
|
panel5.SetButtonCloseOff();
|
|
|
|
|
panel5.SetButtonMinimizeOff();
|
|
|
|
|
panel5.SetButtonPinOff();
|
|
|
|
|
panel5.View("");
|
|
|
|
|
panel5.SetPanelHeaderOff(true);
|
|
|
|
|
panel5.SetFontParams("Calibri",8,FW_EXTRABOLD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Панель справа для вывода статистики по списку трейдов и выбранному символу/магику
|
|
|
|
|
CDashboard *panel6=dashboard.InsertNewPanel(dashboard.ID()+6, 104, 38+20, dashboard.Width()-104-2, dashboard.Height()-38-20-2);
|
|
|
|
|
if(panel5!=NULL)
|
|
|
|
|
{
|
|
|
|
|
panel6.SetName("FieldR");
|
|
|
|
|
panel6.SetButtonCloseOff();
|
|
|
|
|
panel6.SetButtonMinimizeOff();
|
|
|
|
|
panel6.SetButtonPinOff();
|
|
|
|
|
panel6.View("");
|
|
|
|
|
panel6.SetPanelHeaderOff(true);
|
|
|
|
|
panel6.SetFontParams("Calibri",8);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Все таблицы на левой и правой панелях изначально не активны
|
|
|
|
|
LPanelTable=WRONG_VALUE;
|
|
|
|
|
RPanelTable=WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Всё успешно
|
2026-03-23 15:25:14 +07:00
|
|
|
return(INIT_SUCCEEDED);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 15:33:27 +07:00
|
|
|
//| Custom indicator deinitialization function |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void OnDeinit(const int reason)
|
|
|
|
|
{
|
|
|
|
|
//--- Закрываем базу данных
|
|
|
|
|
DatabaseClose(DBHandle);
|
|
|
|
|
if(GetLastError()==ERR_DATABASE_INVALID_HANDLE)
|
|
|
|
|
Print("Error. An invalid database handle was passed to the DatabaseClose() function");
|
|
|
|
|
|
|
|
|
|
//--- Если объект панели существует - удаляем
|
|
|
|
|
if(dashboard!=NULL)
|
|
|
|
|
{
|
|
|
|
|
delete dashboard;
|
|
|
|
|
ChartRedraw();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 15:25:14 +07:00
|
|
|
//| Custom indicator iteration function |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 15:33:27 +07:00
|
|
|
int OnCalculate(const int rates_total,
|
|
|
|
|
const int prev_calculated,
|
2026-03-23 15:25:14 +07:00
|
|
|
const datetime &time[],
|
|
|
|
|
const double &open[],
|
|
|
|
|
const double &high[],
|
|
|
|
|
const double &low[],
|
|
|
|
|
const double &close[],
|
|
|
|
|
const long &tick_volume[],
|
|
|
|
|
const long &volume[],
|
2026-03-23 15:33:27 +07:00
|
|
|
const int &spread[])
|
2026-03-23 15:25:14 +07:00
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
|
|
|
|
|
//--- return value of prev_calculated for next call
|
|
|
|
|
return(rates_total);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 15:33:27 +07:00
|
|
|
//| ChartEvent function |
|
2026-03-23 15:25:14 +07:00
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 15:33:27 +07:00
|
|
|
void OnChartEvent(const int id,
|
|
|
|
|
const long &lparam,
|
|
|
|
|
const double &dparam,
|
|
|
|
|
const string &sparam)
|
2026-03-23 15:25:14 +07:00
|
|
|
{
|
2026-03-23 15:33:27 +07:00
|
|
|
//--- Идентификатор активной панели
|
|
|
|
|
int table_id=WRONG_VALUE;
|
2026-03-23 15:25:14 +07:00
|
|
|
|
2026-03-23 15:33:27 +07:00
|
|
|
//--- Вызываем обработчик событий панели, которая в свою очередь отправляет сюда свои события
|
|
|
|
|
dashboard.OnChartEvent(id,lparam,dparam,sparam);
|
|
|
|
|
|
|
|
|
|
//--- Если получили пользовательское событие от панели-окна программы
|
|
|
|
|
if(id>CHARTEVENT_CUSTOM)
|
|
|
|
|
{
|
|
|
|
|
//--- Нажата кнопка закрытия на панели
|
|
|
|
|
if(id==1001)
|
|
|
|
|
{
|
|
|
|
|
//--- Здесь может быть обработка щелчка по кнопке закрытия
|
|
|
|
|
}
|
|
|
|
|
//--- Нажатия кнопок работы с БД - идентификатор всегда 1002, а уточнение - по значению в lparam
|
|
|
|
|
if(id==1002)
|
|
|
|
|
{
|
|
|
|
|
//--- получение истории сделок с сервера и трейдов из БД (нажата кнопка Get trade history)
|
|
|
|
|
if(lparam==3)
|
|
|
|
|
{
|
|
|
|
|
//--- Если история сделок не получена - уходим
|
|
|
|
|
if(!GetHistoryDeals(DATE_FROM, DATE_TO))
|
|
|
|
|
return;
|
|
|
|
|
//--- Если в истории нет сделок - сообщаем об этом и уходим
|
|
|
|
|
int deals_total=HistoryDealsTotal();
|
|
|
|
|
if(deals_total==0)
|
|
|
|
|
{
|
|
|
|
|
Print("No deals in history");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
//--- создадим таблицу сделок (DEALS) в базе данных
|
|
|
|
|
if(!CreateTableDeals(DBHandle))
|
|
|
|
|
return;
|
|
|
|
|
//--- внесем в созданную таблицу сделки
|
|
|
|
|
if(!InsertDeals(DBHandle))
|
|
|
|
|
return;
|
|
|
|
|
//--- Создадим таблицу трейдов (TRADES) на основе таблицы DEALS
|
|
|
|
|
if(!CreateTableTrades(DBHandle))
|
|
|
|
|
return;
|
|
|
|
|
//--- Заполним через SQL-запрос таблицу TRADES на основе данных из таблицы DEALS
|
|
|
|
|
if(!FillTRADEStableBasedOnDEALStable(DBHandle))
|
|
|
|
|
return;
|
|
|
|
|
//--- Запросим из БД список всех трейдов
|
|
|
|
|
if(!FillsListTradesFromDB(DBHandle, DB_NAME, ArrayTrades))
|
|
|
|
|
return;
|
|
|
|
|
//--- Выведем на панель количество сделок и количество трейдов в истории
|
|
|
|
|
dashboard.DrawText(" ",2,2,clrNONE,0,0); // стираем ранее написанное
|
|
|
|
|
dashboard.DrawText("Total deals in history: "+(string)deals_total+", trades: "+(string)ArrayTrades.Size(),216,3);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на панель заголовков
|
|
|
|
|
CDashboard *panel_h=dashboard.GetPanel("FieldH");
|
|
|
|
|
if(panel_h==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Проверяем наличие и получаем или создаём объект-таблицу для вывода заголовка таблицы трейдов
|
|
|
|
|
CTableData *table_h=NULL;
|
|
|
|
|
if(!panel_h.TableIsExist(TABLE_TRADES) && !panel_h.CreateNewTable(TABLE_TRADES))
|
|
|
|
|
return;
|
|
|
|
|
//--- Получаем указатель на объект-таблицу заголовков трейдов
|
|
|
|
|
table_h=panel_h.GetTable(TABLE_TRADES);
|
|
|
|
|
if(table_h==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Очищаем панель заголовка таблицы и выводим на неё таблицу заголовков
|
|
|
|
|
panel_h.Clear();
|
|
|
|
|
panel_h.DrawGrid(TABLE_TRADES,2,2,1,11,CELL_H,CELL_W_TRADES,C'200,200,200',false);
|
|
|
|
|
//--- Заполняем таблицу заголовков трейдов
|
|
|
|
|
FillsHeaderTradeTable(panel_h,table_h);
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на правую панель
|
|
|
|
|
CDashboard *panel_r=dashboard.GetPanel("FieldR");
|
|
|
|
|
if(panel_r==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Проверяем наличие и получаем или создаём объект-таблицу для вывода трейдов
|
|
|
|
|
if(!panel_r.TableIsExist(TABLE_TRADES) && !panel_r.CreateNewTable(TABLE_TRADES))
|
|
|
|
|
return;
|
|
|
|
|
//--- Получаем указатель на объект-таблицу трейдов
|
|
|
|
|
CTableData *table_r=panel_r.GetTable(TABLE_TRADES);
|
|
|
|
|
if(table_r==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Очищаем панель и выводим на неё таблицу трейдов
|
|
|
|
|
panel_r.Clear();
|
|
|
|
|
panel_r.DrawGrid(TABLE_TRADES,2,2,ArrayTrades.Size(),11,CELL_H,CELL_W_TRADES,C'220,220,220');
|
|
|
|
|
//--- Заполняем таблицу данными трейдов и указываем, что справа активна таблица TABLE_TRADES
|
|
|
|
|
FillsTradeTable(panel_r,table_r);
|
|
|
|
|
RPanelTable=TABLE_TRADES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если нажата кнопка отображения символов
|
|
|
|
|
if(lparam==1)
|
|
|
|
|
{
|
|
|
|
|
//--- запросим из БД список всех символов, на которых осуществлялась торговля, и заполним массив символов
|
|
|
|
|
if(!FillsListSymbolsFromDB(DBHandle, DB_NAME, ArraySymbols))
|
|
|
|
|
return;
|
|
|
|
|
//--- Увеличим массив символов на 1 для записи в него пункта "Все символы" (ALL)
|
|
|
|
|
int size=(int)ArraySymbols.Size();
|
|
|
|
|
if(ArrayResize(ArraySymbols, size+1)==size+1)
|
|
|
|
|
ArraySymbols[size]="ALL";
|
|
|
|
|
//--- Получаем указатель на левую панель
|
|
|
|
|
CDashboard *panel=dashboard.GetPanel("FieldL");
|
|
|
|
|
if(panel==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Проверяем наличие и получаем или создаём объект-таблицу для вывода списка символов
|
|
|
|
|
CTableData *table=NULL;
|
|
|
|
|
if(!panel.TableIsExist(TABLE_SYMBOLS) && !panel.CreateNewTable(TABLE_SYMBOLS))
|
|
|
|
|
return;
|
|
|
|
|
//--- Получаем указатель на объект-таблицу
|
|
|
|
|
table=panel.GetTable(TABLE_SYMBOLS);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Очищаем панель и рисуем на ней таблицу символов
|
|
|
|
|
panel.Clear();
|
|
|
|
|
panel.DrawGrid(TABLE_SYMBOLS,2,2,ArraySymbols.Size(),1,CELL_H,panel.Width()-5,C'220,220,220');
|
|
|
|
|
//--- Заполняем таблицу наименованиями символов и указываем, что на левой панели активна таблица TABLE_SYMBOLS
|
|
|
|
|
FillsSymbolTable(panel,table);
|
|
|
|
|
LPanelTable=TABLE_SYMBOLS;
|
|
|
|
|
|
|
|
|
|
//--- получим торговую статистику в разрезе символов
|
|
|
|
|
if(!GetTradingStatsBySymbols(DBHandle, DB_NAME, ArraySymbolStats))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//--- Выведем на панель количество символов, использованных в торговле
|
|
|
|
|
dashboard.DrawText(" ",2,2,clrNONE,0,0); // Стираем всё содержимое панели
|
|
|
|
|
dashboard.DrawText("Total number of symbols used in trade: "+(string)ArraySymbols.Size(),216,3);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на панель заголовков
|
|
|
|
|
CDashboard *panel_h=dashboard.GetPanel("FieldH");
|
|
|
|
|
if(panel_h==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Проверяем наличие и получаем или создаём объект-таблицу для вывода заголовка таблицы статистики символов
|
|
|
|
|
CTableData *table_h=NULL;
|
|
|
|
|
if(!panel_h.TableIsExist(TABLE_SYMBOLS) && !panel_h.CreateNewTable(TABLE_SYMBOLS))
|
|
|
|
|
return;
|
|
|
|
|
//--- Получаем указатель на объект-таблицу заголовков статистики символов
|
|
|
|
|
table_h=panel_h.GetTable(TABLE_SYMBOLS);
|
|
|
|
|
if(table_h==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Очищаем панель заголовка таблицы и выводим на неё таблицу
|
|
|
|
|
RPanelTable=TABLE_SYMBOLS;
|
|
|
|
|
panel_h.Clear();
|
|
|
|
|
panel_h.DrawGrid(TABLE_SYMBOLS,2,2,1,ArrayDataName.Size(),CELL_H,CELL_W_SYMBOLS,C'200,200,200',false);
|
|
|
|
|
//--- Заполняем таблицу заголовка статистики символов
|
|
|
|
|
FillsHeaderTradingStatsTable(panel_h,table_h);
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на правую панель
|
|
|
|
|
CDashboard *panel_r=dashboard.GetPanel("FieldR");
|
|
|
|
|
if(panel_r==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Проверяем наличие и получаем или создаём объект-таблицу для вывода статистики символов
|
|
|
|
|
if(!panel_r.TableIsExist(TABLE_SYMBOLS) && !panel_r.CreateNewTable(TABLE_SYMBOLS))
|
|
|
|
|
return;
|
|
|
|
|
//--- Получаем указатель на объект-таблицу статистики символов
|
|
|
|
|
CTableData *table_r=panel_r.GetTable(TABLE_SYMBOLS);
|
|
|
|
|
if(table_r==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Очищаем панель и выводим на неё таблицу статистики символов
|
|
|
|
|
panel_r.Clear();
|
|
|
|
|
panel_r.DrawGrid(TABLE_SYMBOLS,2,2,ArraySymbolStats.Size(),ArrayDataName.Size(),CELL_H,CELL_W_SYMBOLS,C'220,220,220');
|
|
|
|
|
//--- Заполняем таблицу данными статистики символов и указываем, что справа активна таблица TABLE_SYMBOLS
|
|
|
|
|
FillsTradingStatsBySymbolsTable(panel_r,table_r);
|
|
|
|
|
RPanelTable=TABLE_SYMBOLS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если нажата кнопка отображения магиков
|
|
|
|
|
if(lparam==2)
|
|
|
|
|
{
|
|
|
|
|
//--- Запросим из БД список всех магиков, на которых осуществлялась торговля, и заполним массив магиков
|
|
|
|
|
if(!FillsListMagicsFromDB(DBHandle, DB_NAME, ArrayMagics))
|
|
|
|
|
return;
|
|
|
|
|
//--- Увеличим массив магиков на 1 для записи в него пункта "Все магики" (значение LONG_MAX указывает на это)
|
|
|
|
|
int size=(int)ArrayMagics.Size();
|
|
|
|
|
if(ArrayResize(ArrayMagics, size+1)==size+1)
|
|
|
|
|
ArrayMagics[size]=LONG_MAX;
|
|
|
|
|
//--- Получаем указатель на левую панель
|
|
|
|
|
CDashboard *panel=dashboard.GetPanel("FieldL");
|
|
|
|
|
if(panel==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Проверяем наличие и получаем или создаём объект-таблицу для вывода магиков
|
|
|
|
|
CTableData *table=NULL;
|
|
|
|
|
if(!panel.TableIsExist(TABLE_MAGICS) && !panel.CreateNewTable(TABLE_MAGICS))
|
|
|
|
|
return;
|
|
|
|
|
//--- Получаем указатель на объект-таблицу
|
|
|
|
|
table=panel.GetTable(TABLE_MAGICS);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Очищаем панель и рисуем на ней таблицу магиков
|
|
|
|
|
panel.Clear();
|
|
|
|
|
panel.DrawGrid(TABLE_MAGICS,2,2,ArrayMagics.Size(),1,CELL_H,panel.Width()-5,C'220,220,220');
|
|
|
|
|
//--- Заполняем таблицу значениями магиков и указываем, что на левой панели активна таблица TABLE_MAGICS
|
|
|
|
|
FillsMagicTable(panel,table);
|
|
|
|
|
LPanelTable=TABLE_MAGICS;
|
|
|
|
|
|
|
|
|
|
//--- Получаем торговую статистику в разрезе магиков
|
|
|
|
|
if(!GetTradingStatsByMagics(DBHandle, DB_NAME, ArrayMagicStats))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//--- Выводим на панель количество магиков, использованных в торговле
|
|
|
|
|
dashboard.DrawText(" ",2,2,clrNONE,0,0);
|
|
|
|
|
dashboard.DrawText("Total number of magics used in trade: "+(string)ArrayMagics.Size(),216,3);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на панель заголовков
|
|
|
|
|
CDashboard *panel_h=dashboard.GetPanel("FieldH");
|
|
|
|
|
if(panel_h==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Проверяем наличие и получаем или создаём объект-таблицу для вывода заголовка таблицы статистики магиков
|
|
|
|
|
CTableData *table_h=NULL;
|
|
|
|
|
if(!panel_h.TableIsExist(TABLE_MAGICS) && !panel_h.CreateNewTable(TABLE_MAGICS))
|
|
|
|
|
return;
|
|
|
|
|
//--- Получаем указатель на объект-таблицу заголовков статистики магиков
|
|
|
|
|
table_h=panel_h.GetTable(TABLE_MAGICS);
|
|
|
|
|
if(table_h==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Очищаем панель заголовка таблицы и выводим на неё таблицу
|
|
|
|
|
panel_h.Clear();
|
|
|
|
|
panel_h.DrawGrid(TABLE_MAGICS,2,2,1,ArrayDataName.Size(),CELL_H,CELL_W_MAGICS,C'200,200,200',false);
|
|
|
|
|
//--- Заполняем таблицу заголовка статистики символов
|
|
|
|
|
FillsHeaderTradingStatsTable(panel_h,table_h);
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на правую панель
|
|
|
|
|
CDashboard *panel_r=dashboard.GetPanel("FieldR");
|
|
|
|
|
if(panel_r==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Проверяем наличие и получаем или создаём объект-таблицу для вывода статистики магиков
|
|
|
|
|
if(!panel_r.TableIsExist(TABLE_MAGICS) && !panel_r.CreateNewTable(TABLE_MAGICS))
|
|
|
|
|
return;
|
|
|
|
|
//--- Получаем указатель на объект-таблицу статистики магиков
|
|
|
|
|
CTableData *table_r=panel_r.GetTable(TABLE_MAGICS);
|
|
|
|
|
if(table_r==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Очищаем панель и выводим на неё таблицу статистики магиков
|
|
|
|
|
panel_r.Clear();
|
|
|
|
|
panel_r.DrawGrid(TABLE_MAGICS,2,2,ArrayMagicStats.Size(),ArrayDataName.Size(),CELL_H,CELL_W_MAGICS,C'220,220,220');
|
|
|
|
|
//--- Заполняем таблицу данными статистики магиков и указываем, что активна таблица TABLE_MAGICS
|
|
|
|
|
FillsTradingStatsByMagicsTable(panel_r,table_r);
|
|
|
|
|
RPanelTable=TABLE_MAGICS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если получили событие прокрутки колёсика мышки
|
|
|
|
|
if(id==CHARTEVENT_MOUSE_WHEEL)
|
|
|
|
|
{
|
|
|
|
|
static int index_l_p=WRONG_VALUE; // Прошлый индекс строки под курсором в таблице на левой панели
|
|
|
|
|
static int index_r_p=WRONG_VALUE; // Прошлый индекс строки под курсором в таблице на правой панели
|
|
|
|
|
|
|
|
|
|
//--- разберем состояние кнопок и колесика мышки для этого события
|
|
|
|
|
int flg_keys = (int)(lparam>>32); // флаг состояний клавиш Ctrl, Shift и кнопок мышки
|
|
|
|
|
int x_cursor = (int)(short)lparam; // X-координата, в которой произошло событие колесика мышки
|
|
|
|
|
int y_cursor = (int)(short)(lparam>>16); // Y-координата, в которой произошло событие колесика мышки
|
|
|
|
|
int delta = (int)dparam; // суммарное значение прокрутки колесика, срабатывает при достижении +120 или -120
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на левую панель и вызываем для неё обработчик прокрутки колёсика мышки
|
|
|
|
|
int index_l=WRONG_VALUE;
|
|
|
|
|
CDashboard *panel_l=dashboard.GetPanel("FieldL");
|
|
|
|
|
if(panel_l!=NULL)
|
|
|
|
|
index_l=TableMouseWhellHandlerL(x_cursor,y_cursor,((flg_keys&0x0004)!=0),delta,panel_l,LPanelTable);
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на правую панель и вызываем для неё обработчик прокрутки колёсика мышки
|
|
|
|
|
int index_r=WRONG_VALUE;
|
|
|
|
|
CDashboard *panel_r=dashboard.GetPanel("FieldR");
|
|
|
|
|
if(panel_r!=NULL)
|
|
|
|
|
index_r=TableMouseWhellHandlerR(x_cursor,y_cursor,((flg_keys&0x0004)!=0),delta,panel_r,RPanelTable);
|
|
|
|
|
|
|
|
|
|
//--- При необходимости можно обработать строку таблицы, над которой находится курсор.
|
|
|
|
|
//--- Номер строки записан в index_l для левой панели и в index_r - для правой
|
|
|
|
|
|
|
|
|
|
//--- Обновляем график после всех изменений, произошедших в обработчиках прокрутки колёсика мышки
|
|
|
|
|
if(index_l_p!=index_l)
|
|
|
|
|
{
|
|
|
|
|
index_l_p=index_l;
|
|
|
|
|
ChartRedraw();
|
|
|
|
|
}
|
|
|
|
|
if(index_r_p!=index_r)
|
|
|
|
|
{
|
|
|
|
|
index_r_p=index_r;
|
|
|
|
|
ChartRedraw();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если получили событие перемещения мышки
|
|
|
|
|
if(id==CHARTEVENT_MOUSE_MOVE)
|
|
|
|
|
{
|
|
|
|
|
static int index_l_p=WRONG_VALUE; // Прошлый индекс строки под курсором в таблице на левой панели
|
|
|
|
|
static int index_r_p=WRONG_VALUE; // Прошлый индекс строки под курсором в таблице на правой панели
|
|
|
|
|
|
|
|
|
|
int x_cursor = (int)lparam; // X-координата курсора мышки
|
|
|
|
|
int y_cursor = (int)dparam; // Y-координата курсора мышки
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на левую панель и вызываем для неё обработчик перемещения мышки
|
|
|
|
|
int index_l=WRONG_VALUE;
|
|
|
|
|
CDashboard *panel_l=dashboard.GetPanel("FieldL");
|
|
|
|
|
if(panel_l!=NULL)
|
|
|
|
|
index_l=TableMouseMoveHandlerL(x_cursor,y_cursor,panel_l,LPanelTable);
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на правую панель и вызываем для неё обработчик перемещения мышки
|
|
|
|
|
int index_r=WRONG_VALUE;
|
|
|
|
|
CDashboard *panel_r=dashboard.GetPanel("FieldR");
|
|
|
|
|
|
|
|
|
|
if(panel_r!=NULL)
|
|
|
|
|
index_r=TableMouseMoveHandlerR(x_cursor,y_cursor,panel_r,RPanelTable);
|
|
|
|
|
|
|
|
|
|
//--- При необходимости можно обработать строку таблицы, над которой находится курсор.
|
|
|
|
|
//--- Номер строки записан в index_l для левой панели и в index_r - для правой
|
|
|
|
|
|
|
|
|
|
//--- Обновляем график после всех изменений, произошедших в обработчиках перемещения мышки
|
|
|
|
|
if(index_l_p!=index_l)
|
|
|
|
|
{
|
|
|
|
|
index_l_p=index_l;
|
|
|
|
|
ChartRedraw();
|
|
|
|
|
}
|
|
|
|
|
if(index_r_p!=index_r)
|
|
|
|
|
{
|
|
|
|
|
index_r_p=index_r;
|
|
|
|
|
ChartRedraw();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если получили событие щелчка мышки
|
|
|
|
|
if(id==CHARTEVENT_CLICK)
|
|
|
|
|
{
|
|
|
|
|
int x_cursor = (int)lparam; // X-координата курсора мышки
|
|
|
|
|
int y_cursor = (int)dparam; // Y-координата курсора мышки
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на левую панель и вызываем обработчик щелчка мышки
|
|
|
|
|
int index_l=WRONG_VALUE;
|
|
|
|
|
CDashboard *panel_l=dashboard.GetPanel("FieldL");
|
|
|
|
|
if(panel_l!=NULL)
|
|
|
|
|
index_l=TableMouseClickHandler(x_cursor,y_cursor,panel_l,LPanelTable);
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на правую панель и вызываем обработчик щелчка мышки
|
|
|
|
|
int index_r=WRONG_VALUE;
|
|
|
|
|
CDashboard *panel_r=dashboard.GetPanel("FieldR");
|
|
|
|
|
if(panel_r!=NULL)
|
|
|
|
|
index_r=TableMouseClickHandler(x_cursor,y_cursor,panel_r,RPanelTable);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- Обработаем строку таблицы, по которой был щелчок
|
|
|
|
|
//--- Если в левой панели был щелчок по символу из списка
|
|
|
|
|
if(LPanelTable==TABLE_SYMBOLS && index_l>WRONG_VALUE)
|
|
|
|
|
{
|
|
|
|
|
//--- Получим таблицу символов с левой панели
|
|
|
|
|
CTableData *table=panel_l.GetTable(TABLE_SYMBOLS);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Получим единственную ячейку таблицы с номером строки index_l
|
|
|
|
|
CTableCell *cell=table.GetCell(index_l,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Если щелчок по последнему пункту (ALL)
|
|
|
|
|
if(index_l==ArraySymbols.Size()-1)
|
|
|
|
|
{
|
|
|
|
|
//--- получим и отобразим торговую статистику аккаунта, и укажем, что справа активна панель TABLE_STATS
|
|
|
|
|
if(!GetTradingStatsByAccount(DBHandle, DB_NAME, ArrayAccountStats))
|
|
|
|
|
return;
|
|
|
|
|
if(ViewStatistic(TABLE_ACCOUNT,(string)AccountInfoInteger(ACCOUNT_LOGIN)))
|
|
|
|
|
RPanelTable=TABLE_STATS;
|
|
|
|
|
}
|
|
|
|
|
//--- Щелчок по наименованию символа - отобразим статистику по символу и укажем, что справа активна панель TABLE_STATS
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(ViewStatistic(TABLE_SYMBOLS,cell.Text()))
|
|
|
|
|
RPanelTable=TABLE_STATS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если в левой панели был щелчок по магику из списка
|
|
|
|
|
if(LPanelTable==TABLE_MAGICS && index_l>WRONG_VALUE)
|
|
|
|
|
{
|
|
|
|
|
//--- Получим таблицу магиков с левой панели
|
|
|
|
|
CTableData *table=panel_l.GetTable(TABLE_MAGICS);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Получим единственную ячейку таблицы с номером строки index_l
|
|
|
|
|
CTableCell *cell=table.GetCell(index_l,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Если щелчок по последнему пункту (ALL)
|
|
|
|
|
if(index_l==ArrayMagics.Size()-1)
|
|
|
|
|
{
|
|
|
|
|
//--- получим и отобразим торговую статистику аккаунта, и укажем, что справа активна панель TABLE_STATS
|
|
|
|
|
if(!GetTradingStatsByAccount(DBHandle, DB_NAME, ArrayAccountStats))
|
|
|
|
|
return;
|
|
|
|
|
if(ViewStatistic(TABLE_ACCOUNT,(string)AccountInfoInteger(ACCOUNT_LOGIN)))
|
|
|
|
|
RPanelTable=TABLE_STATS;
|
|
|
|
|
}
|
|
|
|
|
//--- Щелчок по значению магика - отобразим статистику по магику и укажем, что справа активна панель TABLE_STATS
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(ViewStatistic(TABLE_MAGICS,cell.Text()))
|
|
|
|
|
RPanelTable=TABLE_STATS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если в правой панели был щелчок по символу из списка
|
|
|
|
|
if(RPanelTable==TABLE_SYMBOLS && index_r>WRONG_VALUE)
|
|
|
|
|
{
|
|
|
|
|
//--- Получим таблицу статистики символов с правой панели
|
|
|
|
|
CTableData *table=panel_r.GetTable(TABLE_SYMBOLS);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Получим нулевую ячейку таблицы с номером строки index_r
|
|
|
|
|
CTableCell *cell=table.GetCell(index_r,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Отобразим итоговую статистику по символу и укажем, что справа активна панель TABLE_STATS
|
|
|
|
|
if(ViewStatistic(TABLE_SYMBOLS,cell.Text()))
|
|
|
|
|
RPanelTable=TABLE_STATS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если в правой панели был щелчок по магику из списка
|
|
|
|
|
if(RPanelTable==TABLE_MAGICS && index_r>WRONG_VALUE)
|
|
|
|
|
{
|
|
|
|
|
//--- Получим таблицу статистики магиков с правой панели
|
|
|
|
|
CTableData *table=panel_r.GetTable(TABLE_MAGICS);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Получим нулевую ячейку таблицы с номером строки index_r
|
|
|
|
|
CTableCell *cell=table.GetCell(index_r,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Отобразим итоговую статистику по магику и укажем, что справа активна панель TABLE_STATS
|
|
|
|
|
if(ViewStatistic(TABLE_MAGICS,cell.Text()))
|
|
|
|
|
RPanelTable=TABLE_STATS;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-23 15:25:14 +07:00
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 15:33:27 +07:00
|
|
|
//| Возвращает индекс строки таблицы по координатам курсора |
|
2026-03-23 15:25:14 +07:00
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 15:33:27 +07:00
|
|
|
int TableSelectRowByMouse(const int x_cursor, const int y_cursor, const int cell_h, CDashboard *panel, CTableData *table)
|
2026-03-23 15:25:14 +07:00
|
|
|
{
|
2026-03-23 15:33:27 +07:00
|
|
|
//--- Проверяем указатели на панель и таблицу
|
|
|
|
|
if(panel==NULL || table==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
int index=WRONG_VALUE; // Индекс строки таблицы, расположенной под курсором
|
|
|
|
|
|
|
|
|
|
//--- В цикле по строкам таблицы
|
|
|
|
|
int total=table.RowsTotal();
|
|
|
|
|
for(int i=0;i<total;i++)
|
|
|
|
|
{
|
|
|
|
|
//--- получаем очередную нулевую ячейку таблицы в строке с индексом цикла
|
|
|
|
|
CTableCell *cell=table.GetCell(i,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//--- Рассчитываем верхнюю и нижнюю координаты расположения строки таблицы по координате Y ячейки
|
|
|
|
|
int y1=panel.CoordY()+cell.Y()+1;
|
|
|
|
|
int y2=y1+cell_h;
|
|
|
|
|
|
|
|
|
|
//--- Если курсор по вертикали находится внутри рассчитанных координат строки таблицы
|
|
|
|
|
if(y_cursor>y1 && y_cursor<y2)
|
|
|
|
|
{
|
|
|
|
|
//--- Записываем индекс строки, рисуем прямоугольную область на всю ширину таблицы (выделение строки под курсором) и возвращаем индекс строки
|
|
|
|
|
index=cell.Row();
|
|
|
|
|
panel.DrawRectangleFill(2,cell.Y()+1,panel.Width()-4,y2-y1-1,C'220,220,220',240);
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//--- Ничего не нашли
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Обработчик прокрутки колёсика мышки внутри таблицы левой панели |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int TableMouseWhellHandlerL(const int x_cursor,const int y_cursor,const bool shift_flag,const int delta,CDashboard *panel,const int table_id)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатель на левую панель
|
|
|
|
|
if(panel==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Проверяем расположение курсора внутри панели
|
|
|
|
|
if(x_cursor<panel.CoordX()+2 || x_cursor>panel.CoordX()+panel.Width() ||
|
|
|
|
|
y_cursor<panel.CoordY()+4 || y_cursor>panel.CoordY()+panel.Height())
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Проверяем наличие таблицы на панели
|
|
|
|
|
if(!panel.TableIsExist(table_id))
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на активную таблицу на панели
|
|
|
|
|
CTableData *table=panel.GetTable(table_id);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Рассчитываем смещение таблицы на половину высоты строки таблицы
|
|
|
|
|
int shift=CELL_H/2*(delta<0 ? -1 : 1);
|
|
|
|
|
|
|
|
|
|
//--- Рассчитываем координаты, в пределах которых смещается таблица
|
|
|
|
|
int y=table.Y1()+shift;
|
|
|
|
|
if(y>2)
|
|
|
|
|
y=2;
|
|
|
|
|
if(y+table.Height()<panel.Height()-2)
|
|
|
|
|
y=panel.Height()-2-table.Height();
|
|
|
|
|
if(table.Height()<panel.Height())
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Очищаем панель и выводим на неё активную таблицу
|
|
|
|
|
int total=int(table_id==TABLE_SYMBOLS ? ArraySymbols.Size() : ArrayMagics.Size());
|
|
|
|
|
panel.Clear();
|
|
|
|
|
panel.DrawGrid(table_id,2,y,total,1,CELL_H,panel.Width()-5,C'220,220,220');
|
|
|
|
|
|
|
|
|
|
//--- Заполняем таблицу значениями
|
|
|
|
|
if(table_id==TABLE_SYMBOLS)
|
|
|
|
|
FillsSymbolTable(panel,table);
|
|
|
|
|
else
|
|
|
|
|
FillsMagicTable(panel,table);
|
|
|
|
|
|
|
|
|
|
//--- Получаем номер строки таблицы, над которой расположен курсор
|
|
|
|
|
int index=TableSelectRowByMouse(x_cursor,y_cursor,CELL_H,panel,table);
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Обработчик смещения курсора мышки внутри таблицы левой панели |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int TableMouseMoveHandlerL(const int x_cursor,const int y_cursor,CDashboard *panel,const int table_id)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатель на левую панель
|
|
|
|
|
if(panel==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Проверяем наличие таблицы на панели
|
|
|
|
|
if(!panel.TableIsExist(table_id))
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на активную таблицу на панели
|
|
|
|
|
CTableData *table=panel.GetTable(table_id);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Проверяем расположение курсора внутри панели
|
|
|
|
|
//--- Если курсор за пределами панели - рисуем активную таблицу и возвращаем -1 (чтобы убрать выделение строки, над которой был курсор)
|
|
|
|
|
int total=int(table_id==TABLE_SYMBOLS ? ArraySymbols.Size() : ArrayMagics.Size());
|
|
|
|
|
if(x_cursor<panel.CoordX()+2 || x_cursor>panel.CoordX()+panel.Width() ||
|
|
|
|
|
y_cursor<panel.CoordY()+4 || y_cursor>panel.CoordY()+panel.Height())
|
|
|
|
|
{
|
|
|
|
|
panel.Clear();
|
|
|
|
|
panel.DrawGrid(table_id,2,table.Y1(),total,1,CELL_H,panel.Width()-5,C'220,220,220');
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Очищаем панель и выводим на неё активную таблицу
|
|
|
|
|
panel.Clear();
|
|
|
|
|
panel.DrawGrid(table_id,2,table.Y1(),total,1,CELL_H,panel.Width()-5,C'220,220,220');
|
|
|
|
|
|
|
|
|
|
//--- Заполняем таблицу значениями
|
|
|
|
|
if(table_id==TABLE_SYMBOLS)
|
|
|
|
|
FillsSymbolTable(panel,table);
|
|
|
|
|
else
|
|
|
|
|
FillsMagicTable(panel,table);
|
|
|
|
|
|
|
|
|
|
//--- Получаем и возвращаем номер строки таблицы, над которой расположен курсор
|
|
|
|
|
int index=TableSelectRowByMouse(x_cursor,y_cursor,CELL_H,panel,table);
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Обработчик прокрутки колёсика мышки внутри таблицы правой панели |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int TableMouseWhellHandlerR(const int x_cursor,const int y_cursor,const bool shift_flag,const int delta,CDashboard *panel,const int table_id)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатель на правую панель
|
|
|
|
|
if(panel==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Проверяем расположение курсора внутри панели
|
|
|
|
|
if(x_cursor<panel.CoordX()+2 || x_cursor>panel.CoordX()+panel.Width() ||
|
|
|
|
|
y_cursor<panel.CoordY()+4 || y_cursor>panel.CoordY()+panel.Height())
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Проверяем наличие таблицы на панели
|
|
|
|
|
if(!panel.TableIsExist(table_id))
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на активную таблицу на панели
|
|
|
|
|
CTableData *table=panel.GetTable(table_id);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
//--- Рассчитываем вертикальное смещение таблицы на половину высоты строки таблицы
|
|
|
|
|
int shift_y=CELL_H/2*(delta<0 ? -1 : 1);
|
|
|
|
|
|
|
|
|
|
//--- Рассчитываем горизонтальное смещение таблицы на размер высоты строки таблицы
|
|
|
|
|
int shift_x=(shift_flag ? CELL_H*(delta<0 ? -1 : 1) : 0);
|
|
|
|
|
|
|
|
|
|
//--- Рассчитываем координаты, в пределах которых смещается таблица по Y
|
|
|
|
|
int y=table.Y1()+shift_y;
|
|
|
|
|
if(y>2)
|
|
|
|
|
y=2;
|
|
|
|
|
if(y+table.Height()<panel.Height()-2)
|
|
|
|
|
y=panel.Height()-2-table.Height();
|
|
|
|
|
|
|
|
|
|
//--- Рассчитываем координаты, в пределах которых смещается таблица по X
|
|
|
|
|
int x=0;
|
|
|
|
|
if(shift_flag)
|
|
|
|
|
{
|
|
|
|
|
x=table.X1()+shift_x;
|
|
|
|
|
if(x>2)
|
|
|
|
|
x=2;
|
|
|
|
|
if(x+table.Width()<panel.Width()-2)
|
|
|
|
|
x=panel.Width()-2-table.Width();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если вся таблица умещается в размеры панели - ничего прокручивать не нужно, возвращаем -1
|
|
|
|
|
if(table.Height()<panel.Height() && table.Width()<panel.Width())
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Определяем размеры таблицы
|
|
|
|
|
int total=0; // количество строк
|
|
|
|
|
int columns=0; // количество столбцов
|
|
|
|
|
int cell_w=0; // ширина ячейки таблицы (столбца)
|
|
|
|
|
int cell_h=CELL_H; // высота ячейки таблицы (строки)
|
|
|
|
|
switch(table_id)
|
|
|
|
|
{
|
|
|
|
|
case TABLE_TRADES :
|
|
|
|
|
total=(int)ArrayTrades.Size();
|
|
|
|
|
columns=11;
|
|
|
|
|
cell_w=CELL_W_TRADES;
|
|
|
|
|
break;
|
|
|
|
|
case TABLE_SYMBOLS:
|
|
|
|
|
total=(int)ArraySymbolStats.Size();
|
|
|
|
|
columns=(int)ArrayDataName.Size();
|
|
|
|
|
cell_w=CELL_W_SYMBOLS;
|
|
|
|
|
break;
|
|
|
|
|
case TABLE_MAGICS :
|
|
|
|
|
total=(int)ArrayMagicStats.Size();
|
|
|
|
|
columns=(int)ArrayDataName.Size();
|
|
|
|
|
cell_w=CELL_W_MAGICS;
|
|
|
|
|
break;
|
|
|
|
|
case TABLE_STATS :
|
|
|
|
|
total=TABLE_STAT_ROWS;
|
|
|
|
|
columns=TABLE_STAT_COLS;
|
|
|
|
|
cell_w=(panel.Width()-4)/TABLE_STAT_COLS;
|
|
|
|
|
cell_h=(panel.Height()-4)/total;
|
|
|
|
|
break;
|
|
|
|
|
default :
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
//--- Очищаем панель и выводим на неё активную таблицу
|
|
|
|
|
panel.Clear();
|
|
|
|
|
panel.DrawGrid(table_id,
|
|
|
|
|
(shift_flag ? x : table.X1()),
|
|
|
|
|
(!shift_flag && table.Height()>panel.Height() ? y : table.Y1()),
|
|
|
|
|
total,columns,cell_h,cell_w,
|
|
|
|
|
(table_id!=TABLE_STATS ? C'220,220,220' : C'230,230,230'),
|
|
|
|
|
(table_id!=TABLE_STATS));
|
|
|
|
|
|
|
|
|
|
//--- Заполняем таблицу значениями
|
|
|
|
|
switch(table_id)
|
|
|
|
|
{
|
|
|
|
|
case TABLE_TRADES : FillsTradeTable(panel,table); break;
|
|
|
|
|
case TABLE_SYMBOLS: FillsTradingStatsBySymbolsTable(panel,table); break;
|
|
|
|
|
case TABLE_MAGICS : FillsTradingStatsByMagicsTable(panel,table); break;
|
|
|
|
|
default : break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на панель заголовка
|
|
|
|
|
CDashboard *panel_h=dashboard.GetPanel("FieldH");
|
|
|
|
|
if(panel_h==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
//--- Получаем указатель на таблицу заголовка
|
|
|
|
|
CTableData *table_h=panel_h.GetTable(table_id);
|
|
|
|
|
if(table_h==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
//--- Очищаем панель заголовка таблицы и выводим на неё таблицу
|
|
|
|
|
panel_h.Clear();
|
|
|
|
|
panel_h.DrawGrid(table_id,(shift_flag ? x : table_h.X1()),2,1,columns,cell_h,cell_w,C'200,200,200',false);
|
|
|
|
|
//--- Заполняем таблицу заголовков
|
|
|
|
|
switch(table_id)
|
|
|
|
|
{
|
|
|
|
|
case TABLE_TRADES : FillsHeaderTradeTable(panel_h,table_h); break;
|
|
|
|
|
case TABLE_SYMBOLS:
|
|
|
|
|
case TABLE_MAGICS : FillsHeaderTradingStatsTable(panel_h,table_h); break;
|
|
|
|
|
default : break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Для таблицы итоговой статистики номер строки под курсором искать не нужно
|
|
|
|
|
if(table.ID()==TABLE_STATS)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Получаем номер строки таблицы, над которой расположен курсор
|
|
|
|
|
int index=TableSelectRowByMouse(x_cursor,y_cursor,cell_h,panel,table);
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Обработчик смещения курсора мышки внутри таблицы правой панели |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int TableMouseMoveHandlerR(const int x_cursor,const int y_cursor,CDashboard *panel,const int table_id)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатель на левую панель
|
|
|
|
|
if(panel==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Проверяем наличие таблицы на панели
|
|
|
|
|
if(!panel.TableIsExist(table_id))
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на активную таблицу на панели
|
|
|
|
|
CTableData *table=panel.GetTable(table_id);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Определяем размеры таблицы
|
|
|
|
|
int total=0; // количество строк
|
|
|
|
|
int columns=0; // количество столбцов
|
|
|
|
|
int cell_w=0; // ширина ячейки таблицы (столбца)
|
|
|
|
|
int cell_h=CELL_H; // высота ячейки таблицы (строки)
|
|
|
|
|
switch(table_id)
|
|
|
|
|
{
|
|
|
|
|
case TABLE_TRADES :
|
|
|
|
|
total=(int)ArrayTrades.Size();
|
|
|
|
|
columns=11;
|
|
|
|
|
cell_w=CELL_W_TRADES;
|
|
|
|
|
break;
|
|
|
|
|
case TABLE_SYMBOLS:
|
|
|
|
|
total=(int)ArraySymbolStats.Size();
|
|
|
|
|
columns=(int)ArrayDataName.Size();
|
|
|
|
|
cell_w=CELL_W_SYMBOLS;
|
|
|
|
|
break;
|
|
|
|
|
case TABLE_MAGICS :
|
|
|
|
|
total=(int)ArrayMagicStats.Size();
|
|
|
|
|
columns=(int)ArrayDataName.Size();
|
|
|
|
|
cell_w=CELL_W_MAGICS;
|
|
|
|
|
break;
|
|
|
|
|
case TABLE_STATS :
|
|
|
|
|
total=TABLE_STAT_ROWS;
|
|
|
|
|
columns=TABLE_STAT_COLS;
|
|
|
|
|
cell_w=(panel.Width()-4)/TABLE_STAT_COLS;
|
|
|
|
|
cell_h=(panel.Height()-4)/total;
|
|
|
|
|
break;
|
|
|
|
|
default :
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Проверяем расположение курсора внутри панели
|
|
|
|
|
//--- Если курсор за пределами панели - рисуем активную таблицу и возвращаем -1 (чтобы убрать выделение строки, над которой был курсор)
|
|
|
|
|
if(x_cursor<panel.CoordX()+2 || x_cursor>panel.CoordX()+panel.Width() ||
|
|
|
|
|
y_cursor<panel.CoordY()+4 || y_cursor>panel.CoordY()+panel.Height())
|
|
|
|
|
{
|
|
|
|
|
panel.Clear();
|
|
|
|
|
panel.DrawGrid(table_id,table.X1(),table.Y1(),total,columns,cell_h,cell_w,(table_id!=TABLE_STATS ? C'220,220,220' : C'230,230,230'),(table_id!=TABLE_STATS));
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Очищаем панель и выводим на неё активную таблицу
|
|
|
|
|
panel.Clear();
|
|
|
|
|
panel.DrawGrid(table_id,table.X1(),table.Y1(),total,columns,cell_h,cell_w,(table_id!=TABLE_STATS ? C'220,220,220' : C'230,230,230'),(table_id!=TABLE_STATS));
|
|
|
|
|
|
|
|
|
|
//--- Заполняем таблицу значениями
|
|
|
|
|
switch(table_id)
|
|
|
|
|
{
|
|
|
|
|
case TABLE_TRADES : FillsTradeTable(panel,table); break;
|
|
|
|
|
case TABLE_SYMBOLS: FillsTradingStatsBySymbolsTable(panel,table); break;
|
|
|
|
|
case TABLE_MAGICS : FillsTradingStatsByMagicsTable(panel,table); break;
|
|
|
|
|
default : break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Для таблицы итоговой статистики номер строки под курсором искать не нужно
|
|
|
|
|
if(table.ID()==TABLE_STATS)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Получаем номер строки таблицы, над которой расположен курсор
|
|
|
|
|
int index=TableSelectRowByMouse(x_cursor,y_cursor,cell_h,panel,table);
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Обработчик щелчка мышки внутри таблицы на панели |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int TableMouseClickHandler(const int x_cursor,const int y_cursor,CDashboard *panel,const int table_id)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатель на левую панель
|
|
|
|
|
if(panel==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Проверяем расположение курсора внутри панели
|
|
|
|
|
if(x_cursor<panel.CoordX()+2 || x_cursor>panel.CoordX()+panel.Width() ||
|
|
|
|
|
y_cursor<panel.CoordY()+4 || y_cursor>panel.CoordY()+panel.Height())
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Проверяем наличие таблицы на панели
|
|
|
|
|
if(!panel.TableIsExist(table_id))
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Получаем указатель на активную таблицу на панели
|
|
|
|
|
CTableData *table=panel.GetTable(table_id);
|
|
|
|
|
if(table==NULL)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Для таблицы итоговой статистики номер строки под курсором искать не нужно
|
|
|
|
|
if(table.ID()==TABLE_STATS)
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- Получаем номер строки таблицы, на которой был щелчок
|
|
|
|
|
int index=TableSelectRowByMouse(x_cursor,y_cursor,CELL_H,panel,table);
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Заполняет таблицу наименованиями символов |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void FillsSymbolTable(CDashboard *panel,CTableData *table)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатели на панель и таблицу
|
|
|
|
|
if(panel==NULL || table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//--- Рассчитаем индекс строки, с которой необходимо начать заполнение таблицы
|
|
|
|
|
CTableCell *cell=table.GetCell(0,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
return;
|
|
|
|
|
int y=panel.CoordY()+cell.Y()-2;
|
|
|
|
|
int diff=panel.CoordY()-y;
|
|
|
|
|
int index=diff/CELL_H;
|
|
|
|
|
|
|
|
|
|
//--- Заполняем таблицу значениями из массива, начиная со строки index
|
|
|
|
|
for(int i=index;i<(int)ArraySymbols.Size();i++)
|
|
|
|
|
{
|
|
|
|
|
CTableCell *cell=table.GetCell(i,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//--- невидимые области таблицы не рисуем
|
|
|
|
|
if(cell.X()>panel.CoordX()+panel.Width())
|
|
|
|
|
continue;
|
|
|
|
|
if(cell.Y()>panel.CoordY()+panel.Height())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
//--- выводим данные из массива в ячейки таблицы
|
|
|
|
|
cell.SetText(ArraySymbols[i]);
|
|
|
|
|
panel.DrawText(cell.Text(),cell.X()+2,cell.Y()+1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Заполняет таблицу значениями магиков |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void FillsMagicTable(CDashboard *panel,CTableData *table)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатели на панель и таблицу
|
|
|
|
|
if(panel==NULL || table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//--- Рассчитаем индекс строки, с которой необходимо начать заполнение таблицы
|
|
|
|
|
CTableCell *cell=table.GetCell(0,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
return;
|
|
|
|
|
int y=panel.CoordY()+cell.Y()-2;
|
|
|
|
|
int diff=panel.CoordY()-y;
|
|
|
|
|
int index=diff/CELL_H;
|
|
|
|
|
|
|
|
|
|
//--- Заполняем таблицу значениями из массива, начиная со строки index
|
|
|
|
|
for(int i=index;i<(int)ArrayMagics.Size();i++)
|
|
|
|
|
{
|
|
|
|
|
CTableCell *cell=table.GetCell(i,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//--- невидимые области таблицы не рисуем
|
|
|
|
|
if(cell.X()>panel.CoordX()+panel.Width())
|
|
|
|
|
continue;
|
|
|
|
|
if(cell.Y()>panel.CoordY()+panel.Height())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
//--- выводим данные из массива в ячейки таблицы
|
|
|
|
|
string text=(i<(int)ArrayMagics.Size()-1 ? (string)ArrayMagics[i] : "ALL");
|
|
|
|
|
cell.SetText(text);
|
|
|
|
|
panel.DrawText(cell.Text(),cell.X()+2,cell.Y()+1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Заполняет таблицу заголовков трейдов |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void FillsHeaderTradeTable(CDashboard *panel,CTableData *table)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатели на панель и таблицу
|
|
|
|
|
if(panel==NULL || table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
//--- Заполняем таблицу значениями
|
|
|
|
|
int total=11; // 11 столбцов таблицы
|
|
|
|
|
CTableCell *cell=NULL;
|
|
|
|
|
for(int i=0;i<total;i++)
|
|
|
|
|
{
|
|
|
|
|
//--- Получаем ячейку i таблицы из нулевой (и единственной) строки таблицы
|
|
|
|
|
cell=table.GetCell(0,i);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//--- невидимые области таблицы не рисуем
|
|
|
|
|
if(cell.X()>panel.CoordX()+panel.Width())
|
|
|
|
|
continue;
|
|
|
|
|
if(cell.Y()>panel.CoordY()+panel.Height())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
//--- Записываем наименования заголовков в зависимости от индекса цикла
|
|
|
|
|
string cell_text="";
|
|
|
|
|
switch(i)
|
|
|
|
|
{
|
|
|
|
|
case 0 : cell_text="Time Entry In"; break; // время входа
|
|
|
|
|
case 1 : cell_text="Position ID"; break; // ID позиции
|
|
|
|
|
case 2 : cell_text="Position Type"; break; // покупка или продажа
|
|
|
|
|
case 3 : cell_text="Volume"; break; // объем
|
|
|
|
|
case 4 : cell_text="Symbol"; break; // символ
|
|
|
|
|
case 5 : cell_text="Price Entry In"; break; // цена входа
|
|
|
|
|
case 6 : cell_text="Time Entry Out"; break; // время выхода
|
|
|
|
|
case 7 : cell_text="Price Entry Out"; break; // цена выхода
|
|
|
|
|
case 8 : cell_text="Commission"; break; // комиссия за вход и выход
|
|
|
|
|
case 9 : cell_text="Swap"; break; // своп
|
|
|
|
|
case 10 : cell_text="Profit"; break; // прибыль или убыток
|
|
|
|
|
default : break;
|
|
|
|
|
}
|
|
|
|
|
//--- выводим записи в ячейки таблицы
|
|
|
|
|
cell.SetText(cell_text);
|
|
|
|
|
panel.DrawText(cell.Text(),cell.X()+6,cell.Y()+2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Заполняет таблицу трейдов |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void FillsTradeTable(CDashboard *panel,CTableData *table)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатели на панель и таблицу
|
|
|
|
|
if(panel==NULL || table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//--- Заполняем таблицу значениями из массива
|
|
|
|
|
CTableCell *cell=NULL;
|
|
|
|
|
int total=(int)ArrayTrades.Size();
|
|
|
|
|
if(total==0)
|
|
|
|
|
{
|
|
|
|
|
PrintFormat("%s: Error: Trades array is empty",__FUNCTION__);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Рассчитаем индекс строки, с которой необходимо начать заполнение таблицы
|
|
|
|
|
cell=table.GetCell(0,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
return;
|
|
|
|
|
int y=panel.CoordY()+cell.Y()-2;
|
|
|
|
|
int diff=panel.CoordY()-y;
|
|
|
|
|
int index=diff/CELL_H;
|
|
|
|
|
|
|
|
|
|
//--- В цикле по количеству строк (размер массива трейдов), начиная со строки index
|
|
|
|
|
for(int i=index;i<total;i++)
|
|
|
|
|
{
|
|
|
|
|
//--- в цикле по количеству столбцов (11 для данной таблицы)
|
|
|
|
|
for(int j=0;j<11;j++)
|
|
|
|
|
{
|
|
|
|
|
//--- получаем очередную ячейку таблицы
|
|
|
|
|
cell=table.GetCell(i,j);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//--- невидимые области таблицы не рисуем
|
|
|
|
|
if(cell.X()>panel.CoordX()+panel.Width())
|
|
|
|
|
continue;
|
|
|
|
|
if(cell.Y()>panel.CoordY()+panel.Height())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
//--- Получаем данные таблицы из массива трейдов
|
|
|
|
|
string cell_text="";
|
|
|
|
|
int digits=(int)SymbolInfoInteger(ArrayTrades[i].symbol,SYMBOL_DIGITS);
|
|
|
|
|
switch(j)
|
|
|
|
|
{
|
|
|
|
|
case 0 : cell_text=TimeToString(ArrayTrades[i].time_in); break; // время входа
|
|
|
|
|
case 1 : cell_text=IntegerToString(ArrayTrades[i].ticket); break; // ID позиции
|
|
|
|
|
case 2 : cell_text=(ArrayTrades[i].type==0 ? "Buy" : "Sell"); break; // покупка или продажа
|
|
|
|
|
case 3 : cell_text=DoubleToString(ArrayTrades[i].volume,2); break; // объем
|
|
|
|
|
case 4 : cell_text=ArrayTrades[i].symbol; break; // символ
|
|
|
|
|
case 5 : cell_text=DoubleToString(ArrayTrades[i].price_in,digits); break; // цена входа
|
|
|
|
|
case 6 : cell_text=TimeToString(ArrayTrades[i].time_out); break; // время выхода
|
|
|
|
|
case 7 : cell_text=DoubleToString(ArrayTrades[i].price_out,digits); break; // цена выхода
|
|
|
|
|
case 8 : cell_text=DoubleToString(ArrayTrades[i].commission,2); break; // комиссия за вход и выход
|
|
|
|
|
case 9 : cell_text=DoubleToString(ArrayTrades[i].swap,2); break; // своп
|
|
|
|
|
case 10 : cell_text=DoubleToString(ArrayTrades[i].profit,2); break; // прибыль или убыток
|
|
|
|
|
default : break;
|
|
|
|
|
}
|
|
|
|
|
//--- выводим записи в ячейки таблицы
|
|
|
|
|
cell.SetText(cell_text);
|
|
|
|
|
panel.DrawText(cell.Text(),cell.X()+6,cell.Y()+1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Заполняет таблицу заголовков статистики торговли |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void FillsHeaderTradingStatsTable(CDashboard *panel,CTableData *table)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатели на панель и таблицу
|
|
|
|
|
if(panel==NULL || table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//--- Заполняем таблицу значениями в цикле по количеству столбцов (по размеру данных в ArrayDataName)
|
|
|
|
|
int total=(int)ArrayDataName.Size();
|
|
|
|
|
CTableCell *cell=NULL;
|
|
|
|
|
for(int i=0;i<total;i++)
|
|
|
|
|
{
|
|
|
|
|
//--- получаем очередную ячейку таблицы
|
|
|
|
|
cell=table.GetCell(0,i);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//--- невидимые области таблицы не рисуем
|
|
|
|
|
if(cell.X()>panel.CoordX()+panel.Width())
|
|
|
|
|
continue;
|
|
|
|
|
if(cell.Y()>panel.CoordY()+panel.Height())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
//--- Записываем наименования заголовков в зависимости от индекса цикла
|
|
|
|
|
string cell_text=(i>0 ? ArrayDataName[i] : table.ID()==TABLE_SYMBOLS ? "Symbol" : "Magic");
|
|
|
|
|
//--- выводим записи в ячейки таблицы
|
|
|
|
|
cell.SetText(cell_text);
|
|
|
|
|
panel.DrawText(cell.Text(),cell.X()+6,cell.Y()+2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Заполняет таблицу статистики торговли по символам |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void FillsTradingStatsBySymbolsTable(CDashboard *panel,CTableData *table)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатели на панель и таблицу
|
|
|
|
|
if(panel==NULL || table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//--- Заполняем таблицу значениями из массива
|
|
|
|
|
CTableCell *cell=NULL;
|
|
|
|
|
int total=(int)ArraySymbolStats.Size();
|
|
|
|
|
if(total==0)
|
|
|
|
|
{
|
|
|
|
|
PrintFormat("%s: Error: The array of trading statistics by symbols is empty",__FUNCTION__);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Рассчитаем индекс строки, с которой необходимо начать заполнение таблицы
|
|
|
|
|
cell=table.GetCell(0,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
return;
|
|
|
|
|
int y=panel.CoordY()+cell.Y()-2;
|
|
|
|
|
int diff=panel.CoordY()-y;
|
|
|
|
|
int index=diff/CELL_H;
|
|
|
|
|
|
|
|
|
|
//--- В цикле по количеству строк (размер массива статистики символов), начиная со строки index
|
|
|
|
|
for(int i=index;i<total;i++)
|
|
|
|
|
{
|
|
|
|
|
//--- в цикле по количеству столбцов статистики (массив расположения столбцов таблиц статистики слева-направо)
|
|
|
|
|
for(int j=0;j<(int)ArrayDataName.Size();j++)
|
|
|
|
|
{
|
|
|
|
|
//--- получаем очередную ячейку таблицы
|
|
|
|
|
cell=table.GetCell(i,j);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//--- невидимые области таблицы не рисуем
|
|
|
|
|
if(cell.X()>panel.CoordX()+panel.Width())
|
|
|
|
|
continue;
|
|
|
|
|
if(cell.Y()>panel.CoordY()+panel.Height())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
//--- Получаем данные таблицы из массива структур
|
|
|
|
|
string cell_text="";
|
|
|
|
|
|
|
|
|
|
cell_text=GetDataStatsStr(TABLE_SYMBOLS, ArrayDataName[j],i);
|
|
|
|
|
//--- выводим записи в ячейки таблицы
|
|
|
|
|
cell.SetText(cell_text);
|
|
|
|
|
panel.DrawText(cell.Text(),cell.X()+6,cell.Y()+1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Заполняет таблицу статистики торговли по магикам |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void FillsTradingStatsByMagicsTable(CDashboard *panel,CTableData *table)
|
|
|
|
|
{
|
|
|
|
|
//--- Проверяем указатели на панель и таблицу
|
|
|
|
|
if(panel==NULL || table==NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//--- Заполняем таблицу значениями из массива
|
|
|
|
|
CTableCell *cell=NULL;
|
|
|
|
|
int total=(int)ArrayMagicStats.Size();
|
|
|
|
|
if(total==0)
|
|
|
|
|
{
|
|
|
|
|
PrintFormat("%s: Error: The array of trading statistics by magics is empty",__FUNCTION__);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Рассчитаем индекс строки, с которой необходимо начать заполнение таблицы
|
|
|
|
|
cell=table.GetCell(0,0);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
return;
|
|
|
|
|
int y=panel.CoordY()+cell.Y()-2;
|
|
|
|
|
int diff=panel.CoordY()-y;
|
|
|
|
|
int index=diff/CELL_H;
|
|
|
|
|
|
|
|
|
|
//--- В цикле по количеству строк (размер массива статистики магиков), начиная со строки index
|
|
|
|
|
for(int i=index;i<total;i++)
|
|
|
|
|
{
|
|
|
|
|
//--- в цикле по количеству столбцов статистики (массив расположения столбцов таблиц статистики слева-направо)
|
|
|
|
|
for(int j=0;j<(int)ArrayDataName.Size();j++)
|
|
|
|
|
{
|
|
|
|
|
//--- получаем очередную ячейку таблицы
|
|
|
|
|
cell=table.GetCell(i,j);
|
|
|
|
|
if(cell==NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//--- невидимые области таблицы не рисуем
|
|
|
|
|
if(cell.X()>panel.CoordX()+panel.Width())
|
|
|
|
|
continue;
|
|
|
|
|
if(cell.Y()>panel.CoordY()+panel.Height())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
//--- Получаем данные таблицы из массива структур
|
|
|
|
|
string cell_text=GetDataStatsStr(TABLE_MAGICS, ArrayDataName[j],i);
|
|
|
|
|
//--- выводим записи в ячейки таблицы
|
|
|
|
|
cell.SetText(cell_text);
|
|
|
|
|
panel.DrawText(cell.Text(),cell.X()+6,cell.Y()+1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Возвращает данные из структуры по типу заголовка |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
double GetDataStats(const int table_type, const string data_type, const int index)
|
|
|
|
|
{
|
|
|
|
|
//--- В зависимости от типа данных в таблице возвращаем данные из полей структуры data_type, по индексу массива index
|
|
|
|
|
switch(table_type)
|
|
|
|
|
{
|
|
|
|
|
case TABLE_SYMBOLS :
|
|
|
|
|
return
|
|
|
|
|
(
|
|
|
|
|
data_type==H_TRADES_S ? ArraySymbolStats[index].trades :
|
|
|
|
|
data_type==H_GROSS_PROFIT_S ? ArraySymbolStats[index].gross_profit :
|
|
|
|
|
data_type==H_GROSS_LOSS_S ? ArraySymbolStats[index].gross_loss :
|
|
|
|
|
data_type==H_COMMISSIONS_S ? ArraySymbolStats[index].total_commission :
|
|
|
|
|
data_type==H_SWAPS_S ? ArraySymbolStats[index].total_swap :
|
|
|
|
|
data_type==H_PROFITS_S ? ArraySymbolStats[index].total_profit :
|
|
|
|
|
data_type==H_NET_PROFIT_S ? ArraySymbolStats[index].net_profit :
|
|
|
|
|
data_type==H_WINS_S ? ArraySymbolStats[index].win_trades :
|
|
|
|
|
data_type==H_LOST_S ? ArraySymbolStats[index].loss_trades :
|
|
|
|
|
data_type==H_LONG_S ? ArraySymbolStats[index].long_trades :
|
|
|
|
|
data_type==H_SHORT_S ? ArraySymbolStats[index].short_trades :
|
|
|
|
|
data_type==H_EXP_PAYOFF_S ? ArraySymbolStats[index].expected_payoff :
|
|
|
|
|
data_type==H_WIN_PRC_S ? ArraySymbolStats[index].win_percent :
|
|
|
|
|
data_type==H_LOSS_PRC_S ? ArraySymbolStats[index].loss_percent :
|
|
|
|
|
data_type==H_AVG_PROFIT_S ? ArraySymbolStats[index].average_profit :
|
|
|
|
|
data_type==H_AVG_LOSS_S ? ArraySymbolStats[index].average_loss :
|
|
|
|
|
data_type==H_PRF_FACTOR_S ? ArraySymbolStats[index].profit_factor :
|
|
|
|
|
0
|
|
|
|
|
);
|
|
|
|
|
case TABLE_MAGICS :
|
|
|
|
|
return
|
|
|
|
|
(
|
|
|
|
|
data_type==H_TRADES_S ? ArrayMagicStats[index].trades :
|
|
|
|
|
data_type==H_GROSS_PROFIT_S ? ArrayMagicStats[index].gross_profit :
|
|
|
|
|
data_type==H_GROSS_LOSS_S ? ArrayMagicStats[index].gross_loss :
|
|
|
|
|
data_type==H_COMMISSIONS_S ? ArrayMagicStats[index].total_commission :
|
|
|
|
|
data_type==H_SWAPS_S ? ArrayMagicStats[index].total_swap :
|
|
|
|
|
data_type==H_PROFITS_S ? ArrayMagicStats[index].total_profit :
|
|
|
|
|
data_type==H_NET_PROFIT_S ? ArrayMagicStats[index].net_profit :
|
|
|
|
|
data_type==H_WINS_S ? ArrayMagicStats[index].win_trades :
|
|
|
|
|
data_type==H_LOST_S ? ArrayMagicStats[index].loss_trades :
|
|
|
|
|
data_type==H_LONG_S ? ArrayMagicStats[index].long_trades :
|
|
|
|
|
data_type==H_SHORT_S ? ArrayMagicStats[index].short_trades :
|
|
|
|
|
data_type==H_EXP_PAYOFF_S ? ArrayMagicStats[index].expected_payoff :
|
|
|
|
|
data_type==H_WIN_PRC_S ? ArrayMagicStats[index].win_percent :
|
|
|
|
|
data_type==H_LOSS_PRC_S ? ArrayMagicStats[index].loss_percent :
|
|
|
|
|
data_type==H_AVG_PROFIT_S ? ArrayMagicStats[index].average_profit :
|
|
|
|
|
data_type==H_AVG_LOSS_S ? ArrayMagicStats[index].average_loss :
|
|
|
|
|
data_type==H_PRF_FACTOR_S ? ArrayMagicStats[index].profit_factor :
|
|
|
|
|
0
|
|
|
|
|
);
|
|
|
|
|
case TABLE_ACCOUNT :
|
|
|
|
|
return
|
|
|
|
|
(
|
|
|
|
|
data_type==H_TRADES_S ? ArrayAccountStats[index].trades :
|
|
|
|
|
data_type==H_GROSS_PROFIT_S ? ArrayAccountStats[index].gross_profit :
|
|
|
|
|
data_type==H_GROSS_LOSS_S ? ArrayAccountStats[index].gross_loss :
|
|
|
|
|
data_type==H_COMMISSIONS_S ? ArrayAccountStats[index].total_commission :
|
|
|
|
|
data_type==H_SWAPS_S ? ArrayAccountStats[index].total_swap :
|
|
|
|
|
data_type==H_PROFITS_S ? ArrayAccountStats[index].total_profit :
|
|
|
|
|
data_type==H_NET_PROFIT_S ? ArrayAccountStats[index].net_profit :
|
|
|
|
|
data_type==H_WINS_S ? ArrayAccountStats[index].win_trades :
|
|
|
|
|
data_type==H_LOST_S ? ArrayAccountStats[index].loss_trades :
|
|
|
|
|
data_type==H_LONG_S ? ArrayAccountStats[index].long_trades :
|
|
|
|
|
data_type==H_SHORT_S ? ArrayAccountStats[index].short_trades :
|
|
|
|
|
data_type==H_EXP_PAYOFF_S ? ArrayAccountStats[index].expected_payoff :
|
|
|
|
|
data_type==H_WIN_PRC_S ? ArrayAccountStats[index].win_percent :
|
|
|
|
|
data_type==H_LOSS_PRC_S ? ArrayAccountStats[index].loss_percent :
|
|
|
|
|
data_type==H_AVG_PROFIT_S ? ArrayAccountStats[index].average_profit :
|
|
|
|
|
data_type==H_AVG_LOSS_S ? ArrayAccountStats[index].average_loss :
|
|
|
|
|
data_type==H_PRF_FACTOR_S ? ArrayAccountStats[index].profit_factor :
|
|
|
|
|
0
|
|
|
|
|
);
|
|
|
|
|
default : return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Возвращает данные из структуры по типу заголовка в виде строки |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
string GetDataStatsStr(const int table_type, const string data_type, const int index)
|
|
|
|
|
{
|
|
|
|
|
//--- В зависимости от типа данных, определяем количество знаков после запятой
|
|
|
|
|
//--- (2 - для вещественного свойства и 0 - для целочисленного)
|
|
|
|
|
int digits=(data_type==H_TRADES_S ||
|
|
|
|
|
data_type==H_WINS_S ||
|
|
|
|
|
data_type==H_LOST_S ||
|
|
|
|
|
data_type==H_LONG_S ||
|
|
|
|
|
data_type==H_SHORT_S ? 0 : 2);
|
|
|
|
|
|
|
|
|
|
//--- Если тип данных "Заголовок"
|
|
|
|
|
if(data_type=="HEADER")
|
|
|
|
|
{
|
|
|
|
|
//--- возвращаем наименование в зависимости от типа таблицы (символ, магик, аккаунт)
|
|
|
|
|
switch(table_type)
|
|
|
|
|
{
|
|
|
|
|
case TABLE_SYMBOLS : return ArraySymbolStats[index].name;
|
|
|
|
|
case TABLE_MAGICS : return (string)ArrayMagicStats[index].magic;
|
|
|
|
|
case TABLE_ACCOUNT : return (string)ArrayAccountStats[index].account;
|
|
|
|
|
default : return "Unknown:"+(string)table_type;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//--- Для всех остальных типов данных возвращаем их строковое значение с ранее определённым количеством десятичных знаков
|
|
|
|
|
return(DoubleToString(GetDataStats(table_type, data_type, index),digits));
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Возвращает индекс символа в массиве статистики по символам |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int GetIndexSymbol(const string symbol)
|
|
|
|
|
{
|
|
|
|
|
int total=(int)ArraySymbolStats.Size();
|
|
|
|
|
for(int i=0;i<total;i++)
|
|
|
|
|
{
|
|
|
|
|
if(ArraySymbolStats[i].name==symbol)
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Возвращает индекс магика в массиве статистики по магикам |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int GetIndexMagic(const long magic)
|
|
|
|
|
{
|
|
|
|
|
int total=(int)ArrayMagicStats.Size();
|
|
|
|
|
for(int i=0;i<total;i++)
|
|
|
|
|
{
|
|
|
|
|
if(ArrayMagicStats[i].magic==magic)
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
return WRONG_VALUE;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Отображает статистику по выбранному символу, магику или счёту |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool ViewStatistic(const int table_type,const string cell_text)
|
|
|
|
|
{
|
|
|
|
|
//--- Получаем указатели на панель заголовков и правую панель для вывода статистики
|
|
|
|
|
CDashboard *panel_h=dashboard.GetPanel("FieldH");
|
|
|
|
|
CDashboard *panel_r=dashboard.GetPanel("FieldR");
|
|
|
|
|
if(panel_h==NULL || panel_r==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//--- Определяем источник статистических данных (символ/магик/аккаунт)
|
|
|
|
|
string source=(table_type==TABLE_SYMBOLS ? "symbol" : table_type==TABLE_MAGICS ? "magic" : "account");
|
|
|
|
|
int index=WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
//--- В зависимости от текста в выбранной ячейке таблицы (cell_text), переданному в функцию,
|
|
|
|
|
//--- получаем индекс, по которому содержатся данные в соответствующем массиве статистики
|
|
|
|
|
switch(table_type)
|
|
|
|
|
{
|
|
|
|
|
case TABLE_SYMBOLS: index=GetIndexSymbol(cell_text); break;
|
|
|
|
|
case TABLE_MAGICS : index=GetIndexMagic(StringToInteger(cell_text)); break;
|
|
|
|
|
case TABLE_ACCOUNT: index=(ArrayAccountStats.Size()==1 ? 0 : -1); break;
|
|
|
|
|
default : break;
|
|
|
|
|
}
|
|
|
|
|
//--- Если индекс получить не удалось, считаем, что соответствующий массив статистики пуст
|
|
|
|
|
if(index==WRONG_VALUE)
|
|
|
|
|
{
|
|
|
|
|
PrintFormat("%s: Error. Empty array of %s statistics",__FUNCTION__,source);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Получим и сохраним установленные для панели заголовков свойства шрифта
|
|
|
|
|
int f_size;
|
|
|
|
|
uint f_flags,f_angle;
|
|
|
|
|
string f_name=panel_h.FontParams(f_size,f_flags,f_angle);
|
|
|
|
|
|
|
|
|
|
//--- Очищаем панель заголовков и выводим на неё описание выбранных данных шрифтом Tahoma размером 8
|
|
|
|
|
panel_h.Clear();
|
|
|
|
|
panel_h.SetFontParams("Tahoma",8,f_flags,f_angle);
|
|
|
|
|
panel_h.DrawText(StringFormat("Trade statistics by %s %s",source,cell_text),8,3,C'150,150,150');
|
|
|
|
|
//--- Возвращаем шрифту панели заголовков прежние сохранённые свойства
|
|
|
|
|
panel_h.SetFontParams(f_name,f_size,f_flags,f_angle);
|
|
|
|
|
|
|
|
|
|
//--- Проверяем наличие и получаем или создаём объект-таблицу для вывода статистики на правой панели
|
|
|
|
|
if(!panel_r.TableIsExist(TABLE_STATS) && !panel_r.CreateNewTable(TABLE_STATS))
|
|
|
|
|
return false;
|
|
|
|
|
//--- Получаем указатель на созданную таблицу
|
|
|
|
|
CTableData *table_r=panel_r.GetTable(TABLE_STATS);
|
|
|
|
|
if(table_r==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//--- Очищаем правую панель и рисуем на ней таблицу
|
|
|
|
|
panel_r.Clear();
|
|
|
|
|
panel_r.DrawGrid(TABLE_STATS,2,2,TABLE_STAT_ROWS,TABLE_STAT_COLS,(panel_r.Height()-4)/TABLE_STAT_ROWS,(panel_r.Width()-4)/TABLE_STAT_COLS,C'230,230,230',false);
|
|
|
|
|
|
|
|
|
|
//--- Объявляем структуру для хранения данных статистики
|
|
|
|
|
//--- (символ/магик/аккаунт) по ранее полученному индексу данных.
|
|
|
|
|
//--- Все поля структур SSymbolStats, SMagicStats и SAccountStats одинаковы,
|
|
|
|
|
//--- кроме первого поля с наименованием символа, значением магика или номером счёта.
|
|
|
|
|
//--- Т.к. первое поле здесь не нужно, поэтому здесь достаточно любого типа структуры из трёх.
|
|
|
|
|
//--- Заполняем объявленную структуру данными в зависимости от выбранного источника
|
|
|
|
|
SSymbolStats stats={};
|
|
|
|
|
switch(table_type)
|
|
|
|
|
{
|
|
|
|
|
case TABLE_SYMBOLS:
|
|
|
|
|
stats.trades = ArraySymbolStats[index].trades;
|
|
|
|
|
stats.gross_profit = ArraySymbolStats[index].gross_profit;
|
|
|
|
|
stats.gross_loss = ArraySymbolStats[index].gross_loss;
|
|
|
|
|
stats.total_commission= ArraySymbolStats[index].total_commission;
|
|
|
|
|
stats.total_swap = ArraySymbolStats[index].total_swap;
|
|
|
|
|
stats.total_profit = ArraySymbolStats[index].total_profit;
|
|
|
|
|
stats.net_profit = ArraySymbolStats[index].net_profit;
|
|
|
|
|
stats.win_trades = ArraySymbolStats[index].win_trades;
|
|
|
|
|
stats.loss_trades = ArraySymbolStats[index].loss_trades;
|
|
|
|
|
stats.long_trades = ArraySymbolStats[index].long_trades;
|
|
|
|
|
stats.short_trades = ArraySymbolStats[index].short_trades;
|
|
|
|
|
stats.expected_payoff = ArraySymbolStats[index].expected_payoff;
|
|
|
|
|
stats.win_percent = ArraySymbolStats[index].win_percent;
|
|
|
|
|
stats.loss_percent = ArraySymbolStats[index].loss_percent;
|
|
|
|
|
stats.average_profit = ArraySymbolStats[index].average_profit;
|
|
|
|
|
stats.average_loss = ArraySymbolStats[index].average_loss;
|
|
|
|
|
stats.profit_factor = ArraySymbolStats[index].profit_factor;
|
|
|
|
|
break;
|
|
|
|
|
case TABLE_MAGICS :
|
|
|
|
|
stats.trades = ArrayMagicStats[index].trades;
|
|
|
|
|
stats.gross_profit = ArrayMagicStats[index].gross_profit;
|
|
|
|
|
stats.gross_loss = ArrayMagicStats[index].gross_loss;
|
|
|
|
|
stats.total_commission= ArrayMagicStats[index].total_commission;
|
|
|
|
|
stats.total_swap = ArrayMagicStats[index].total_swap;
|
|
|
|
|
stats.total_profit = ArrayMagicStats[index].total_profit;
|
|
|
|
|
stats.net_profit = ArrayMagicStats[index].net_profit;
|
|
|
|
|
stats.win_trades = ArrayMagicStats[index].win_trades;
|
|
|
|
|
stats.loss_trades = ArrayMagicStats[index].loss_trades;
|
|
|
|
|
stats.long_trades = ArrayMagicStats[index].long_trades;
|
|
|
|
|
stats.short_trades = ArrayMagicStats[index].short_trades;
|
|
|
|
|
stats.expected_payoff = ArrayMagicStats[index].expected_payoff;
|
|
|
|
|
stats.win_percent = ArrayMagicStats[index].win_percent;
|
|
|
|
|
stats.loss_percent = ArrayMagicStats[index].loss_percent;
|
|
|
|
|
stats.average_profit = ArrayMagicStats[index].average_profit;
|
|
|
|
|
stats.average_loss = ArrayMagicStats[index].average_loss;
|
|
|
|
|
stats.profit_factor = ArrayMagicStats[index].profit_factor;
|
|
|
|
|
break;
|
|
|
|
|
case TABLE_ACCOUNT:
|
|
|
|
|
stats.trades = ArrayAccountStats[index].trades;
|
|
|
|
|
stats.gross_profit = ArrayAccountStats[index].gross_profit;
|
|
|
|
|
stats.gross_loss = ArrayAccountStats[index].gross_loss;
|
|
|
|
|
stats.total_commission= ArrayAccountStats[index].total_commission;
|
|
|
|
|
stats.total_swap = ArrayAccountStats[index].total_swap;
|
|
|
|
|
stats.total_profit = ArrayAccountStats[index].total_profit;
|
|
|
|
|
stats.net_profit = ArrayAccountStats[index].net_profit;
|
|
|
|
|
stats.win_trades = ArrayAccountStats[index].win_trades;
|
|
|
|
|
stats.loss_trades = ArrayAccountStats[index].loss_trades;
|
|
|
|
|
stats.long_trades = ArrayAccountStats[index].long_trades;
|
|
|
|
|
stats.short_trades = ArrayAccountStats[index].short_trades;
|
|
|
|
|
stats.expected_payoff = ArrayAccountStats[index].expected_payoff;
|
|
|
|
|
stats.win_percent = ArrayAccountStats[index].win_percent;
|
|
|
|
|
stats.loss_percent = ArrayAccountStats[index].loss_percent;
|
|
|
|
|
stats.average_profit = ArrayAccountStats[index].average_profit;
|
|
|
|
|
stats.average_loss = ArrayAccountStats[index].average_loss;
|
|
|
|
|
stats.profit_factor = ArrayAccountStats[index].profit_factor;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Получим и сохраним установленные для правой панели свойства шрифта
|
|
|
|
|
f_name=panel_r.FontParams(f_size,f_flags,f_angle);
|
|
|
|
|
//--- Устанавливаем для правой панели новый шрифт Tahoma размером 8
|
|
|
|
|
panel_r.SetFontParams("Tahoma",8,FW_BLACK,f_angle);
|
|
|
|
|
|
|
|
|
|
//--- Переменные для расчёта места расположения текста в ячейке таблицы
|
|
|
|
|
CTableCell *cellH=NULL, *cellV=NULL;
|
|
|
|
|
int cols=table_r.ColumnsInRow(0); // количество столбцов таблицы статистики
|
|
|
|
|
int cw=table_r.Width()/cols; // ширина одного столбца таблицы
|
|
|
|
|
int y_shift=6; // смещение текста по высоте
|
|
|
|
|
int x_shift=21; // смещение текста по ширине
|
|
|
|
|
int tw=0; // ширина текста
|
|
|
|
|
string text="";
|
|
|
|
|
double value=0;
|
|
|
|
|
|
|
|
|
|
//--- Левый столбец (данные -- значение)
|
|
|
|
|
//--- Получаем ячейки 0,0 и 0,1 таблицы и выводим в их координаты Trades и его значение
|
|
|
|
|
cellH=table_r.GetCell(0,0);
|
|
|
|
|
cellV=table_r.GetCell(0,1);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
text=(string)stats.trades;
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_TRADES+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,C'150,150,150');
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 1,0 и 1,1 таблицы и выводим в их координаты Long и его значение
|
|
|
|
|
cellH=table_r.GetCell(1,0);
|
|
|
|
|
cellV=table_r.GetCell(1,1);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
text=(string)stats.long_trades;
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_LONG+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,C'150,150,150');
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 2,0 и 2,1 таблицы и выводим в их координаты Short и его значение
|
|
|
|
|
cellH=table_r.GetCell(2,0);
|
|
|
|
|
cellV=table_r.GetCell(2,1);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
text=(string)stats.short_trades;
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_SHORT+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,C'150,150,150');
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 3,0 и 3,1 таблицы и выводим в их координаты Net Profit и его значение
|
|
|
|
|
cellH=table_r.GetCell(3,0);
|
|
|
|
|
cellV=table_r.GetCell(3,1);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.net_profit;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_NET_PROFIT+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,(value>0 ? C'86,119,204' : value<0 ? C'234,50,50' : C'150,150,150'));
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 4,0 и 4,1 таблицы и выводим в их координаты Profit Loss и его значение
|
|
|
|
|
cellH=table_r.GetCell(4,0);
|
|
|
|
|
cellV=table_r.GetCell(4,1);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.total_profit;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_PROFITS+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,(value>0 ? C'86,119,204' : value<0 ? C'234,50,50' : C'150,150,150'));
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 5,0 и 5,1 таблицы и выводим в их координаты Gross Profit и его значение
|
|
|
|
|
cellH=table_r.GetCell(5,0);
|
|
|
|
|
cellV=table_r.GetCell(5,1);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.gross_profit;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_GROSS_PROFIT+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,(value>0 ? C'86,119,204' : C'150,150,150'));
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 6,0 и 6,1 таблицы и выводим в их координаты Gross Loss и его значение
|
|
|
|
|
cellH=table_r.GetCell(6,0);
|
|
|
|
|
cellV=table_r.GetCell(6,1);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.gross_loss;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_GROSS_LOSS+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,(value<0 ? C'234,50,50' : C'150,150,150'));
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 7,0 и 7,1 таблицы и выводим в их координаты Commission total и его значение
|
|
|
|
|
cellH=table_r.GetCell(7,0);
|
|
|
|
|
cellV=table_r.GetCell(7,1);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.total_commission;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_COMMISSIONS+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,(value<0 ? C'234,50,50' : C'150,150,150'));
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 8,0 и 8,1 таблицы и выводим в их координаты Swap total и его значение
|
|
|
|
|
cellH=table_r.GetCell(8,0);
|
|
|
|
|
cellV=table_r.GetCell(8,1);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.total_swap;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_SWAPS+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,(value<0 ? C'234,50,50' : C'150,150,150'));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- Правый столбец (данные -- значение)
|
|
|
|
|
//--- Получаем ячейки 0,2 и 0,3 таблицы и выводим в их координаты Win trades и его значение
|
|
|
|
|
cellH=table_r.GetCell(0,2);
|
|
|
|
|
cellV=table_r.GetCell(0,3);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
text=(string)stats.win_trades;
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_WINS+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,C'150,150,150');
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 1,2 и 1,3 таблицы и выводим в их координаты Loss trades и его значение
|
|
|
|
|
cellH=table_r.GetCell(1,2);
|
|
|
|
|
cellV=table_r.GetCell(1,3);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
text=(string)stats.loss_trades;
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_LOST+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,C'150,150,150');
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 2,2 и 2,3 таблицы и выводим в их координаты Expected Payoff и его значение
|
|
|
|
|
cellH=table_r.GetCell(2,2);
|
|
|
|
|
cellV=table_r.GetCell(2,3);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.expected_payoff;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_EXP_PAYOFF+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,C'150,150,150');
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 3,2 и 3,3 таблицы и выводим в их координаты Win percent и его значение
|
|
|
|
|
cellH=table_r.GetCell(3,2);
|
|
|
|
|
cellV=table_r.GetCell(3,3);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.win_percent;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_WIN_PRC+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,C'86,119,204');
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 4,2 и 4,3 таблицы и выводим в их координаты Loss percent и его значение
|
|
|
|
|
cellH=table_r.GetCell(4,2);
|
|
|
|
|
cellV=table_r.GetCell(4,3);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.loss_percent;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_LOSS_PRC+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,C'234,50,50');
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 5,2 и 5,3 таблицы и выводим в их координаты Average Profit и его значение
|
|
|
|
|
cellH=table_r.GetCell(5,2);
|
|
|
|
|
cellV=table_r.GetCell(5,3);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.average_profit;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_AVG_PROFIT+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,(value>0 ? C'86,119,204' : C'150,150,150'));
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 6,2 и 6,3 таблицы и выводим в их координаты Average Loss и его значение
|
|
|
|
|
cellH=table_r.GetCell(6,2);
|
|
|
|
|
cellV=table_r.GetCell(6,3);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.average_loss;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_AVG_LOSS+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,(value<0 ? C'234,50,50' : C'150,150,150'));
|
|
|
|
|
|
|
|
|
|
//--- Получаем ячейки 7,2 и 7,3 таблицы и выводим в их координаты Profit factor и его значение
|
|
|
|
|
cellH=table_r.GetCell(7,2);
|
|
|
|
|
cellV=table_r.GetCell(7,3);
|
|
|
|
|
if(cellH==NULL || cellV==NULL)
|
|
|
|
|
return false;
|
|
|
|
|
value=stats.profit_factor;
|
|
|
|
|
text=DoubleToString(value,2);
|
|
|
|
|
tw=panel_r.TextWidth(text);
|
|
|
|
|
panel_r.DrawText(H_PRF_FACTOR+":",cellH.X()+x_shift,cellH.Y()+y_shift,C'150,150,150');
|
|
|
|
|
panel_r.DrawText(text,cellV.X()+cw-tw-x_shift,cellV.Y()+y_shift,C'150,150,150');
|
2026-03-23 15:25:14 +07:00
|
|
|
|
2026-03-23 15:33:27 +07:00
|
|
|
//--- Возвращаем шрифту правой панели прежние сохранённые свойства
|
|
|
|
|
panel_r.SetFontParams(f_name,f_size,f_flags,f_angle);
|
|
|
|
|
return true;
|
2026-03-23 15:25:14 +07:00
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|