Не так давно я впервые создал и поделился с вами способом создания торговой панели на основе графических объектов. Топик назывался "
Панель управления на MQL4 это просто!"
Сейчас я хочу предложить более трудозатратный но намного более интересный способ написания торговой панели. В основу легла статья
СОЗДАЕМ ПОМОЩНИКА В РУЧНОЙ ТОРГОВЛЕ. Я немного переделал этот урок для терминала МТ4.
На нашей панели будет 3 кнопки, метка и поле для редактирования и выглядеть она будет следующим образом:
Первым делом создадим следующую заготовку на базе класса
CAppDialog.
//+------------------------------------------------------------------+
//| Panelka.mq4 |
//| Copyright 2016, AM2 |
//| http://www.forexsystems.biz |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, AM2"
#property link "http://www.forexsystems.biz"
#property version "1.00"
#property strict
#include <Controls\Dialog.mqh>
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CTradePanel : public CAppDialog
{
public:
CTradePanel(void){};
~CTradePanel(void){};
};
CTradePanel TradePanel;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
// Create Trade Panel
// Create Trade Panel
TradePanel.Create(ChartID(),"Panelka",0,20,20,150,200);
// Run Trade Panel
TradePanel.Run();
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
}
//+------------------------------------------------------------------+
Выглядеть она будет так:
Чтобы нанести на панель необходимые нам элементы, создадим объекты соответствующих классов.
Добавляем необходимые включаемые файлы и создаем функцию Creat() для класса
CTradePanel:
#include <Controls\Dialog.mqh>
#include <Controls\Label.mqh>
#include <Controls\Button.mqh>
Для каждого объекта на панели в классе
CTradePanel объявляем переменные соответствующего типа, и там же объявляем процедуру Creat(..), в которой и расставим все элементы по своим местам. Обратите внимание: объявление переменных и другие действия внутри класса
CTradePanel мы объявляем в блоке «private». Функции же, доступные для вызова из-за пределов класса, такие как Creat(...), объявляются в блоке «public».
class CTradePanel : public CAppDialog
{
private:
CLabel Lots_label; // Display label " Lots"
CEdit Lots; // Display volume of next order
CButton SELL,BUY; // Sell and Buy Buttons
CButton CloseAll; // Close buttons
public:
CTradePanel(void){};
~CTradePanel(void){};
virtual bool Create(const long chart,const string name,const int subwin=0,const int x1=20,const int y1=20,const int x2=320,const int y2=420);
};
Создадим функции для отбражения наших элементов на панели:
Класс
CLabel мы будем использовать для отображения информационного текста на нашей панели.
bool CTradePanel::CreateLabel(const long chart,const int subwindow,CLabel &object,const string text,const uint x,const uint y,label_align align)
{
// All objects must have separate name
string name=m_name+"Label"+(string)ObjectsTotal(chart,-1,OBJ_LABEL);
//--- Call Create function
if(!object.Create(chart,name,subwindow,x,y,0,0))
{
return false;
}
//--- Adjust text
if(!object.Text(text))
{
return false;
}
//--- Align text to Dialog box's grid
ObjectSetInteger(chart,object.Name(),OBJPROP_ANCHOR,(align==left ? ANCHOR_LEFT_UPPER <img src='http://opentraders.ru/templates/skin/g6h/images/smilies/005.gif' alt=' ( '> align==right ? ANCHOR_RIGHT_UPPER : ANCHOR_UPPER)));
//--- Add object to controls
if(!Add(object))
{
return false;
}
return true;
}
Класс
CButton предназначен для создания кнопок прямоугольной формы с надписью. Это наши стандартные кнопки открытия и закрытия ордеров.
bool CTradePanel::CreateButton(const long chart,const int subwindow,CButton &object,const string text,const uint x,const uint y,const uint x_size,const uint y_size)
{
// All objects must have separate name
string name=m_name+"Button"+(string)ObjectsTotal(chart,-1,OBJ_BUTTON);
//--- Call Create function
if(!object.Create(chart,name,subwindow,x,y,x+x_size,y+y_size))
{
return false;
}
//--- Adjust text
if(!object.Text(text))
{
return false;
}
//--- set button flag to unlock
object.Locking(false);
//--- set button flag to unpressed
if(!object.Pressed(false))
{
return false;
}
//--- Add object to controls
if(!Add(object))
{
return false;
}
return true;
}
Класс
CEdit предназначен для создания объектов ввода данных.
bool CTradePanel::CreateEdit(const long chart,const int subwindow,CEdit &object,const string text,const uint x,const uint y,const uint x_size,const uint y_size)
{
// All objects must have separate name
string name=m_name+"Edit"+(string)ObjectsTotal(chart,-1,OBJ_EDIT);
//--- Call Create function
if(!object.Create(chart,name,subwindow,x,y,x+x_size,y+y_size))
{
return false;
}
//--- Adjust text
if(!object.Text(text))
{
return false;
}
//--- Align text in Edit box
if(!object.TextAlign(ALIGN_CENTER))
{
return false;
}
//--- set Read only flag to false
if(!object.ReadOnly(false))
{
return false;
}
//--- Add object to controls
if(!Add(object))
{
return false;
}
return true;
}
Объявим эти функции в блоке «private» нашего класса.
private:
//--- Create Label object
bool CreateLabel(const long chart,const int subwindow,CLabel &object,const string text,const uint x,const uint y,label_align align);
//--- Create Button
bool CreateButton(const long chart,const int subwindow,CButton &object,const string text,const uint x,const uint y,const uint x_size,const uint y_size);
//--- Create Edit object
bool CreateEdit(const long chart,const int subwindow,CEdit &object,const string text,const uint x,const uint y,const uint x_size,const uint y_size);
//--- Create BMP Button
bool CreateBmpButton(const long chart,const int subwindow,CBmpButton &object,const uint x,const uint y,string BmpON,string BmpOFF,bool lock);
Теперь напишем функцию, которая создаст все элементы на панели:
bool CTradePanel::Create(const long chart,const string name,const int subwin=0,const int x1=20,const int y1=20,const int x2=320,const int y2=420)
{
// At first call create function of parents class
CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2);
// Calculate coordinates and size of BID object
// Create object
CreateLabel(chart,subwin,Lots_label,"LOT",55,5,0);
CreateEdit(chart,subwin,Lots,"0.1",33,35,60,20);
CreateButton(chart,subwin,BUY,"BUY",33,65,60,20);
CreateButton(chart,subwin,SELL,"SELL",33,95,60,20);
CreateButton(chart,subwin,CloseAll,"CLOSE",33,125,60,20);
return(true);
}
События от нажатия кнопок обрабатываются функцией
OnChartEvent.
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//---
TradePanel.OnEvent(id, lparam, dparam, sparam);
}
Пропишем ее в родительском классе:
public:
virtual bool OnEvent(const int id,const long &lparam, const double &dparam, const string &sparam);
Создадим диспетчер для вызова функций с макроподстановками:
//+------------------------------------------------------------------+
//| Event Handling |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CTradePanel)
ON_EVENT(ON_END_EDIT,Lots,LotsEndEdit)
ON_EVENT(ON_CLICK,BUY,BuyClick)
ON_EVENT(ON_CLICK,SELL,SellClick)
ON_EVENT(ON_CLICK,CloseAll,CloseClick)
EVENT_MAP_END(CAppDialog)
Соответственно, все функции обработки событий мы должны объявить в блоке «private» нашего класса
private:
//--- On Event functions
void LotsEndEdit(void); // Edit Lot size
//--- variables of current values
double cur_lot; // Lot of next order
void BuyClick(); // Click BUY button
void SellClick(); // Click SELL button
void CloseClick(); // Click CLOSE button
Сами фцнкции обработкки событий будут выглядеть так:
//+------------------------------------------------------------------+
//| Click BUY button |
//+------------------------------------------------------------------+
void CTradePanel::BuyClick(void)
{
PutOrder(0,Ask);
}
//+------------------------------------------------------------------+
//| Click SELL button |
//+------------------------------------------------------------------+
void CTradePanel::SellClick(void)
{
PutOrder(1,Bid);
}
//+------------------------------------------------------------------+
//| Click CLOSE button |
//+------------------------------------------------------------------+
void CTradePanel::CloseClick(void)
{
CloseAll();
}
Для торговых операций воспользуемся заготовленными заранее функциями:
//+------------------------------------------------------------------+
//| Установка ордера |
//+------------------------------------------------------------------+
void PutOrder(int type,double price)
{
int r=0;
color clr=Green;
double sl=0,tp=0;
if(type==1 || type==3 || type==5)
{
clr=Red;
if(StopLoss>0) sl=NormalizeDouble(price+StopLoss*Point,Digits);
if(TakeProfit>0) tp=NormalizeDouble(price-TakeProfit*Point,Digits);
}
if(type==0 || type==2 || type==4)
{
clr=Blue;
if(StopLoss>0) sl=NormalizeDouble(price-StopLoss*Point,Digits);
if(TakeProfit>0) tp=NormalizeDouble(price+TakeProfit*Point,Digits);
}
r=OrderSend(NULL,type,Lot,NormalizeDouble(price,Digits),Slip,sl,tp,"",Magic,0,clr);
return;
}
//+------------------------------------------------------------------+
//| Закрытие позиции по типу ордера |
//+------------------------------------------------------------------+
void CloseAll(int ot=-1)
{
bool cl;
for(int i=OrdersTotal()-1;i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
{
if(OrderType()==0 && (ot==0 || ot==-1))
{
RefreshRates();
cl=OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),Slip,White);
}
if(OrderType()==1 && (ot==1 || ot==-1))
{
RefreshRates();
cl=OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),Slip,White);
}
}
}
}
}
При деинициализации программы генерируется событие
Deinit, которое вызывает функцию
OnDeinit с указанием причины деинициализации. Следовательно, из указанной функции основной программы мы должны вызвать функцию деинициализации нашего класса:
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
TradePanel.Destroy(reason);
return;
}
Эту функцию мы должны объявить в блоке public нашего класса:
public:
.............
virtual void Destroy(const int reason);
В теле этой функции вызовем функцию деинициализации родительского класса и удалим объекты торговой панели с графика.
//+------------------------------------------------------------------+
//| Application deinitialization function |
//+------------------------------------------------------------------+
void CTradePanel:<img src='http://opentraders.ru/templates/skin/g6h/images/smilies/003.gif' alt=' :D '> estroy(const int reason)
{
CAppDialog:<img src='http://opentraders.ru/templates/skin/g6h/images/smilies/003.gif' alt=' :D '> estroy(reason);
return;
}
И наконец пропишем входные переменные для советника:
extern double Lot = 0.1; // лот
extern int StopLoss = 500; // лось
extern int TakeProfit = 500; // язь
extern int Slip = 30; // реквот
extern int Magic = 0; // магик
На этом все и сейчас посмотрит результат работы нашей панели.
Нажимает кнопку бай:
Жмем клоуз, закрылись:
Более подробный урок можете посмотреть по ссылке выше. Если у кого есть какие то вопросы спрашивайте
Скачать советник:
www.opentraders.ru/downloads/1209/
Комментарии (24)
27 Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
35 AM2 Автор Сообщений: 16445 - Андрей
Каждый класс со своими функциями отдельным файлом. К ним только обращаться и расширять их, может быть изменять, но не залезая к ним внутрь. (в этом их и суть)
27 Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
35 AM2 Автор Сообщений: 16445 - Андрей
27 Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
1 ZeleBoba Сообщений: 7
19 Kashtan Сообщений: 739 - Игорь
7 Vitalik5675 Сообщений: 282
Там три файла:
Вот так выглядит:
27 Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
35 AM2 Автор Сообщений: 16445 - Андрей
А индикатор панель такую же строит?
27 Oxy Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
Если это конечно актуально спустя столько лет.
Или может это вовсе не то.
20 alex30774 Сообщений: 778
35 AM2 Автор Сообщений: 16445 - Андрей
Дело в том, что когда я добавляю другие кнопки в панель, то они не перемещаются вместе с панелью а висят на одном месте, тоже самое при закрытии панели
А еще не работает переключение лотности, когда другой лот вбиваю, открывается всегда одним и тем же.
Ах да еще вопрос хотел, еще одну панель такую же рядом, с другим набором кнопок, но они чего то конфликтуют, хотя не должны.
И на масое главное, какая функция отвечает за перетаскивание панели по графику?
Наверное надо код приложить и скрин я чуть поздне добавлю. Редактирован: 13 ноября 2016, 16:30
16 cerber04 Сообщений: 409
35 AM2 Автор Сообщений: 16445 - Андрей
35 AM2 Автор Сообщений: 16445 - Андрей
Ваш вариант работает на реальных графиках, но на тестере события не срабатывают. ((
Почему?
1 ZeleBoba Сообщений: 7
и подключить к ней нужный скрипт из папки ...\MQL4\Scripts?
Так, чтобы скрипт срабатывал при нажатии на эту кнопку.
11 preasto Сообщений: 445
35 AM2 Автор Сообщений: 16445 - Андрей
чтобы при нажатии на неё запускался указанный отдельный(внешний) скрипт из папки ...\MQL4\Scripts.
(а не заданный(внесённый как функция) из кода самой панельки). Редактирован: 29 декабря 2016, 15:30
11 preasto Сообщений: 445
MT4 Build 1090.
0 lova Сообщений: 1
Только что испытал)))
Вот как надо:
Вот как при переключении таймфреймов:
Всё работает, всё нормально, но при переключении ТФ реально рассыпается)))
Короче, беда с этой библиотекой, при перходе из ТФ в ТФ множит объекты как из пулемёта, в чём можно убедиться, посмотрев кол-во объектов на графике.
Увы, вот самый приемлемый вариант, через указатель:
При таком раскладе объекты множатся друг под другом, не в рассыпную, а на изначально заданных координатах. Редактирован: 17 июля 2019, 19:15
24 ShamanHand Сообщений: 1092 - Наношу добро, причиняю пользу.
Кода меньше, всё понятней.
24 ShamanHand Сообщений: 1092 - Наношу добро, причиняю пользу.
4 qorqis Сообщений: 20
Зарегистрируйтесь или авторизуйтесь, чтобы оставить комментарий