Jump to content
RickD

MQL-4: некоторые полезные функции

Recommended Posts

RickD

Получить количество ордеров (рыночных либо отложенных) данного типа.

 

int OrdersCount(int type)
{
 int orders = 0;

 int cnt = OrdersTotal();
 for (int i=0; i<cnt; i++) {
   if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;

   //По желанию
   //if (OrderSymbol() != Symbol()) continue;

   //По желанию
   //if (OrderMagicNumber() != Magic) continue;

   if (OrderType() == type) orders++;
 }

 return (orders);
}

 

В эксперте эту функцию можно использовать следующим образом:

 

int start() 
{
 int BuyCnt = OrdersCount(OP_BUY);
 if (BuyCnt > 0) return (0);
 ...

  • Thanks 1

MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
RickD

Закрыть все ордера:

 

void CloseOrders() 
{
 int cnt = OrdersTotal();
 for (int i=cnt-1; i>=0; i--) {
   if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;

   //По желанию
   //if (OrderSymbol() != Symbol()) continue;

   //По желанию
   //if (OrderMagicNumber() != Magic) continue;

   if (OrderType() == OP_BUY) OrderClose(OrderTicket(), OrderLots(), Bid, Slippage);
   if (OrderType() == OP_SELL) OrderClose(OrderTicket(), OrderLots(), Ask, Slippage);
 }
}

 

Закрыть все ордера данного типа:

 

void CloseOrders(int type) 
{
 int cnt = OrdersTotal();
 for (int i=cnt-1; i>=0; i--) {
   if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;

   //По желанию
   //if (OrderSymbol() != Symbol()) continue;

   //По желанию
   //if (OrderMagicNumber() != Magic) continue;

   if (OrderType() != type) continue;

   if (type == OP_BUY) OrderClose(OrderTicket(), OrderLots(), Bid, Slippage);
   if (type == OP_SELL) OrderClose(OrderTicket(), OrderLots(), Ask, Slippage);
 }
}

 

Slippage - допустимое проскальзывание в пунктах.


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
RickD

Удалить все отложенные ордера данного типа:

 

void DeleteOrders(int type) 
{
 int cnt = OrdersTotal();
 for (int i=cnt-1; i>=0; i--) {
   if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
   //По желанию
   //if (OrderSymbol() != Symbol()) continue;
   //По желанию
   //if (OrderMagicNumber() != Magic) continue;

   if (OrderType() != type) continue;

   if (type == OP_BUYSTOP || type == OP_SELLSTOP) OrderDelete(OrderTicket());
   if (type == OP_BUYLIMIT || type == OP_SELLLIMIT) OrderDelete(OrderTicket());    
 }
}


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
RickD

Получить время открытия последнего ордера данного типа.

Смотрим в открытых ордерах и в истории.

Если не найдено ордеров, удовлетворяющих условиям поиска, возвращаем -1.

 

datetime GetLastOpenTime(int type) {

 datetime tm = -1;

 int cnt = OrdersTotal();
 for (int i=0; i<cnt; i++) {
   if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;

   //Опционально
   if (OrderSymbol() != Symbol()) continue;
   if (OrderMagicNumber() != Magic) continue;

   if (OrderType() != type) continue;

   tm = MathMax(tm, OrderOpenTime());
 }

 cnt = HistoryTotal();
 for (i=0; i<cnt; i++) {
   if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;

   //Опционально
   if (OrderSymbol() != Symbol()) continue;
   if (OrderMagicNumber() != Magic) continue;

   if (OrderType() != type) continue;

   tm = MathMax(tm, OrderOpenTime());
 }

 return (tm);
}


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
RickD

Польза от функции GetLastOpenTime такая.

Например мы не хотим открывать лонг-ордера чаще чем раз в 2 часа.

Тогда условие на открытие будет выглядеть так:

 

if (CurTime() - GetLastOpenTime(OP_BUY) >= 2*60*60) {
  OrderSend(Symbol(), OP_BUY, ...
}


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
Massaraksh

Получить дату следующего дня:

void NextDay(int &d,int &m,int &y)
{
int mx[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int plus=0;
if (TimeDayOfWeek(StrToTime(y+"."+m+"."+d))==5)plus=2;
if((y%4)==0)mx[1]++;d++;d+=plus;if(d>mx[m-1]){d=d-mx[m-1];m++;if(m>12){m=1;y++;}}
}


С уважением.

Share this post


Link to post
Share on other sites
RickD
Получить дату следующего дня:

 

А такой вариант не пойдет?

 

 datetime Time0 = CurTime();
 datetime Tomorrow = Time0 + 24*60*60;
 int day = TimeDayOfYear(Tomorrow);
 int month = TimeMonth(Tomorrow);
 int year = TimeYear(Tomorrow);


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
Massaraksh

Еще надо учесть субботу и воскресенье. Точнее, их отсутствие.


С уважением.

Share this post


Link to post
Share on other sites
RickD
Еще надо учесть субботу и воскресенье. Точнее, их отсутствие.

 

Не совсем понятно чем суббота и воскресенье не угодили. :)


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
RickD

Получить тикет последнего закрытого ордера из истории.

Если тип ордера не указан, берется самый последний ордер любого типа.

Если ордеров, отвечающих указанным критерию не найдено, возвращает -1.

 

int GetLastOrderHist(int type = -1) 
{
 int ticket = -1;
 datetime dt = 0;
 int cnt = HistoryTotal();

 for (int i=0; i < cnt; i++) {
   if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;

   //Опционально
   if (OrderSymbol() != Symbol()) continue;
   //Опционально
   if (OrderMagicNumber() != Magic) continue;

   if (type != -1 && OrderType() != type) continue;

   if (OrderCloseTime() > dt) {
     dt = OrderCloseTime();
     ticket = OrderTicket();
   }
 }

 return (ticket);
}


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
RickD

Функция для расчета рабочего лота по следующим условиям.

lotmin - стартовый размер лота.

lotmax - верхнее ограничение на размер лота.

Если последняя сделка закрылась в +, то увеличиваем лот на величину lotstep.

Как только последняя сделка закрылась в -, возвращаемся к lotmin.

Т.е. при наступлении серии положительных сделок мы увеличиваем нагрузку на лот.

 

Будем использовать функцию GetLastOrderHist, описанную выше.

 

// --- Параметры управления капиталом ---
extern bool uplot = true; - вкл/выкл изменение величины лота
extern int lastprofit = 1; - принимает значения -1/1. 
-1 - увеличение лота после минусовой сделки до первой плюсовой.
1 - увеличение лота после плюсовой сделки до первой минусовой.
extern double lotmin = 0.1; - начальное значение
extern double lotmax = 0.5; - потолок
extern double lotstep = 0.1; - приращение лота 

double GetLots() {

 double lot = lotmin;
 if (!uplot) return (lot);

 int ticket = GetLastOrderHist();
 if (ticket == -1) return (lot);

 if (!OrderSelect(ticket, SELECT_BY_TICKET, MODE_HISTORY)) return (lot);
 if (OrderProfit()*lastprofit < 0) return (lot);

 lot = MathMin(OrderLots() + lotstep, lotmax);
 return (lot);
}


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
RickD

Трейлинг-стоп.

MinProfit - когда профит достигает указанное количество пунктов, трейлинг начинает работу

TrailingStop - величина трала

TrailingStep - шаг

l - префикс для лонгов

s - префикс для шортов

 

extern bool UseTrailing = true;
extern int lMinProfit = 30;
extern int sMinProfit = 30;
extern int lTrailingStop = 15;
extern int sTrailingStop = 15;
extern int lTrailingStep = 5;
extern int sTrailingStep = 5;

if (UseTrailing) TrailPositions();  

void TrailPositions() 
{
 int cnt = OrdersTotal();

 for (int i=0; i<cnt; i++) {
   if (!(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))) continue;
   if (OrderSymbol() != Symbol()) continue;        

   if (OrderType() == OP_BUY) {
     if (Bid-OrderOpenPrice() > lMinProfit*Point) {
       if (OrderStopLoss() < Bid-(lTrailingStop+lTrailingStep-1)*Point) {
         OrderModify(OrderTicket(), OrderOpenPrice(), Bid-lTrailingStop*Point, OrderTakeProfit(), 0, Blue);
       }
     }
   }

   if (OrderType() == OP_SELL) {
     if (OrderOpenPrice()-Ask > sMinProfit*Point) {
       if (OrderStopLoss() > Ask+(sTrailingStop+sTrailingStep-1)*Point || OrderStopLoss() == 0) {
         OrderModify(OrderTicket(), OrderOpenPrice(), Ask+sTrailingStop*Point, OrderTakeProfit(), 0, Blue);
       }
     }
   }
 }

}


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
Telemah
:smt045 Edited by Telemah

Share this post


Link to post
Share on other sites
RickD

2 метода - Buy и Sell. Помимо открытия позиции нормализуют цены и выводят в лог входные параметры. Возвращают номер тикета, либо -1 в случае ошибки. После открытия ордера выдерживается установленный таймаут.

 

#include <stdlib.mqh>
#include <stderror.mqh>

int SleepOk = 2000;
int SleepErr = 6000;
int Slippage = 3;

//~~~~~

int Buy(string symbol, double lot, double price, double sl, double tp, int magic, string comment="") {
 int dig = MarketInfo(symbol, MODE_DIGITS);

 price = NormalizeDouble(price, dig);
 sl = NormalizeDouble(sl, dig);
 tp = NormalizeDouble(tp, dig);

 string _lot = DoubleToStr(lot, 1);
 string _price = DoubleToStr(price, dig);
 string _sl = DoubleToStr(sl, dig);
 string _tp = DoubleToStr(tp, dig);

 Print("Buy \"", symbol, "\", ", _lot, ", ", _price, ", ", Slippage, ", ", _sl, ", ", _tp, ", ", magic, ", \"", comment, "\"");

 int res = OrderSend(symbol, OP_BUY, lot, price, Slippage, sl, tp, comment, magic);
 if (res >= 0) {
   Sleep(SleepOk);
   return (res);
 } 	

 int code = GetLastError();
 Print("Error opening BUY order: ", ErrorDescription(code), " (", code, ")");
 Sleep(SleepErr);

 return (-1);
}

int Sell(string symbol, double lot, double price, double sl, double tp, int magic, string comment="") {
 int dig = MarketInfo(symbol, MODE_DIGITS);

 price = NormalizeDouble(price, dig);
 sl = NormalizeDouble(sl, dig);
 tp = NormalizeDouble(tp, dig);

 string _lot = DoubleToStr(lot, 1);
 string _price = DoubleToStr(price, dig);
 string _sl = DoubleToStr(sl, dig);
 string _tp = DoubleToStr(tp, dig);

 Print("Sell \"", symbol, "\", ", _lot, ", ", _price, ", ", Slippage, ", ", _sl, ", ", _tp, ", ", magic, ", \"", comment, "\"");

 int res = OrderSend(symbol, OP_SELL, lot, price, Slippage, sl, tp, comment, magic);
 if (res >= 0) {
   Sleep(SleepOk);
   return (res);
 } 	

 int code = GetLastError();
 Print("Error opening SELL order: ", ErrorDescription(code), " (", code, ")");
 Sleep(SleepErr);

 return (-1);
}


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
RickD

Открыть позицию в заданное время.

Код удобнее всего поместить в скрипт, который работает в бесконечном цикле. Это даст возможность открыться в нужное время, не дожидаясь прихода первого тика.

 

OpenTime - время открытия.

OpenPeriod - рабочий интервал, мин

 

 extern string OpenTime = "00:00";
 extern int OpenPeriod = 10;

 datetime tm0 = StrToTime(TimeToStr(CurTime(), TIME_DATE) + " " + OpenTime);
 datetime tm1 = tm0 + OpenPeriod*60;

 if (CurTime() < tm0 || CurTime() > tm1) return;

 //Открываем позицию либо ставим ордер

 

Дополнительно следует использовать проверку на максимально допустимое количество открытых ордеров.


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
Неизвестный

Подскажите плиз есть ли скрипт для МТ4 выполняющий такие действия:

выставляем отложенный ордер с условием его отмены, если цена достигла уровня х,хххх ?

Share this post


Link to post
Share on other sites
RickD
Подскажите плиз есть ли скрипт для МТ4 выполняющий такие действия:

выставляем отложенный ордер с условием его отмены, если цена достигла уровня х,хххх ?

 

Можно выставлять отложенные ордера только с безусловной отменой.


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
RickD

Эксперт, закрывающий ордера по рынку с указанным тейкпрофитом.

TakeProfit можно ставить 1, 2, 3, ...

 

 

extern int TakeProfit = 2;
extern int Slippage = 3;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void init () {
}

void deinit() {
}

void start() {

 if (TakeProfit == 0) return;

 int cnt = OrdersTotal();
 for (int i=cnt-1; i >= 0; i--) {
   if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
   if (OrderSymbol() != Symbol()) continue;

   int type = OrderType();
   if (type == OP_BUY) {
     if (Bid > OrderOpenPrice() + TakeProfit*Point)
       OrderClose(OrderTicket(), OrderLots(), Bid, Slippage);   
   }

   if (type == OP_SELL) {
     if (Ask < OrderOpenPrice() - TakeProfit*Point) 
       OrderClose(OrderTicket(), OrderLots(), Ask, Slippage); 
   }
 }
}


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
RickD

Функция возвращает длину цепочки ордеров с положительным профитом. Считаем с конца history.

 

int GetLastPositiveOrdersCount() 
{
 int PosCnt = 0;
 int cnt = HistoryTotal();
 for (int i = cnt-1; i >=0; i--) {

   if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
   //if (OrderSymbol() != Symbol()) continue;
   //if (OrderMagicNumber() != Magic) continue;


   int type = OrderType();
   if (type != OP_BUY && type != OP_SELL) continue;

   if (OrderProfit() < 0) break;

   PosCnt++;
 }

 return (PosCnt);
}


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
Player 2
После открытия ордера выдерживается установленный таймаут.

А можно узнать про таймаут, зачем он? А то у меня безо всяких таймаутов все работает, может это нестабильно или еще что-то.

Share this post


Link to post
Share on other sites
Юг

RickD

 

Привет.

 

Случайно не втречал нигде скриптика (или эксперта ну или функции), который бы сохранял эквити в файл каждые полчаса (час.....), вроде где-то видел, но что-то не могу найти на форуме.:roll:


С уважением, Юг

Обсуждаем...

ФА...

Share this post


Link to post
Share on other sites
RickD
RickD

 

Привет.

 

Случайно не втречал нигде скриптика (или эксперта ну или функции), который бы сохранял эквити в файл каждые полчаса (час.....), вроде где-то видел, но что-то не могу найти на форуме.:roll:

 

Привет.

Приблизительно такой скрипт будет. Раз в час будет добавлять строку в файл file.csv.

Сделан по простому - потому при перезапуске снова добавит данные за текущий час. Можно использовать глобальные переменные для запоминания последнего времени записи.

 

int Hour0 = -1; 

void init () {
 Comment("");
}

void deinit() {
 Comment("");
}

void start() {
 for (; {
   Comment(TimeToStr(LocalTime(),TIME_DATE|TIME_SECONDS ));

   if (Hour() != Hour0) {
     Hour0 = Hour();
     Write();
   }

   Sleep(5000);
 }
}

void Write() 
{  
 int hFile = FileOpen("file.csv", FILE_CSV|FILE_READ|FILE_WRITE, ';');
 if (hFile == -1) {
   Print("Cannot open csv file!");
   return;
 }

 FileSeek(hFile, 0, SEEK_END);
 FileWrite(hFile, 
   TimeToStr(LocalTime()), 
   DoubleToStr(AccountEquity(), 2),
 );

 FileClose(hFile);

}


MQL4: идея * опыт + творческий подход

:agree:

Share this post


Link to post
Share on other sites
AlexSilver
RickD

 

Привет.

 

Случайно не втречал нигде скриптика (или эксперта ну или функции), который бы сохранял эквити в файл каждые полчаса (час.....), вроде где-то видел, но что-то не могу найти на форуме.:roll:

 

Теоретически, в МТ-4 можно сделать скрипт, который будет формировать почасовую историю эквити по истории счета и часовкам используемых инструментов ;)

 

Вот это было бы решением вопроса, а сохранение эквити очень заморочно - надо держать компьютер постоянно включенным и один терминал только под этот скрипт на компьютере. Я когда-то еще на МТ-3 делал такое в виде советника, но потом плюнул на это дело и бросил, повесив закрытые счета на VIAC ;)


alexsilver

Учу великому, доброму, вечному!.. 

Share this post


Link to post
Share on other sites
Юг

:roll:

Теоретически, в МТ-4 можно сделать скрипт, который будет формировать почасовую историю эквити по истории счета и часовкам используемых инструментов ;)

 

Вот это было бы решением вопроса, а сохранение эквити очень заморочно - надо держать компьютер постоянно включенным и один терминал только под этот скрипт на компьютере. Я когда-то еще на МТ-3 делал такое в виде советника, но потом плюнул на это дело и бросил, повесив закрытые счета на VIAC ;)

 

Теоретически можно, но реально не так оказыватся просто к сожалению :roll: А в реальности вполне можно запустить МТ на сервере и пусть себе пишет, так ведь на Виаке и сделано :).

 

RickD & Rosh

 

Спасибо наваял вот такого экспера, вроде пишет нормально :)

 

int expertBars;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
 {
//----

//----
  return(0);
 }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
 {
//----

//----
  return(0);
 }
//+------------------------------------------------------------------+
//| возвращает true если появлися новый бар, иначе false             |
//+------------------------------------------------------------------+
bool isNewBar()
 {
//----
  bool res=false; 
  if (expertBars!=Bars) 
     {
     expertBars=Bars;
     res=true;
     } 
//----
  return(res);
 }
//+------------------------------------------------------------------+
//| выполняется один раз при появлении нового бара                   |
//+------------------------------------------------------------------+
void Write() 
{  
 int hFile = FileOpen("equity.txt", FILE_CSV|FILE_READ|FILE_WRITE,'\t');
 if (hFile == -1) {
   Print("Cannot open csv file!");
   return;
 }

 FileSeek(hFile, 0, SEEK_END);
 FileWrite(hFile, 
   TimeToStr(LocalTime()), 
   DoubleToStr(AccountEquity(), 2),
 );

 FileClose(hFile);
  return;    
}
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
 {
//----
  if (isNewBar()) Write() ; // если появился новый бар - 
                              //выполнить необходимые для него действия
//----
  return(0);
 }
//+------------------------------------------------------------------+


С уважением, Юг

Обсуждаем...

ФА...

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.

  • Recently Browsing   0 members

    No registered users viewing this page.

×