Blessing 3
Похожие материалы по тегам
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «blessing_3_v3.9.6.23.mq4» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
Blessing 3 v3.9.6.23 — торговый советник для MetaTrader 4, работающий на языке MQL4. Советник обрабатывает рыночные и торговые события, анализирует ценовые данные и технические показатели, использует торговые операции MetaTrader и отправляет уведомления о событиях и условиях. В исходном коде присутствуют обработчики событий, функции работы с ордерами и позициями, а также вспомогательные функции для отображения информации на графике. Советник поддерживает настройку торговых параметров, управление рисками, хеджирование и отправку email-уведомлений. Все настройки задаются через входные параметры, которые можно изменять в окне свойств советника. Код содержит большое количество пользовательских настроек, сгруппированных по категориям: торговые параметры, настройки сетки, хеджирование, управление капиталом, отображение и оптимизация. Советник не является библиотекой или индикатором, а представляет собой полноценный торговый робот для автоматической торговли на платформе MetaTrader 4.
Настройки программы
| Настройка | Описание |
|---|---|
| Version_3_9_6_23 | Отображает версию советника. |
| TradeComment | Комментарий, добавляемый к торговым операциям советника. |
| Notes | Произвольные заметки пользователя, не влияющие на работу советника. |
| EA Magic Number (EANumber) | Уникальный номер советника (Magic Number), используемый для идентификации ордеров, открытых этим советником. |
| CLOSE ALL NOW *** (EmergencyCloseAll) | Экстренно закрывает все открытые позиции и удаляет отложенные ордера. |
| . (s1) | Разделитель в списке параметров. |
| NO NEW TRADES *** (ShutDown) | Запрещает открытие новых сделок, но не закрывает существующие позиции. |
| . (s2) | Разделитель в списке параметров. |
| == ACCOUNT SETTINGS == (LabelAcc) | Заголовок раздела настроек аккаунта. |
| . (s3) | Разделитель в списке параметров. |
| Opt. with 'Open prices only' -- (eopb) | Вспомогательный параметр для режима 'Open prices only'. |
| EnableOncePerBar | Включает режим, при котором торговые сигналы проверяются только один раз на бар, что ускоряет оптимизацию. |
| UseMinMarginPercent | Включает контроль минимального процента свободной маржи. |
| MinMarginPercent | Минимальный процент свободной маржи, при котором разрешена торговля. |
| . (eopb1) | Вспомогательный параметр для режима 'Open prices only'. |
| CUSTOM TESTER SETTINGS ------ (LabelTST) | Заголовок раздела пользовательских настроек тестера. |
| . (LabelTST2) | Разделитель для пользовательских настроек тестера. |
| LOT SIZE ----------- (LabelLS) | Заголовок раздела размера лота. |
| GRID SETTINGS ------ (LabelGS) | Заголовок раздела настроек сетки. |
| ===== TRADING ===== (LabelTS) | Заголовок раздела торговых настроек. |
| EXITS ----------- (LabelES) | Заголовок раздела выходов. |
| EARLY EXITS --------- (LabelEE) | Заголовок раздела ранних выходов. |
| . (LabelAdv) | Разделитель для дополнительных настроек. |
| GRID SIZE --------- (LabelGrid) | Заголовок раздела размера сетки. |
| . (LabelEST0) | Разделитель для параметров входа. |
| == ENTRY PARAMETERS == (LabelEST) | Заголовок раздела параметров входа. |
| MA ------------- (LabelMA) | Заголовок раздела настроек скользящей средней. |
| CCI ------------- (LabelCCI) | Заголовок раздела настроек CCI. |
| BOLLINGER BANDS ----- (LabelBBS) | Заголовок раздела настроек Bollinger Bands. |
| ICHIMOKU CLOUD ----- (LabelIchi) | Заголовок раздела настроек Ichimoku Cloud. |
| Ichimoku Entry (IchimokuEntry) | Выбор режима входа по индикатору Ichimoku. |
| TF setting, but only current will work (ICHI_TF) | Таймфрейм для индикатора Ichimoku (работает только текущий). |
| Tenkan (Tenkan_Sen) | Период линии Tenkan в индикаторе Ichimoku. |
| Kijun (Kijun_Sen) | Период линии Kijun в индикаторе Ichimoku. |
| Senkou (Senkou_Span) | Период линии Senkou в индикаторе Ichimoku. |
| Trade if price breaks cloud / Kumo (useCloudBreakOut) | Включает торговлю при пробое облака (Kumo). |
| Trade if Tenken crosses Kijun (useTenken_Kijun_cross) | Выбор режима торговли при пересечении Tenkan и Kijun. |
| Trade if Price crosses Tenken (usePriceCrossTenken) | Включает торговлю при пересечении ценой линии Tenkan. |
| Trade if price crosses Kijun (usePriceCrossKijun) | Включает торговлю при пересечении ценой линии Kijun. |
| Trade if chiku crosses Price (useChikuspan) | Включает торговлю при пересечении линии Chikou Span с ценой. |
| Close all orders if price dives into the cloud/kumo (useCloudSL) | Закрывает все ордера, если цена входит в облако (Kumo). |
| STOCHASTIC -------- (LabelSto) | Заголовок раздела настроек стохастика. |
| MACD ------------ (LabelMACD) | Заголовок раздела настроек MACD. |
| SMART GRID --------- (LabelSG) | Заголовок раздела умной сетки. |
| . (LabelHS0) | Разделитель для настроек хеджирования. |
| HEDGE SETTINGS ----- (LabelHS) | Заголовок раздела настроек хеджирования. |
| . (LabelOS0) | Разделитель для прочих настроек. |
| OTHER ----------- (LabelOS) | Заголовок раздела прочих настроек. |
| EMAIL ------------ (LabelUE) | Заголовок раздела настроек email. |
| UseEmail | Включает отправку email-уведомлений о событиях советника. |
| . (LabelEDD) | Разделитель для настроек email-просадки. |
| EmailDD1 | Первый порог просадки для отправки email-уведомления. |
| EmailDD2 | Второй порог просадки для отправки email-уведомления. |
| EmailDD3 | Третий порог просадки для отправки email-уведомления. |
| . (LabelEH) | Разделитель для настроек email-часов. |
| Minimum number of hours between emails (EmailHours) | Минимальное количество часов между отправкой email-уведомлений. |
| DISPLAY ----------- (LabelDisplay) | Заголовок раздела настроек отображения. |
| Debug | Включает или выключает вывод отладочных сообщений в журнал. |
| GRID OPTIMIZATION ---- (LabelGridOpt) | Заголовок раздела оптимизации сетки. |
| . (LabelOpt) | Разделитель для настроек оптимизации. |
| SetArray1 | Первый параметр для оптимизации настроек. |
| SetArray2 | Второй параметр для оптимизации настроек. |
| SetArray3 | Третий параметр для оптимизации настроек. |
| SetArray4 | Четвёртый параметр для оптимизации настроек. |
| GridArray1 | Первый параметр сетки для оптимизации. |
| GridArray2 | Второй параметр сетки для оптимизации. |
| GridArray3 | Третий параметр сетки для оптимизации. |
| GridArray4 | Четвёртый параметр сетки для оптимизации. |
| GridArray5 | Пятый параметр сетки для оптимизации. |
| TPArray1 | Первый параметр тейк-профита для оптимизации. |
| TPArray2 | Второй параметр тейк-профита для оптимизации. |
| TPArray3 | Третий параметр тейк-профита для оптимизации. |
| TPArray4 | Четвёртый параметр тейк-профита для оптимизации. |
| TPArray5 | Пятый параметр тейк-профита для оптимизации. |
Поиск по коду файла
#property version "396.23"
#property strict
#ifdef __MQL5__
#define MT4_TICKET_TYPE
#ifndef __MT4ORDERS__
#ifdef MT4ORDERS_BENCHMARK_MINTIME
#include <fxsaber\Benchmark.mqh> //
#define _B2(A) _B(A, MT4ORDERS_BENCHMARK_MINTIME)
#define _B3(A) _B(A, 1)
#define _BV2(A) _BV(A, MT4ORDERS_BENCHMARK_MINTIME)
#else // MT4ORDERS_BENCHMARK_MINTIME
#define _B2(A) (A)
#define _B3(A) (A)
#define _BV2(A) { A; }
#endif // MT4ORDERS_BENCHMARK_MINTIME
#define __MT4ORDERS__ "2020.09.30"
#define MT4ORDERS_SLTP_OLD // Enabling the old mechanism for determining SL / TP closed positions via OrderClose
#ifdef MT4_TICKET_TYPE
#define TICKET_TYPE int
#define MAGIC_TYPE int
#undef MT4_TICKET_TYPE
#else // MT4_TICKET_TYPE
#define TICKET_TYPE long // Negative values are also required for OrderSelectByTicket.
#define MAGIC_TYPE long
#endif // MT4_TICKET_TYPE
struct MT4_ORDER
{
long Ticket;
int Type;
long TicketOpen;
long TicketID;
double Lots;
string Symbol;
string Comment;
double OpenPriceRequest;
double OpenPrice;
long OpenTimeMsc;
datetime OpenTime;
ENUM_DEAL_REASON OpenReason;
double StopLoss;
double TakeProfit;
double ClosePriceRequest;
double ClosePrice;
long CloseTimeMsc;
datetime CloseTime;
ENUM_DEAL_REASON CloseReason;
ENUM_ORDER_STATE State;
datetime Expiration;
long MagicNumber;
double Profit;
double Commission;
double Swap;
#define POSITION_SELECT (-1)
#define ORDER_SELECT (-2)
static int GetDigits( double Price )
{
int Res = 0;
while ((bool)(Price = ::NormalizeDouble(Price - (int)Price, 8)))
{
Price *= 10;
Res++;
}
return(Res);
}
static string DoubleToString( const double Num, const int digits )
{
return(::DoubleToString(Num, ::MathMax(digits, MT4_ORDER::GetDigits(Num))));
}
static string TimeToString( const long time )
{
return((string)(datetime)(time / 1000) + "." + ::IntegerToString(time % 1000, 3, '0'));
}
static const MT4_ORDER GetPositionData( void )
{
MT4_ORDER Res = {0};
Res.Ticket = ::PositionGetInteger(POSITION_TICKET);
Res.Type = (int)::PositionGetInteger(POSITION_TYPE);
Res.Lots = ::PositionGetDouble(POSITION_VOLUME);
Res.Symbol = ::PositionGetString(POSITION_SYMBOL);
Res.OpenPrice = ::PositionGetDouble(POSITION_PRICE_OPEN);
Res.OpenTimeMsc = (datetime)::PositionGetInteger(POSITION_TIME_MSC);
Res.StopLoss = ::PositionGetDouble(POSITION_SL);
Res.TakeProfit = ::PositionGetDouble(POSITION_TP);
Res.ClosePrice = ::PositionGetDouble(POSITION_PRICE_CURRENT);
Res.CloseTimeMsc = 0;
Res.Expiration = 0;
Res.MagicNumber = ::PositionGetInteger(POSITION_MAGIC);
Res.Profit = ::PositionGetDouble(POSITION_PROFIT);
Res.Swap = ::PositionGetDouble(POSITION_SWAP);
return(Res);
}
static const MT4_ORDER GetOrderData( void )
{
MT4_ORDER Res = {0};
Res.Ticket = ::OrderGetInteger(ORDER_TICKET);
Res.Type = (int)::OrderGetInteger(ORDER_TYPE);
Res.Lots = ::OrderGetDouble(ORDER_VOLUME_CURRENT);
Res.Symbol = ::OrderGetString(ORDER_SYMBOL);
Res.Comment = ::OrderGetString(ORDER_COMMENT);
Res.OpenPrice = ::OrderGetDouble(ORDER_PRICE_OPEN);
Res.OpenTimeMsc = (datetime)::OrderGetInteger(ORDER_TIME_SETUP_MSC);
Res.StopLoss = ::OrderGetDouble(ORDER_SL);
Res.TakeProfit = ::OrderGetDouble(ORDER_TP);
Res.ClosePrice = ::OrderGetDouble(ORDER_PRICE_CURRENT);
Res.CloseTimeMsc = 0; // (datetime)::OrderGetInteger(ORDER_TIME_DONE)
Res.Expiration = (datetime)::OrderGetInteger(ORDER_TIME_EXPIRATION);
Res.MagicNumber = ::OrderGetInteger(ORDER_MAGIC);
Res.Profit = 0;
Res.Commission = 0;
Res.Swap = 0;
if (!Res.OpenPrice)
Res.OpenPrice = Res.ClosePrice;
return(Res);
}
string ToString( void ) const
{
static const string Types[] = {"buy", "sell", "buy limit", "sell limit", "buy stop", "sell stop", "balance"};
const int digits = (int)::SymbolInfoInteger(this.Symbol, SYMBOL_DIGITS);
MT4_ORDER TmpOrder = {0};
if (this.Ticket == POSITION_SELECT)
{
TmpOrder = MT4_ORDER::GetPositionData();
TmpOrder.Comment = this.Comment;
TmpOrder.Commission = this.Commission;
}
else if (this.Ticket == ORDER_SELECT)
TmpOrder = MT4_ORDER::GetOrderData();
return(((this.Ticket == POSITION_SELECT) || (this.Ticket == ORDER_SELECT)) ? TmpOrder.ToString() :
("#" + (string)this.Ticket + " " +
MT4_ORDER::TimeToString(this.OpenTimeMsc) + " " +
((this.Type < ::ArraySize(Types)) ? Types[this.Type] : "unknown") + " " +
MT4_ORDER::DoubleToString(this.Lots, 2) + " " +
(::StringLen(this.Symbol) ? this.Symbol + " " : NULL) +
MT4_ORDER::DoubleToString(this.OpenPrice, digits) + " " +
MT4_ORDER::DoubleToString(this.StopLoss, digits) + " " +
MT4_ORDER::DoubleToString(this.TakeProfit, digits) + " " +
((this.CloseTimeMsc > 0) ? (MT4_ORDER::TimeToString(this.CloseTimeMsc) + " ") : "") +
MT4_ORDER::DoubleToString(this.ClosePrice, digits) + " " +
MT4_ORDER::DoubleToString(::NormalizeDouble(this.Commission, 3), 2) + " " + // Don't print more than three digits after the decimal point
MT4_ORDER::DoubleToString(this.Swap, 2) + " " +
MT4_ORDER::DoubleToString(this.Profit, 2) + " " +
((this.Comment == "") ? "" : (this.Comment + " ")) +
(string)this.MagicNumber +
(((this.Expiration > 0) ? (" expiration " + (string)this.Expiration): ""))));
}
};
#define RESERVE_SIZE 1000
#define DAY (24 * 3600)
#define HISTORY_PAUSE (MT4HISTORY::IsTester ? 0 : 5)
#define END_TIME D'31.12.3000 23:59:59'
#define THOUSAND 1000
#define LASTTIME(A) \
if (Time##A >= LastTimeMsc) \
{ \
const datetime TmpTime = (datetime)(Time##A / THOUSAND); \
\
if (TmpTime > this.LastTime) \
{ \
this.LastTotalOrders = 0; \
this.LastTotalDeals = 0; \
\
this.LastTime = TmpTime; \
LastTimeMsc = this.LastTime * THOUSAND; \
} \
\
this.LastTotal##A##s++; \
}
#ifndef MT4ORDERS_FASTHISTORY_OFF
#include <Generic\HashMap.mqh>
#endif // MT4ORDERS_FASTHISTORY_OFF
class MT4HISTORY
{
private:
static const bool MT4HISTORY::IsTester;
#ifndef MT4ORDERS_FASTHISTORY_OFF
CHashMap<ulong, ulong> DealsIn; // By positionID returns DealIn
CHashMap<ulong, ulong> DealsOut; // By positionID returns DealOut
#endif // MT4ORDERS_FASTHISTORY_OFF
long Tickets[];
uint Amount;
int LastTotalDeals;
int LastTotalOrders;
#ifdef MT4ORDERS_HISTORY_OLD
datetime LastTime;
datetime LastInitTime;
int PrevDealsTotal;
int PrevOrdersTotal;
bool IsChangeHistory( void )
{
bool Res = !_B2(::HistorySelect(0, INT_MAX));
if (!Res)
{
const int iDealsTotal = ::HistoryDealsTotal();
const int iOrdersTotal = ::HistoryOrdersTotal();
if (Res = (iDealsTotal != this.PrevDealsTotal) || (iOrdersTotal != this.PrevOrdersTotal))
{
this.PrevDealsTotal = iDealsTotal;
this.PrevOrdersTotal = iOrdersTotal;
}
}
return(Res);
}
bool RefreshHistory( void )
{
bool Res = !MT4HISTORY::IsChangeHistory();
if (!Res)
{
const datetime LastTimeCurrent = ::TimeCurrent();
if (!MT4HISTORY::IsTester && ((LastTimeCurrent >= this.LastInitTime + DAY)))
{
this.LastTime = 0;
this.LastTotalOrders = 0;
this.LastTotalDeals = 0;
this.Amount = 0;
::ArrayResize(this.Tickets, this.Amount, RESERVE_SIZE);
this.LastInitTime = LastTimeCurrent;
#ifndef MT4ORDERS_FASTHISTORY_OFF
this.DealsIn.Clear();
this.DealsOut.Clear();
#endif // MT4ORDERS_FASTHISTORY_OFF
}
const datetime LastTimeCurrentLeft = LastTimeCurrent - HISTORY_PAUSE;
if (!this.LastTime || _B2(::HistorySelect(this.LastTime, END_TIME))) //
{
const int TotalOrders = ::HistoryOrdersTotal();
const int TotalDeals = ::HistoryDealsTotal();
Res = ((TotalOrders > this.LastTotalOrders) || (TotalDeals > this.LastTotalDeals));
if (Res)
{
int iOrder = this.LastTotalOrders;
int iDeal = this.LastTotalDeals;
ulong TicketOrder = 0;
ulong TicketDeal = 0;
long TimeOrder = (iOrder < TotalOrders) ? ::HistoryOrderGetInteger((TicketOrder = ::HistoryOrderGetTicket(iOrder)), ORDER_TIME_DONE_MSC) : LONG_MAX;
long TimeDeal = (iDeal < TotalDeals) ? ::HistoryDealGetInteger((TicketDeal = ::HistoryDealGetTicket(iDeal)), DEAL_TIME_MSC) : LONG_MAX;
if (this.LastTime < LastTimeCurrentLeft)
{
this.LastTotalOrders = 0;
this.LastTotalDeals = 0;
this.LastTime = LastTimeCurrentLeft;
}
long LastTimeMsc = this.LastTime * THOUSAND;
while ((iDeal < TotalDeals) || (iOrder < TotalOrders))
if (TimeOrder < TimeDeal)
{
LASTTIME(Order)
if (MT4HISTORY::IsMT4Order(TicketOrder))
{
this.Amount = ::ArrayResize(this.Tickets, this.Amount + 1, RESERVE_SIZE);
this.Tickets[this.Amount - 1] = -(long)TicketOrder;
}
iOrder++;
TimeOrder = (iOrder < TotalOrders) ? ::HistoryOrderGetInteger((TicketOrder = ::HistoryOrderGetTicket(iOrder)), ORDER_TIME_DONE_MSC) : LONG_MAX;
}
else
{
LASTTIME(Deal)
if (MT4HISTORY::IsMT4Deal(TicketDeal))
{
this.Amount = ::ArrayResize(this.Tickets, this.Amount + 1, RESERVE_SIZE);
this.Tickets[this.Amount - 1] = (long)TicketDeal;
#ifndef MT4ORDERS_FASTHISTORY_OFF
_B2(this.DealsOut.Add(::HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID), TicketDeal));
#endif // MT4ORDERS_FASTHISTORY_OFF
}
#ifndef MT4ORDERS_FASTHISTORY_OFF
else if ((ENUM_DEAL_ENTRY)::HistoryDealGetInteger(TicketDeal, DEAL_ENTRY) == DEAL_ENTRY_IN)
_B2(this.DealsIn.Add(::HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID), TicketDeal));
#endif // MT4ORDERS_FASTHISTORY_OFF
iDeal++;
TimeDeal = (iDeal < TotalDeals) ? ::HistoryDealGetInteger((TicketDeal = ::HistoryDealGetTicket(iDeal)), DEAL_TIME_MSC) : LONG_MAX;
}
}
else if (LastTimeCurrentLeft > this.LastTime)
{
this.LastTime = LastTimeCurrentLeft;
this.LastTotalOrders = 0;
this.LastTotalDeals = 0;
}
}
}
return(Res);
}
#else // #ifdef MT4ORDERS_HISTORY_OLD
bool RefreshHistory( void )
{
if (_B2(::HistorySelect(0, INT_MAX)))
{
const int TotalOrders = ::HistoryOrdersTotal();
const int TotalDeals = ::HistoryDealsTotal();
if ((TotalOrders > this.LastTotalOrders) || (TotalDeals > this.LastTotalDeals))
{
ulong TicketOrder = 0;
ulong TicketDeal = 0;
long TimeOrder = (this.LastTotalOrders < TotalOrders) ?
::HistoryOrderGetInteger((TicketOrder = ::HistoryOrderGetTicket(this.LastTotalOrders)), ORDER_TIME_DONE_MSC) : LONG_MAX;
long TimeDeal = (this.LastTotalDeals < TotalDeals) ?
::HistoryDealGetInteger((TicketDeal = ::HistoryDealGetTicket(this.LastTotalDeals)), DEAL_TIME_MSC) : LONG_MAX;
while ((this.LastTotalDeals < TotalDeals) || (this.LastTotalOrders < TotalOrders))
if (TimeOrder < TimeDeal)
{
if (MT4HISTORY::IsMT4Order(TicketOrder))
{
this.Amount = ::ArrayResize(this.Tickets, this.Amount + 1, RESERVE_SIZE);
this.Tickets[this.Amount - 1] = -(long)TicketOrder;
}
this.LastTotalOrders++;
TimeOrder = (this.LastTotalOrders < TotalOrders) ?
::HistoryOrderGetInteger((TicketOrder = ::HistoryOrderGetTicket(this.LastTotalOrders)), ORDER_TIME_DONE_MSC) : LONG_MAX;
}
else
{
if (MT4HISTORY::IsMT4Deal(TicketDeal))
{
this.Amount = ::ArrayResize(this.Tickets, this.Amount + 1, RESERVE_SIZE);
this.Tickets[this.Amount - 1] = (long)TicketDeal;
_B2(this.DealsOut.Add(::HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID), TicketDeal));
}
else if ((ENUM_DEAL_ENTRY)::HistoryDealGetInteger(TicketDeal, DEAL_ENTRY) == DEAL_ENTRY_IN)
_B2(this.DealsIn.Add(::HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID), TicketDeal));
this.LastTotalDeals++;
TimeDeal = (this.LastTotalDeals < TotalDeals) ?
::HistoryDealGetInteger((TicketDeal = ::HistoryDealGetTicket(this.LastTotalDeals)), DEAL_TIME_MSC) : LONG_MAX;
}
}
}
return(true);
}
#endif // #ifdef MT4ORDERS_HISTORY_OLD #else
public:
static bool IsMT4Deal( const ulong &Ticket )
{
const ENUM_DEAL_TYPE DealType = (ENUM_DEAL_TYPE)::HistoryDealGetInteger(Ticket, DEAL_TYPE);
const ENUM_DEAL_ENTRY DealEntry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(Ticket, DEAL_ENTRY);
return(((DealType != DEAL_TYPE_BUY) && (DealType != DEAL_TYPE_SELL)) || // not a bargain
((DealEntry == DEAL_ENTRY_OUT) || (DealEntry == DEAL_ENTRY_OUT_BY))); // commercial
}
static bool IsMT4Order( const ulong &Ticket )
{
return(!::HistoryOrderGetInteger(Ticket, ORDER_POSITION_ID) || (::HistoryOrderGetDouble(Ticket, ORDER_VOLUME_CURRENT) &&
::HistoryOrderGetInteger(Ticket, ORDER_TYPE) > ORDER_TYPE_SELL));
}
MT4HISTORY( void ) : Amount(::ArrayResize(this.Tickets, 0, RESERVE_SIZE)),
LastTotalDeals(0), LastTotalOrders(0)
#ifdef MT4ORDERS_HISTORY_OLD
, LastTime(0), LastInitTime(0), PrevDealsTotal(0), PrevOrdersTotal(0)
#endif // #ifdef MT4ORDERS_HISTORY_OLD
{
}
ulong GetPositionDealIn( const ulong PositionIdentifier = -1 ) // 0 - it is impossible, because the balance sheet of the tester has zero
{
ulong Ticket = 0;
if (PositionIdentifier == -1)
{
const ulong MyPositionIdentifier = ::PositionGetInteger(POSITION_IDENTIFIER);
#ifndef MT4ORDERS_FASTHISTORY_OFF
if (!_B2(this.DealsIn.TryGetValue(MyPositionIdentifier, Ticket))
#ifndef MT4ORDERS_HISTORY_OLD
&& !_B2(this.RefreshHistory() && this.DealsIn.TryGetValue(MyPositionIdentifier, Ticket))
#endif // #ifndef MT4ORDERS_HISTORY_OLD
)
#endif // MT4ORDERS_FASTHISTORY_OFF
{
const datetime PosTime = (datetime)::PositionGetInteger(POSITION_TIME);
if (_B3(::HistorySelect(PosTime, PosTime)))
{
const int Total = ::HistoryDealsTotal();
for (int i = 0; i < Total; i++)
{
const ulong TicketDeal = ::HistoryDealGetTicket(i);
if ((::HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID) == MyPositionIdentifier)) // The first mention and so will be DEAL_ENTRY_IN
{
Ticket = TicketDeal;
#ifndef MT4ORDERS_FASTHISTORY_OFF
_B2(this.DealsIn.Add(MyPositionIdentifier, Ticket));
#endif // MT4ORDERS_FASTHISTORY_OFF
break;
}
}
}
}
}
else if (PositionIdentifier && // PositionIdentifier of balance transactions is zero
#ifndef MT4ORDERS_FASTHISTORY_OFF
!_B2(this.DealsIn.TryGetValue(PositionIdentifier, Ticket)) &&
#ifndef MT4ORDERS_HISTORY_OLD
!_B2(this.RefreshHistory() && this.DealsIn.TryGetValue(PositionIdentifier, Ticket)) &&
#endif // #ifndef MT4ORDERS_HISTORY_OLD
#endif // MT4ORDERS_FASTHISTORY_OFF
_B3(::HistorySelectByPosition(PositionIdentifier)) && (::HistoryDealsTotal() > 1)) // Почему > 1, а не > 0 ?!
{
Ticket = _B2(::HistoryDealGetTicket(0)); // The first mention and so will be DEAL_ENTRY_IN
#ifndef MT4ORDERS_FASTHISTORY_OFF
_B2(this.DealsIn.Add(PositionIdentifier, Ticket));
#endif // MT4ORDERS_FASTHISTORY_OFF
}
return(Ticket);
}
ulong GetPositionDealOut( const ulong PositionIdentifier )
{
ulong Ticket = 0;
#ifndef MT4ORDERS_FASTHISTORY_OFF
if (!_B2(this.DealsOut.TryGetValue(PositionIdentifier, Ticket)) && _B2(this.RefreshHistory()))
_B2(this.DealsOut.TryGetValue(PositionIdentifier, Ticket));
#endif // MT4ORDERS_FASTHISTORY_OFF
return(Ticket);
}
int GetAmount( void )
{
_B2(this.RefreshHistory());
return((int)this.Amount);
}
long operator []( const uint &Pos )
{
long Res = 0;
if ((Pos >= this.Amount))
{
_B2(this.RefreshHistory());
if (Pos < this.Amount)
Res = this.Tickets[Pos];
}
else
Res = this.Tickets[Pos];
return(Res);
}
};
static const bool MT4HISTORY::IsTester = ::MQLInfoInteger(MQL_TESTER);
#undef LASTTIME
#undef THOUSAND
#undef END_TIME
#undef HISTORY_PAUSE
#undef DAY
#undef RESERVE_SIZE
#define OP_BUY ORDER_TYPE_BUY
#define OP_SELL ORDER_TYPE_SELL
#define OP_BUYLIMIT ORDER_TYPE_BUY_LIMIT
#define OP_SELLLIMIT ORDER_TYPE_SELL_LIMIT
#define OP_BUYSTOP ORDER_TYPE_BUY_STOP
#define OP_SELLSTOP ORDER_TYPE_SELL_STOP
#define OP_BALANCE 6
#define SELECT_BY_POS 0
#define SELECT_BY_TICKET 1
#define MODE_TRADES 0
#define MODE_HISTORY 1
class MT4ORDERS
{
private:
static MT4_ORDER Order;
static MT4HISTORY History;
static const bool MT4ORDERS::IsTester;
static const bool MT4ORDERS::IsHedging;
static int OrderSendBug;
static bool HistorySelectOrder( const ulong Ticket )
{
return(Ticket && ((::HistoryOrderGetInteger(Ticket, ORDER_TICKET) == Ticket) ||
(_B2(::HistorySelect(0, INT_MAX)) && (::HistoryOrderGetInteger(Ticket, ORDER_TICKET) == Ticket))));
}
static bool HistorySelectDeal( const ulong &Ticket )
{
return(Ticket && ((::HistoryDealGetInteger(Ticket, DEAL_TICKET) == Ticket) ||
(_B2(::HistorySelect(0, INT_MAX)) && (::HistoryDealGetInteger(Ticket, DEAL_TICKET) == Ticket))));
}
#define UNKNOWN_COMMISSION DBL_MIN
#define UNKNOWN_REQUEST_PRICE DBL_MIN
#define UNKNOWN_TICKET 0
static bool CheckNewTicket( void )
{
return(false); // This functionality is useless - there is INT_MIN / INT_MAX with SELECT_BY_POS + MODE_TRADES
static long PrevPosTimeUpdate = 0;
static long PrevPosTicket = 0;
const long PosTimeUpdate = ::PositionGetInteger(POSITION_TIME_UPDATE_MSC);
const long PosTicket = ::PositionGetInteger(POSITION_TICKET);
const bool Res = ((PosTimeUpdate != PrevPosTimeUpdate) || (PosTicket != PrevPosTicket));
if (Res)
{
MT4ORDERS::GetPositionData();
PrevPosTimeUpdate = PosTimeUpdate;
PrevPosTicket = PosTicket;
}
return(Res);
}
static bool CheckPositionTicketOpen( void )
{
if ((MT4ORDERS::Order.TicketOpen == UNKNOWN_TICKET) || MT4ORDERS::CheckNewTicket())
MT4ORDERS::Order.TicketOpen = (long)_B2(MT4ORDERS::History.GetPositionDealIn()); // All because of this very expensive function
return(true);
}
static bool CheckPositionCommissionComment( void )
{
if ((MT4ORDERS::Order.Commission == UNKNOWN_COMMISSION) || MT4ORDERS::CheckNewTicket())
{
MT4ORDERS::Order.Commission = 0; // Always zero
MT4ORDERS::Order.Comment = ::PositionGetString(POSITION_COMMENT);
if (!MT4ORDERS::Order.Commission || (MT4ORDERS::Order.Comment == ""))
{
MT4ORDERS::CheckPositionTicketOpen();
const ulong Ticket = MT4ORDERS::Order.TicketOpen;
if ((Ticket > 0) && _B2(MT4ORDERS::HistorySelectDeal(Ticket)))
{
if (!MT4ORDERS::Order.Commission)
{
const double LotsIn = ::HistoryDealGetDouble(Ticket, DEAL_VOLUME);
if (LotsIn > 0)
MT4ORDERS::Order.Commission = ::HistoryDealGetDouble(Ticket, DEAL_COMMISSION) * ::PositionGetDouble(POSITION_VOLUME) / LotsIn;
}
if (MT4ORDERS::Order.Comment == "")
MT4ORDERS::Order.Comment = ::HistoryDealGetString(Ticket, DEAL_COMMENT);
}
}
}
return(true);
}
static bool CheckPositionOpenPriceRequest( void )
{
const long PosTicket = ::PositionGetInteger(POSITION_TICKET);
if (((MT4ORDERS::Order.OpenPriceRequest == UNKNOWN_REQUEST_PRICE) || MT4ORDERS::CheckNewTicket()) &&
!(MT4ORDERS::Order.OpenPriceRequest = (_B2(MT4ORDERS::HistorySelectOrder(PosTicket)) &&
(MT4ORDERS::IsTester || (::PositionGetInteger(POSITION_TIME_MSC) ==
::HistoryOrderGetInteger(PosTicket, ORDER_TIME_DONE_MSC)))) // Is this check necessary?
? ::HistoryOrderGetDouble(PosTicket, ORDER_PRICE_OPEN)
: ::PositionGetDouble(POSITION_PRICE_OPEN)))
MT4ORDERS::Order.OpenPriceRequest = ::PositionGetDouble(POSITION_PRICE_OPEN); // In case the order price is zero
return(true);
}
static void GetPositionData( void )
{
MT4ORDERS::Order.Ticket = POSITION_SELECT;
MT4ORDERS::Order.Commission = UNKNOWN_COMMISSION;
MT4ORDERS::Order.OpenPriceRequest = UNKNOWN_REQUEST_PRICE;
MT4ORDERS::Order.TicketOpen = UNKNOWN_TICKET;
return;
}
#undef UNKNOWN_TICKET
#undef UNKNOWN_REQUEST_PRICE
#undef UNKNOWN_COMMISSION
static void GetOrderData( void )
{
MT4ORDERS::Order.Ticket = ORDER_SELECT;
return;
}
static void GetHistoryOrderData( const ulong Ticket )
{
MT4ORDERS::Order.Ticket = ::HistoryOrderGetInteger(Ticket, ORDER_TICKET);
MT4ORDERS::Order.Type = (int)::HistoryOrderGetInteger(Ticket, ORDER_TYPE);
MT4ORDERS::Order.TicketOpen = MT4ORDERS::Order.Ticket;
MT4ORDERS::Order.TicketID = MT4ORDERS::Order.Ticket;
MT4ORDERS::Order.Lots = ::HistoryOrderGetDouble(Ticket, ORDER_VOLUME_CURRENT);
if (!MT4ORDERS::Order.Lots)
MT4ORDERS::Order.Lots = ::HistoryOrderGetDouble(Ticket, ORDER_VOLUME_INITIAL);
MT4ORDERS::Order.Symbol = ::HistoryOrderGetString(Ticket, ORDER_SYMBOL);
MT4ORDERS::Order.Comment = ::HistoryOrderGetString(Ticket, ORDER_COMMENT);
MT4ORDERS::Order.OpenTimeMsc = ::HistoryOrderGetInteger(Ticket, ORDER_TIME_SETUP_MSC);
MT4ORDERS::Order.OpenTime = (datetime)(MT4ORDERS::Order.OpenTimeMsc / 1000);
MT4ORDERS::Order.OpenPrice = ::HistoryOrderGetDouble(Ticket, ORDER_PRICE_OPEN);
MT4ORDERS::Order.OpenPriceRequest = MT4ORDERS::Order.OpenPrice;
MT4ORDERS::Order.OpenReason = (ENUM_DEAL_REASON)::HistoryOrderGetInteger(Ticket, ORDER_REASON);
MT4ORDERS::Order.StopLoss = ::HistoryOrderGetDouble(Ticket, ORDER_SL);
MT4ORDERS::Order.TakeProfit = ::HistoryOrderGetDouble(Ticket, ORDER_TP);
MT4ORDERS::Order.CloseTimeMsc = ::HistoryOrderGetInteger(Ticket, ORDER_TIME_DONE_MSC);
MT4ORDERS::Order.CloseTime = (datetime)(MT4ORDERS::Order.CloseTimeMsc / 1000);
MT4ORDERS::Order.ClosePrice = ::HistoryOrderGetDouble(Ticket, ORDER_PRICE_CURRENT);
MT4ORDERS::Order.ClosePriceRequest = MT4ORDERS::Order.ClosePrice;
MT4ORDERS::Order.CloseReason = MT4ORDERS::Order.OpenReason;
MT4ORDERS::Order.State = (ENUM_ORDER_STATE)::HistoryOrderGetInteger(Ticket, ORDER_STATE);
MT4ORDERS::Order.Expiration = (datetime)::HistoryOrderGetInteger(Ticket, ORDER_TIME_EXPIRATION);
MT4ORDERS::Order.MagicNumber = ::HistoryOrderGetInteger(Ticket, ORDER_MAGIC);
MT4ORDERS::Order.Profit = 0;
MT4ORDERS::Order.Commission = 0;
MT4ORDERS::Order.Swap = 0;
return;
}
static string GetTickFlag( uint tickflag )
{
string flag = " " + (string)tickflag;
#define TICKFLAG_MACRO(A) flag += ((bool)(tickflag & TICK_FLAG_##A)) ? " TICK_FLAG_" + #A : ""; \
tickflag -= tickflag & TICK_FLAG_##A;
TICKFLAG_MACRO(BID)
TICKFLAG_MACRO(ASK)
TICKFLAG_MACRO(LAST)
TICKFLAG_MACRO(VOLUME)
TICKFLAG_MACRO(BUY)
TICKFLAG_MACRO(SELL)
#undef TICKFLAG_MACRO
if (tickflag)
flag += " FLAG_UNKNOWN (" + (string)tickflag + ")";
return(flag);
}
#define TOSTR(A) " " + #A + " = " + (string)Tick.A
#define TOSTR2(A) " " + #A + " = " + ::DoubleToString(Tick.A, digits)
#define TOSTR3(A) " " + #A + " = " + (string)(A)
static string TickToString( const string &Symb, const MqlTick &Tick )
{
const int digits = (int)::SymbolInfoInteger(Symb, SYMBOL_DIGITS);
return(TOSTR3(Symb) + TOSTR(time) + "." + ::IntegerToString(Tick.time_msc % 1000, 3, '0') +
TOSTR2(bid) + TOSTR2(ask) + TOSTR2(last)+ TOSTR(volume) + MT4ORDERS::GetTickFlag(Tick.flags));
}
static string TickToString( const string &Symb )
{
MqlTick Tick = {0};
return(TOSTR3(::SymbolInfoTick(Symb, Tick)) + MT4ORDERS::TickToString(Symb, Tick));
}
#undef TOSTR3
#undef TOSTR2
#undef TOSTR
static void AlertLog( void )
{
::Alert("Please send the logs to the coauthor - ");
string Str = ::TimeToString(::TimeLocal(), TIME_DATE);
::StringReplace(Str, ".", NULL);
::Alert(::TerminalInfoString(TERMINAL_PATH) + "\\MQL5\\Logs\\" + Str + ".log");
return;
}
static long GetTimeCurrent( void )
{
long Res = 0;
MqlTick Tick = {0};
for (int i = ::SymbolsTotal(true) - 1; i >= 0; i--)
{
const string SymbName = ::SymbolName(i, true);
if (!::SymbolInfoInteger(SymbName, SYMBOL_CUSTOM) && ::SymbolInfoTick(SymbName, Tick) && (Tick.time_msc > Res))
Res = Tick.time_msc;
}
return(Res);
}
static string TimeToString( const long time )
{
return((string)(datetime)(time / 1000) + "." + ::IntegerToString(time % 1000, 3, '0'));
}
#define WHILE(A) while ((!(Res = (A))) && MT4ORDERS::Waiting())
#define TOSTR(A) #A + " = " + (string)(A) + "\n"
#define TOSTR2(A) #A + " = " + ::EnumToString(A) + " (" + (string)(A) + ")\n"
static void GetHistoryPositionData( const ulong Ticket )
{
MT4ORDERS::Order.Ticket = (long)Ticket;
MT4ORDERS::Order.TicketID = ::HistoryDealGetInteger(MT4ORDERS::Order.Ticket, DEAL_POSITION_ID);
MT4ORDERS::Order.Type = (int)::HistoryDealGetInteger(Ticket, DEAL_TYPE);
if ((MT4ORDERS::Order.Type > OP_SELL))
MT4ORDERS::Order.Type += (OP_BALANCE - OP_SELL - 1);
else
MT4ORDERS::Order.Type = 1 - MT4ORDERS::Order.Type;
MT4ORDERS::Order.Lots = ::HistoryDealGetDouble(Ticket, DEAL_VOLUME);
MT4ORDERS::Order.Symbol = ::HistoryDealGetString(Ticket, DEAL_SYMBOL);
MT4ORDERS::Order.Comment = ::HistoryDealGetString(Ticket, DEAL_COMMENT);
MT4ORDERS::Order.CloseTimeMsc = ::HistoryDealGetInteger(Ticket, DEAL_TIME_MSC);
MT4ORDERS::Order.CloseTime = (datetime)(MT4ORDERS::Order.CloseTimeMsc / 1000);
MT4ORDERS::Order.ClosePrice = ::HistoryDealGetDouble(Ticket, DEAL_PRICE);
MT4ORDERS::Order.CloseReason = (ENUM_DEAL_REASON)::HistoryDealGetInteger(Ticket, DEAL_REASON);;
MT4ORDERS::Order.Expiration = 0;
MT4ORDERS::Order.MagicNumber = ::HistoryDealGetInteger(Ticket, DEAL_MAGIC);
MT4ORDERS::Order.Profit = ::HistoryDealGetDouble(Ticket, DEAL_PROFIT);
MT4ORDERS::Order.Commission = ::HistoryDealGetDouble(Ticket, DEAL_COMMISSION);
MT4ORDERS::Order.Swap = ::HistoryDealGetDouble(Ticket, DEAL_SWAP);
#ifndef MT4ORDERS_SLTP_OLD
MT4ORDERS::Order.StopLoss = ::HistoryDealGetDouble(Ticket, DEAL_SL);
MT4ORDERS::Order.TakeProfit = ::HistoryDealGetDouble(Ticket, DEAL_TP);
#else // MT4ORDERS_SLTP_OLD
MT4ORDERS::Order.StopLoss = 0;
MT4ORDERS::Order.TakeProfit = 0;
#endif // MT4ORDERS_SLTP_OLD
const ulong OrderTicket = (MT4ORDERS::Order.Type < OP_BALANCE) ? ::HistoryDealGetInteger(Ticket, DEAL_ORDER) : 0;
const ulong PosTicket = MT4ORDERS::Order.TicketID;
const ulong OpenTicket = (OrderTicket > 0) ? _B2(MT4ORDERS::History.GetPositionDealIn(PosTicket)) : 0;
if (OpenTicket > 0)
{
const ENUM_DEAL_REASON Reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(Ticket, DEAL_REASON);
const ENUM_DEAL_ENTRY DealEntry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(Ticket, DEAL_ENTRY);
#ifdef MT4ORDERS_FASTHISTORY_OFF
const bool Res = true;
#else // MT4ORDERS_FASTHISTORY_OFF
bool Res = MT4ORDERS::IsTester ? MT4ORDERS::HistorySelectOrder(OrderTicket) : MT4ORDERS::Waiting(true);
if (!Res)
WHILE(_B2(MT4ORDERS::HistorySelectOrder(OrderTicket))) //
;
if (_B2(MT4ORDERS::HistorySelectDeal(OpenTicket))) // Sure to work, because OpenTicket guaranteed in history
#endif // MT4ORDERS_FASTHISTORY_OFF
{
MT4ORDERS::Order.TicketOpen = (long)OpenTicket;
MT4ORDERS::Order.OpenReason = Reason;
MT4ORDERS::Order.OpenPrice = ::HistoryDealGetDouble(OpenTicket, DEAL_PRICE);
MT4ORDERS::Order.OpenTimeMsc = ::HistoryDealGetInteger(OpenTicket, DEAL_TIME_MSC);
MT4ORDERS::Order.OpenTime = (datetime)(MT4ORDERS::Order.OpenTimeMsc / 1000);
const double OpenLots = ::HistoryDealGetDouble(OpenTicket, DEAL_VOLUME);
if (OpenLots > 0)
MT4ORDERS::Order.Commission += ::HistoryDealGetDouble(OpenTicket, DEAL_COMMISSION) * MT4ORDERS::Order.Lots / OpenLots;
const long __Magic = ::HistoryDealGetInteger(OpenTicket, DEAL_MAGIC);
if (__Magic)
MT4ORDERS::Order.MagicNumber = __Magic;
const string StrComment = ::HistoryDealGetString(OpenTicket, DEAL_COMMENT);
if (Res) // OrderTicket may not be in history, but may be among the living. Perhaps it is reasonable to get the necessary info from there.
{
double OrderPriceOpen = ::HistoryOrderGetDouble(OrderTicket, ORDER_PRICE_OPEN);
#ifdef MT4ORDERS_SLTP_OLD
if (Reason == DEAL_REASON_SL)
{
if (!OrderPriceOpen)
OrderPriceOpen = (double)::StringSubstr(MT4ORDERS::Order.Comment, MT4ORDERS::IsTester ? 3 : (::StringFind(MT4ORDERS::Order.Comment, "sl ") + 3));
MT4ORDERS::Order.StopLoss = OrderPriceOpen;
MT4ORDERS::Order.TakeProfit = ::HistoryOrderGetDouble(OrderTicket, ORDER_SL);
}
else if (Reason == DEAL_REASON_TP)
{
if (!OrderPriceOpen)
OrderPriceOpen = (double)::StringSubstr(MT4ORDERS::Order.Comment, MT4ORDERS::IsTester ? 3 : (::StringFind(MT4ORDERS::Order.Comment, "tp ") + 3));
MT4ORDERS::Order.TakeProfit = OrderPriceOpen;
MT4ORDERS::Order.StopLoss = ::HistoryOrderGetDouble(OrderTicket, ORDER_TP);
}
else
{
MT4ORDERS::Order.StopLoss = ::HistoryOrderGetDouble(OrderTicket, ORDER_TP);
MT4ORDERS::Order.TakeProfit = ::HistoryOrderGetDouble(OrderTicket, ORDER_SL);
}
#endif // MT4ORDERS_SLTP_OLD
MT4ORDERS::Order.State = (ENUM_ORDER_STATE)::HistoryOrderGetInteger(OrderTicket, ORDER_STATE);
if (!(MT4ORDERS::Order.ClosePriceRequest = (DealEntry == DEAL_ENTRY_OUT_BY) ? MT4ORDERS::Order.ClosePrice : OrderPriceOpen))
MT4ORDERS::Order.ClosePriceRequest = MT4ORDERS::Order.ClosePrice;
if (!(MT4ORDERS::Order.OpenPriceRequest = _B2(MT4ORDERS::HistorySelectOrder(PosTicket) &&
(MT4ORDERS::IsTester || (::HistoryDealGetInteger(OpenTicket, DEAL_TIME_MSC) == ::HistoryOrderGetInteger(PosTicket, ORDER_TIME_DONE_MSC)))) ?
::HistoryOrderGetDouble(PosTicket, ORDER_PRICE_OPEN) : MT4ORDERS::Order.OpenPrice))
MT4ORDERS::Order.OpenPriceRequest = MT4ORDERS::Order.OpenPrice;
}
else
{
MT4ORDERS::Order.State = ORDER_STATE_FILLED;
MT4ORDERS::Order.ClosePriceRequest = MT4ORDERS::Order.ClosePrice;
MT4ORDERS::Order.OpenPriceRequest = MT4ORDERS::Order.OpenPrice;
}
if (StrComment != "")
MT4ORDERS::Order.Comment = StrComment;
}
if (!Res)
{
::Alert("HistoryOrderSelect(" + (string)OrderTicket + ") - BUG! MT4ORDERS - not Sync with History!");
MT4ORDERS::AlertLog();
::Print(__FILE__ + "\nVersion = " + __MT4ORDERS__ + "\nCompiler = " + (string)__MQLBUILD__ + "\n" + TOSTR(__DATE__) +
TOSTR(::AccountInfoString(ACCOUNT_SERVER)) + TOSTR2((ENUM_ACCOUNT_TRADE_MODE)::AccountInfoInteger(ACCOUNT_TRADE_MODE)) +
TOSTR((bool)::TerminalInfoInteger(TERMINAL_CONNECTED)) +
TOSTR(::TerminalInfoInteger(TERMINAL_PING_LAST)) + TOSTR(::TerminalInfoDouble(TERMINAL_RETRANSMISSION)) +
TOSTR(::TerminalInfoInteger(TERMINAL_BUILD)) + TOSTR((bool)::TerminalInfoInteger(TERMINAL_X64)) +
TOSTR((bool)::TerminalInfoInteger(TERMINAL_VPS)) + TOSTR2((ENUM_PROGRAM_TYPE)::MQLInfoInteger(MQL_PROGRAM_TYPE)) +
TOSTR(::TimeCurrent()) + TOSTR(::TimeTradeServer()) + TOSTR(MT4ORDERS::TimeToString(MT4ORDERS::GetTimeCurrent())) +
TOSTR(::SymbolInfoString(MT4ORDERS::Order.Symbol, SYMBOL_PATH)) + TOSTR(::SymbolInfoString(MT4ORDERS::Order.Symbol, SYMBOL_DESCRIPTION)) +
"CurrentTick =" + MT4ORDERS::TickToString(MT4ORDERS::Order.Symbol) + "\n" +
TOSTR(::PositionsTotal()) + TOSTR(::OrdersTotal()) +
TOSTR(::HistorySelect(0, INT_MAX)) + TOSTR(::HistoryDealsTotal()) + TOSTR(::HistoryOrdersTotal()) +
TOSTR(::TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)) + TOSTR(::TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL)) +
TOSTR(::TerminalInfoInteger(TERMINAL_MEMORY_TOTAL)) + TOSTR(::TerminalInfoInteger(TERMINAL_MEMORY_USED)) +
TOSTR(::MQLInfoInteger(MQL_MEMORY_LIMIT)) + TOSTR(::MQLInfoInteger(MQL_MEMORY_USED)) +
TOSTR(Ticket) + TOSTR(OrderTicket) + TOSTR(OpenTicket) + TOSTR(PosTicket) +
TOSTR(MT4ORDERS::TimeToString(MT4ORDERS::Order.CloseTimeMsc)) +
TOSTR(MT4ORDERS::HistorySelectOrder(OrderTicket)) + TOSTR(::OrderSelect(OrderTicket)) +
(::OrderSelect(OrderTicket) ? TOSTR2((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE)) : NULL) +
(::HistoryDealsTotal() ? TOSTR(::HistoryDealGetTicket(::HistoryDealsTotal() - 1)) +
"DEAL_TIME_MSC = " + MT4ORDERS::TimeToString(::HistoryDealGetInteger(::HistoryDealGetTicket(::HistoryDealsTotal() - 1), DEAL_TIME_MSC)) + "\n"
: NULL) +
(::HistoryOrdersTotal() ? TOSTR(::HistoryOrderGetTicket(::HistoryOrdersTotal() - 1)) +
"ORDER_TIME_DONE_MSC = " + MT4ORDERS::TimeToString(::HistoryOrderGetInteger(::HistoryOrderGetTicket(::HistoryOrdersTotal() - 1), ORDER_TIME_DONE_MSC)) + "\n"
: NULL));
}
}
else
{
MT4ORDERS::Order.TicketOpen = MT4ORDERS::Order.Ticket;
if (!MT4ORDERS::Order.TicketID && (MT4ORDERS::Order.Type <= OP_SELL)) // The balance sheet ID must remain zero
MT4ORDERS::Order.TicketID = MT4ORDERS::Order.Ticket;
MT4ORDERS::Order.OpenPrice = MT4ORDERS::Order.ClosePrice;
MT4ORDERS::Order.OpenTimeMsc = MT4ORDERS::Order.CloseTimeMsc;
MT4ORDERS::Order.OpenTime = MT4ORDERS::Order.CloseTime;
MT4ORDERS::Order.OpenReason = MT4ORDERS::Order.CloseReason;
MT4ORDERS::Order.State = ORDER_STATE_FILLED;
MT4ORDERS::Order.ClosePriceRequest = MT4ORDERS::Order.ClosePrice;
MT4ORDERS::Order.OpenPriceRequest = MT4ORDERS::Order.OpenPrice;
}
if (OrderTicket)
{
bool Res = MT4ORDERS::IsTester ? MT4ORDERS::HistorySelectOrder(OrderTicket) : MT4ORDERS::Waiting(true);
if (!Res)
WHILE(_B2(MT4ORDERS::HistorySelectOrder(OrderTicket))) //
;
if ((ENUM_ORDER_TYPE)::HistoryOrderGetInteger(OrderTicket, ORDER_TYPE) == ORDER_TYPE_CLOSE_BY)
{
const ulong PosTicketBy = ::HistoryOrderGetInteger(OrderTicket, ORDER_POSITION_BY_ID);
if (PosTicketBy == PosTicket) // CloseBy-Slave should not affect trade.
{
MT4ORDERS::Order.Lots = 0;
MT4ORDERS::Order.Commission = 0;
MT4ORDERS::Order.ClosePrice = MT4ORDERS::Order.OpenPrice;
MT4ORDERS::Order.ClosePriceRequest = MT4ORDERS::Order.ClosePrice;
}
else // CloseBy-Master must receive a commission from CloseBy-Slave
{
const ulong OpenTicketBy = (OrderTicket > 0) ? _B2(MT4ORDERS::History.GetPositionDealIn(PosTicketBy)) : 0;
if ((OpenTicketBy > 0) && _B2(MT4ORDERS::HistorySelectDeal(OpenTicketBy)))
{
const double OpenLots = ::HistoryDealGetDouble(OpenTicketBy, DEAL_VOLUME);
if (OpenLots > 0)
MT4ORDERS::Order.Commission += ::HistoryDealGetDouble(OpenTicketBy, DEAL_COMMISSION) * MT4ORDERS::Order.Lots / OpenLots;
}
}
}
}
return;
}
static bool Waiting( const bool FlagInit = false )
{
static ulong StartTime = 0;
const bool Res = FlagInit ? false : (::GetMicrosecondCount() - StartTime < MT4ORDERS::OrderSend_MaxPause);
if (FlagInit)
{
StartTime = ::GetMicrosecondCount();
MT4ORDERS::OrderSendBug = 0;
}
else if (Res)
{
MT4ORDERS::OrderSendBug++;
}
return(Res);
}
static bool EqualPrices( const double Price1, const double &Price2, const int &digits)
{
return(!::NormalizeDouble(Price1 - Price2, digits));
}
static bool HistoryDealSelect2( MqlTradeResult &Result ) // At the end of the name is a number for greater compatibility with macros
{
#ifdef MT4ORDERS_HISTORY_OLD
if (!Result.deal && Result.order && _B3(::HistorySelectByPosition(::HistoryOrderGetInteger(Result.order, ORDER_POSITION_ID))))
{
#else // #ifdef MT4ORDERS_HISTORY_OLD
if (!Result.deal && Result.order && _B2(MT4ORDERS::HistorySelectOrder(Result.order)))
{
const long OrderTimeFill = ::HistoryOrderGetInteger(Result.order, ORDER_TIME_DONE_MSC);
#endif // #ifdef MT4ORDERS_HISTORY_OLD #else
for (int i = ::HistoryDealsTotal() - 1; i >= 0; i--)
{
const ulong DealTicket = ::HistoryDealGetTicket(i);
if (Result.order == ::HistoryDealGetInteger(DealTicket, DEAL_ORDER))
{
Result.deal = DealTicket;
Result.price = ::HistoryDealGetDouble(DealTicket, DEAL_PRICE);
break;
}
#ifndef MT4ORDERS_HISTORY_OLD
else if (::HistoryDealGetInteger(DealTicket, DEAL_TIME_MSC) < OrderTimeFill)
break;
#endif // #ifndef MT4ORDERS_HISTORY_OLD
}
}
return(_B2(MT4ORDERS::HistorySelectDeal(Result.deal)));
}
#define TMP_MT4ORDERS_BENCHMARK(A) \
static ulong Max##A = 0; \
\
if (Interval##A > Max##A) \
{ \
MT4ORDERS_BENCHMARK \
\
Max##A = Interval##A; \
}
static void OrderSend_Benchmark( const ulong &Interval1, const ulong &Interval2 )
{
#ifdef MT4ORDERS_BENCHMARK
TMP_MT4ORDERS_BENCHMARK(1)
TMP_MT4ORDERS_BENCHMARK(2)
#endif // MT4ORDERS_BENCHMARK
return;
}
#undef TMP_MT4ORDERS_BENCHMARK
static string ToString( const MqlTradeRequest &Request )
{
return(TOSTR2(Request.action) + TOSTR(Request.magic) + TOSTR(Request.order) +
TOSTR(Request.symbol) + TOSTR(Request.volume) + TOSTR(Request.price) +
TOSTR(Request.stoplimit) + TOSTR(Request.sl) + TOSTR(Request.tp) +
TOSTR(Request.deviation) + TOSTR2(Request.type) + TOSTR2(Request.type_filling) +
TOSTR2(Request.type_time) + TOSTR(Request.expiration) + TOSTR(Request.comment) +
TOSTR(Request.position) + TOSTR(Request.position_by));
}
static string ToString( const MqlTradeResult &Result )
{
return(TOSTR(Result.retcode) + TOSTR(Result.deal) + TOSTR(Result.order) +
TOSTR(Result.volume) + TOSTR(Result.price) + TOSTR(Result.bid) +
TOSTR(Result.ask) + TOSTR(Result.comment) + TOSTR(Result.request_id) +
TOSTR(Result.retcode_external));
}
static bool OrderSend( const MqlTradeRequest &Request, MqlTradeResult &Result )
{
MqlTick PrevTick = {0};
if (!MT4ORDERS::IsTester)
::SymbolInfoTick(Request.symbol, PrevTick); // Может тормозить.
const long PrevTimeCurrent = MT4ORDERS::IsTester ? 0 : MT4ORDERS::GetTimeCurrent();
const ulong StartTime1 = MT4ORDERS::IsTester ? 0 : ::GetMicrosecondCount();
bool Res = ::OrderSend(Request, Result);
const ulong Interval1 = MT4ORDERS::IsTester ? 0 : (::GetMicrosecondCount() - StartTime1);
const ulong StartTime2 = MT4ORDERS::IsTester ? 0 : ::GetMicrosecondCount();
if (!MT4ORDERS::IsTester && Res && (Result.retcode < TRADE_RETCODE_ERROR) && (MT4ORDERS::OrderSend_MaxPause > 0))
{
Res = (Result.retcode == TRADE_RETCODE_DONE);
MT4ORDERS::Waiting(true);
if (Request.action == TRADE_ACTION_DEAL)
{
if (!Result.deal)
{
WHILE(_B2(::OrderSelect(Result.order)) || _B2(MT4ORDERS::HistorySelectOrder(Result.order)))
;
if (!Res)
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR(::OrderSelect(Result.order)) + TOSTR(MT4ORDERS::HistorySelectOrder(Result.order)));
else if (::OrderSelect(Result.order) && !(Res = ((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED) ||
((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) == ORDER_STATE_PARTIAL)))
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR(::OrderSelect(Result.order)) + TOSTR2((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE)));
}
if (Res)
{
const bool ResultDeal = (!Result.deal) && (!MT4ORDERS::OrderSendBug);
if (MT4ORDERS::OrderSendBug && (!Result.deal))
::Print("Line = " + (string)__LINE__ + "\n" + "Before ::HistoryOrderSelect(Result.order):\n" + TOSTR(MT4ORDERS::OrderSendBug) + TOSTR(Result.deal));
WHILE(_B2(MT4ORDERS::HistorySelectOrder(Result.order)))
;
if (ResultDeal)
MT4ORDERS::OrderSendBug = 0;
if (!Res)
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR(MT4ORDERS::HistorySelectOrder(Result.order)) + TOSTR(MT4ORDERS::HistorySelectDeal(Result.deal)) + TOSTR(::OrderSelect(Result.order)));
else if (!(Res = ((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_FILLED) ||
((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_PARTIAL)))
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR2((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE)));
}
if (Res)
{
const bool ResultDeal = (!Result.deal) && (!MT4ORDERS::OrderSendBug);
if (MT4ORDERS::OrderSendBug && (!Result.deal))
::Print("Line = " + (string)__LINE__ + "\n" + "Before MT4ORDERS::HistoryDealSelect(Result):\n" + TOSTR(MT4ORDERS::OrderSendBug) + TOSTR(Result.deal));
WHILE(MT4ORDERS::HistoryDealSelect2(Result))
;
if (ResultDeal)
MT4ORDERS::OrderSendBug = 0;
if (!Res)
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR(MT4ORDERS::HistoryDealSelect2(Result)));
}
}
else if (Request.action == TRADE_ACTION_PENDING)
{
if (Res)
{
WHILE(_B2(::OrderSelect(Result.order)))
;
if (!Res)
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR(::OrderSelect(Result.order)));
else if (!(Res = ((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED) ||
((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) == ORDER_STATE_PARTIAL)))
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR2((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE)));
}
else
{
WHILE(_B2(MT4ORDERS::HistorySelectOrder(Result.order)))
;
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR(MT4ORDERS::HistorySelectOrder(Result.order)));
Res = false;
}
}
else if (Request.action == TRADE_ACTION_SLTP)
{
if (Res)
{
const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);
bool EqualSL = false;
bool EqualTP = false;
do
if (Request.position ? _B2(::PositionSelectByTicket(Request.position)) : _B2(::PositionSelect(Request.symbol)))
{
EqualSL = MT4ORDERS::EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
EqualTP = MT4ORDERS::EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
}
WHILE(EqualSL && EqualTP);
if (!Res)
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR(::PositionGetDouble(POSITION_SL)) + TOSTR(::PositionGetDouble(POSITION_TP)) +
TOSTR(EqualSL) + TOSTR(EqualTP) +
TOSTR(Request.position ? ::PositionSelectByTicket(Request.position) : ::PositionSelect(Request.symbol)));
}
}
else if (Request.action == TRADE_ACTION_MODIFY)
{
if (Res)
{
const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);
bool EqualSL = false;
bool EqualTP = false;
bool EqualPrice = false;
do
if (_B2(::OrderSelect(Result.order)) && ((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) != ORDER_STATE_REQUEST_MODIFY))
{
EqualSL = MT4ORDERS::EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
EqualTP = MT4ORDERS::EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
EqualPrice = MT4ORDERS::EqualPrices(::OrderGetDouble(ORDER_PRICE_OPEN), Request.price, digits);
}
WHILE((EqualSL && EqualTP && EqualPrice));
if (!Res)
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR(::OrderGetDouble(ORDER_SL)) + TOSTR(Request.sl)+
TOSTR(::OrderGetDouble(ORDER_TP)) + TOSTR(Request.tp) +
TOSTR(::OrderGetDouble(ORDER_PRICE_OPEN)) + TOSTR(Request.price) +
TOSTR(EqualSL) + TOSTR(EqualTP) + TOSTR(EqualPrice) +
TOSTR(::OrderSelect(Result.order)) +
TOSTR2((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE)));
}
}
else if (Request.action == TRADE_ACTION_REMOVE)
{
if (Res)
WHILE(_B2(MT4ORDERS::HistorySelectOrder(Result.order)))
;
if (!Res)
::Print("Line = " + (string)__LINE__ + "\n" + TOSTR(MT4ORDERS::HistorySelectOrder(Result.order)));
}
const ulong Interval2 = ::GetMicrosecondCount() - StartTime2;
Result.comment += " " + ::DoubleToString(Interval1 / 1000.0, 3) + " + " +
::DoubleToString(Interval2 / 1000.0, 3) + " (" + (string)MT4ORDERS::OrderSendBug + ") ms.";
if (!Res || MT4ORDERS::OrderSendBug)
{
::Alert(Res ? "OrderSend(" + (string)Result.order + ") - BUG!" : "MT4ORDERS - not Sync with History!");
MT4ORDERS::AlertLog();
::Print(__FILE__ + "\nVersion = " + __MT4ORDERS__ + "\nCompiler = " + (string)__MQLBUILD__ + "\n" + TOSTR(__DATE__) +
TOSTR(::AccountInfoString(ACCOUNT_SERVER)) + TOSTR2((ENUM_ACCOUNT_TRADE_MODE)::AccountInfoInteger(ACCOUNT_TRADE_MODE)) +
TOSTR((bool)::TerminalInfoInteger(TERMINAL_CONNECTED)) +
TOSTR(::TerminalInfoInteger(TERMINAL_PING_LAST)) + TOSTR(::TerminalInfoDouble(TERMINAL_RETRANSMISSION)) +
TOSTR(::TerminalInfoInteger(TERMINAL_BUILD)) + TOSTR((bool)::TerminalInfoInteger(TERMINAL_X64)) +
TOSTR((bool)::TerminalInfoInteger(TERMINAL_VPS)) + TOSTR2((ENUM_PROGRAM_TYPE)::MQLInfoInteger(MQL_PROGRAM_TYPE)) +
TOSTR(::TimeCurrent()) + TOSTR(::TimeTradeServer()) +
TOSTR(MT4ORDERS::TimeToString(MT4ORDERS::GetTimeCurrent())) + TOSTR(MT4ORDERS::TimeToString(PrevTimeCurrent)) +
"PrevTick =" + MT4ORDERS::TickToString(Request.symbol, PrevTick) + "\n" +
"CurrentTick =" + MT4ORDERS::TickToString(Request.symbol) + "\n" +
TOSTR(::SymbolInfoString(Request.symbol, SYMBOL_PATH)) + TOSTR(::SymbolInfoString(Request.symbol, SYMBOL_DESCRIPTION)) +
TOSTR(::PositionsTotal()) + TOSTR(::OrdersTotal()) +
TOSTR(::HistorySelect(0, INT_MAX)) + TOSTR(::HistoryDealsTotal()) + TOSTR(::HistoryOrdersTotal()) +
(::HistoryDealsTotal() ? TOSTR(::HistoryDealGetTicket(::HistoryDealsTotal() - 1)) +
"DEAL_TIME_MSC = " + MT4ORDERS::TimeToString(::HistoryDealGetInteger(::HistoryDealGetTicket(::HistoryDealsTotal() - 1), DEAL_TIME_MSC)) + "\n"
: NULL) +
(::HistoryOrdersTotal() ? TOSTR(::HistoryOrderGetTicket(::HistoryOrdersTotal() - 1)) +
"ORDER_TIME_DONE_MSC = " + MT4ORDERS::TimeToString(::HistoryOrderGetInteger(::HistoryOrderGetTicket(::HistoryOrdersTotal() - 1), ORDER_TIME_DONE_MSC)) + "\n"
: NULL) +
TOSTR(::TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)) + TOSTR(::TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL)) +
TOSTR(::TerminalInfoInteger(TERMINAL_MEMORY_TOTAL)) + TOSTR(::TerminalInfoInteger(TERMINAL_MEMORY_USED)) +
TOSTR(::MQLInfoInteger(MQL_MEMORY_LIMIT)) + TOSTR(::MQLInfoInteger(MQL_MEMORY_USED)) +
TOSTR(MT4ORDERS::IsHedging) + TOSTR(Res) + TOSTR(MT4ORDERS::OrderSendBug) +
MT4ORDERS::ToString(Request) + MT4ORDERS::ToString(Result));
}
else
MT4ORDERS::OrderSend_Benchmark(Interval1, Interval2);
}
else if (!MT4ORDERS::IsTester && MT4ORDERS::OrderSend_MaxPause)
{
Result.comment += " " + ::DoubleToString(Interval1 / 1000.0, 3) + " ms";
::Print(TOSTR(::TimeCurrent()) + TOSTR(::TimeTradeServer()) + TOSTR(MT4ORDERS::TimeToString(PrevTimeCurrent)) +
MT4ORDERS::TickToString(Request.symbol, PrevTick) + "\n" + MT4ORDERS::TickToString(Request.symbol) + "\n" +
MT4ORDERS::ToString(Request) + MT4ORDERS::ToString(Result));
}
return(Res);
}
#undef TOSTR2
#undef TOSTR
#undef WHILE
static ENUM_DAY_OF_WEEK GetDayOfWeek( const datetime &time )
{
MqlDateTime sTime = {0};
::TimeToStruct(time, sTime);
return((ENUM_DAY_OF_WEEK)sTime.day_of_week);
}
static bool SessionTrade( const string &Symb )
{
datetime TimeNow = ::TimeCurrent();
const ENUM_DAY_OF_WEEK DayOfWeek = MT4ORDERS::GetDayOfWeek(TimeNow);
TimeNow %= 24 * 60 * 60;
bool Res = false;
datetime From, To;
for (int i = 0; (!Res) && ::SymbolInfoSessionTrade(Symb, DayOfWeek, i, From, To); i++)
Res = ((From <= TimeNow) && (TimeNow < To));
return(Res);
}
static bool SymbolTrade( const string &Symb )
{
MqlTick Tick;
return(::SymbolInfoTick(Symb, Tick) ? (Tick.bid && Tick.ask && MT4ORDERS::SessionTrade(Symb)) : false);
}
static bool CorrectResult( void )
{
::ZeroMemory(MT4ORDERS::LastTradeResult);
MT4ORDERS::LastTradeResult.retcode = MT4ORDERS::LastTradeCheckResult.retcode;
MT4ORDERS::LastTradeResult.comment = MT4ORDERS::LastTradeCheckResult.comment;
return(false);
}
static bool NewOrderCheck( void )
{
return((::OrderCheck(MT4ORDERS::LastTradeRequest, MT4ORDERS::LastTradeCheckResult) &&
(MT4ORDERS::IsTester || MT4ORDERS::SymbolTrade(MT4ORDERS::LastTradeRequest.symbol))) ||
(!MT4ORDERS::IsTester && MT4ORDERS::CorrectResult()));
}
static bool NewOrderSend( const int &Check )
{
return((Check == INT_MAX) ? MT4ORDERS::NewOrderCheck() :
(((Check != INT_MIN) || MT4ORDERS::NewOrderCheck()) && MT4ORDERS::OrderSend(MT4ORDERS::LastTradeRequest, MT4ORDERS::LastTradeResult) ? MT4ORDERS::LastTradeResult.retcode < TRADE_RETCODE_ERROR : false));
}
static bool ModifyPosition( const long &Ticket, MqlTradeRequest &Request )
{
const bool Res = _B2(::PositionSelectByTicket(Ticket));
if (Res)
{
Request.action = TRADE_ACTION_SLTP;
Request.position = Ticket;
Request.symbol = ::PositionGetString(POSITION_SYMBOL); // One ticket is not enough!
}
return(Res);
}
static ENUM_ORDER_TYPE_FILLING GetFilling( const string &Symb, const uint Type = ORDER_FILLING_FOK )
{
static ENUM_ORDER_TYPE_FILLING Res = ORDER_FILLING_FOK;
static string LastSymb = NULL;
static uint LastType = ORDER_FILLING_FOK;
const bool SymbFlag = (LastSymb != Symb);
if (SymbFlag || (LastType != Type)) // You can speed up a little by changing the order of checking the conditions
{
LastType = Type;
if (SymbFlag)
LastSymb = Symb;
const ENUM_SYMBOL_TRADE_EXECUTION ExeMode = (ENUM_SYMBOL_TRADE_EXECUTION)::SymbolInfoInteger(Symb, SYMBOL_TRADE_EXEMODE);
const int FillingMode = (int)::SymbolInfoInteger(Symb, SYMBOL_FILLING_MODE);
Res = (!FillingMode || (Type >= ORDER_FILLING_RETURN) || ((FillingMode & (Type + 1)) != Type + 1)) ?
(((ExeMode == SYMBOL_TRADE_EXECUTION_EXCHANGE) || (ExeMode == SYMBOL_TRADE_EXECUTION_INSTANT)) ?
ORDER_FILLING_RETURN : ((FillingMode == SYMBOL_FILLING_IOC) ? ORDER_FILLING_IOC : ORDER_FILLING_FOK)) :
(ENUM_ORDER_TYPE_FILLING)Type;
}
return(Res);
}
static ENUM_ORDER_TYPE_TIME GetExpirationType( const string &Symb, uint Expiration = ORDER_TIME_GTC )
{
static ENUM_ORDER_TYPE_TIME Res = ORDER_TIME_GTC;
static string LastSymb = NULL;
static uint LastExpiration = ORDER_TIME_GTC;
const bool SymbFlag = (LastSymb != Symb);
if ((LastExpiration != Expiration) || SymbFlag)
{
LastExpiration = Expiration;
if (SymbFlag)
LastSymb = Symb;
const int ExpirationMode = (int)::SymbolInfoInteger(Symb, SYMBOL_EXPIRATION_MODE);
if ((Expiration > ORDER_TIME_SPECIFIED_DAY) || (!((ExpirationMode >> Expiration) & 1)))
{
if ((Expiration < ORDER_TIME_SPECIFIED) || (ExpirationMode < SYMBOL_EXPIRATION_SPECIFIED))
Expiration = ORDER_TIME_GTC;
else if (Expiration > ORDER_TIME_DAY)
Expiration = ORDER_TIME_SPECIFIED;
uint i = 1 << Expiration;
while ((Expiration <= ORDER_TIME_SPECIFIED_DAY) && ((ExpirationMode & i) != i))
{
i <<= 1;
Expiration++;
}
}
Res = (ENUM_ORDER_TYPE_TIME)Expiration;
}
return(Res);
}
static bool ModifyOrder( const long Ticket, const double &Price, const datetime &Expiration, MqlTradeRequest &Request )
{
const bool Res = _B2(::OrderSelect(Ticket));
if (Res)
{
Request.action = TRADE_ACTION_MODIFY;
Request.order = Ticket;
Request.price = Price;
Request.symbol = ::OrderGetString(ORDER_SYMBOL);
Request.type_filling = _B2(MT4ORDERS::GetFilling(Request.symbol));
Request.type_time = _B2(MT4ORDERS::GetExpirationType(Request.symbol, (uint)Expiration));
if (Expiration > ORDER_TIME_DAY)
Request.expiration = Expiration;
}
return(Res);
}
static bool SelectByPosHistory( const int Index )
{
const long Ticket = MT4ORDERS::History[Index];
const bool Res = (Ticket > 0) ? _B2(MT4ORDERS::HistorySelectDeal(Ticket)) : ((Ticket < 0) && _B2(MT4ORDERS::HistorySelectOrder(-Ticket)));
if (Res)
{
if (Ticket > 0)
_BV2(MT4ORDERS::GetHistoryPositionData(Ticket))
else
_BV2(MT4ORDERS::GetHistoryOrderData(-Ticket))
}
return(Res);
}
static bool OrderVisible( void )
{
bool Market = false;
bool Res = !(::OrderGetInteger(ORDER_POSITION_ID) &&
(Market = (::OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL))); // Partial-delayer has non-zero PositionID
if (Res && Market)
{
const long Ticket = ::PositionGetInteger(POSITION_TICKET);
if (_B2(::PositionSelectByTicket(::OrderGetInteger(ORDER_TICKET)))) // The order and its position can be simultaneous - this condition will help only on Hedge accounts
{
if (Ticket && (::PositionGetInteger(POSITION_TICKET) != Ticket))
_B2(::PositionSelectByTicket(Ticket));
Res = false;
}
}
return(Res);
}
static ulong OrderGetTicket( const int Index )
{
ulong Res;
int PrevTotal;
const long PrevTicket = ::OrderGetInteger(ORDER_TICKET);
do
{
Res = 0;
PrevTotal = ::OrdersTotal();
if ((Index >= 0) && (Index < PrevTotal))
{
int Count = 0;
for (int i = 0; i < PrevTotal; i++)
{
const int Total = ::OrdersTotal();
if (Total != PrevTotal)
{
PrevTotal = Total;
Count = 0;
i = -1;
}
else
{
const ulong Ticket = ::OrderGetTicket(i);
if (Ticket && MT4ORDERS::OrderVisible())
{
if (Count == Index)
{
Res = Ticket;
break;
}
Count++;
}
}
}
if (!Res && PrevTicket && (::OrderGetInteger(ORDER_TICKET) != PrevTicket))
const bool AntiWarning = _B2(::OrderSelect(PrevTicket));
}
} while (PrevTotal != ::OrdersTotal()); // The number of orders may change during the search
return(Res);
}
static bool SelectByPos( const int Index )
{
bool Flag = (Index == INT_MAX);
bool Res = Flag || (Index == INT_MIN);
if (!Res)
{
const int Total = ::PositionsTotal();
Flag = (Index < Total);
Res = (Flag) ? _B2(::PositionGetTicket(Index)) :
#ifdef MT4ORDERS_SELECTFILTER_OFF
::OrderGetTicket(Index - Total);
#else // MT4ORDERS_SELECTFILTER_OFF
(MT4ORDERS::IsTester ? ::OrderGetTicket(Index - Total) : _B2(MT4ORDERS::OrderGetTicket(Index - Total)));
#endif //MT4ORDERS_SELECTFILTER_OFF
}
if (Res)
{
if (Flag)
MT4ORDERS::GetPositionData(); // (Index == INT_MAX) - switch to MT5 position without checking for existence and updating
else
MT4ORDERS::GetOrderData(); // (Index == INT_MIN) - switch to a live MT5 order without checking for existence and updating
}
return(Res);
}
static bool SelectByHistoryTicket( const long &Ticket )
{
bool Res = false;
if (!Ticket) // Selection by OrderTicketID (zero value - balance operations)
{
const ulong TicketDealOut = MT4ORDERS::History.GetPositionDealOut(Ticket);
if (Res = _B2(MT4ORDERS::HistorySelectDeal(TicketDealOut)))
_BV2(MT4ORDERS::GetHistoryPositionData(TicketDealOut));
}
else if (_B2(MT4ORDERS::HistorySelectDeal(Ticket)))
{
if (Res = MT4HISTORY::IsMT4Deal(Ticket))
_BV2(MT4ORDERS::GetHistoryPositionData(Ticket))
else
{
const ulong TicketDealOut = MT4ORDERS::History.GetPositionDealOut(HistoryDealGetInteger(Ticket, DEAL_POSITION_ID)); // DealIn selection
if (Res = _B2(MT4ORDERS::HistorySelectDeal(TicketDealOut)))
_BV2(MT4ORDERS::GetHistoryPositionData(TicketDealOut))
}
}
else if (_B2(MT4ORDERS::HistorySelectOrder(Ticket)))
{
if (Res = MT4HISTORY::IsMT4Order(Ticket))
_BV2(MT4ORDERS::GetHistoryOrderData(Ticket))
else
{
const ulong TicketDealOut = MT4ORDERS::History.GetPositionDealOut(HistoryOrderGetInteger(Ticket, ORDER_POSITION_ID));
if (Res = _B2(MT4ORDERS::HistorySelectDeal(TicketDealOut)))
_BV2(MT4ORDERS::GetHistoryPositionData(TicketDealOut));
}
}
else
{
const ulong TicketDealOut = MT4ORDERS::History.GetPositionDealOut(Ticket);
if (Res = _B2(MT4ORDERS::HistorySelectDeal(TicketDealOut)))
_BV2(MT4ORDERS::GetHistoryPositionData(TicketDealOut));
}
return(Res);
}
static bool SelectByExistingTicket( const long &Ticket )
{
bool Res = true;
if (Ticket < 0)
{
if (_B2(::OrderSelect(-Ticket)))
MT4ORDERS::GetOrderData();
else if (_B2(::PositionSelectByTicket(-Ticket)))
MT4ORDERS::GetPositionData();
else
Res = false;
}
else if (_B2(::PositionSelectByTicket(Ticket)))
MT4ORDERS::GetPositionData();
else if (_B2(::OrderSelect(Ticket)))
MT4ORDERS::GetOrderData();
else if (_B2(MT4ORDERS::HistorySelectDeal(Ticket)))
{
if (MT4HISTORY::IsMT4Deal(Ticket)) // If a choice is made by DealOut
_BV2(MT4ORDERS::GetHistoryPositionData(Ticket))
else if (_B2(::PositionSelectByTicket(::HistoryDealGetInteger(Ticket, DEAL_POSITION_ID)))) // DealIn selection
MT4ORDERS::GetPositionData();
else
Res = false;
}
else if (_B2(MT4ORDERS::HistorySelectOrder(Ticket)) && _B2(::PositionSelectByTicket(::HistoryOrderGetInteger(Ticket, ORDER_POSITION_ID)))) // Выбор по тикету MT5-ордера
MT4ORDERS::GetPositionData();
else
Res = false;
return(Res);
}
static bool SelectByTicket( const long &Ticket, const int &Pool )
{
return((Pool == MODE_TRADES) || (Ticket < 0) ?
(_B2(MT4ORDERS::SelectByExistingTicket(Ticket)) || ((Ticket > 0) && _B2(MT4ORDERS::SelectByHistoryTicket(Ticket)))) :
(_B2(MT4ORDERS::SelectByHistoryTicket(Ticket)) || _B2(MT4ORDERS::SelectByExistingTicket(Ticket))));
}
#ifdef MT4ORDERS_SLTP_OLD
static void CheckPrices( double &MinPrice, double &MaxPrice, const double Min, const double Max )
{
if (MinPrice && (MinPrice >= Min))
MinPrice = 0;
if (MaxPrice && (MaxPrice <= Max))
MaxPrice = 0;
return;
}
#endif // MT4ORDERS_SLTP_OLD
static int OrdersTotal( void )
{
int Res = 0;
const long PrevTicket = ::OrderGetInteger(ORDER_TICKET);
int PrevTotal;
do
{
PrevTotal = ::OrdersTotal();
for (int i = PrevTotal - 1; i >= 0; i--)
{
const int Total = ::OrdersTotal();
if (Total != PrevTotal)
{
PrevTotal = Total;
Res = 0;
i = PrevTotal;
}
else if (::OrderGetTicket(i) && MT4ORDERS::OrderVisible())
Res++;
}
} while (PrevTotal != ::OrdersTotal()); // The number of orders may change during the search
if (PrevTicket && (::OrderGetInteger(ORDER_TICKET) != PrevTicket))
const bool AntiWarning = _B2(::OrderSelect(PrevTicket));
return(Res);
}
public:
static uint OrderSend_MaxPause; // Maximum time for synchronization in microseconds
static MqlTradeResult LastTradeResult;
static MqlTradeRequest LastTradeRequest;
static MqlTradeCheckResult LastTradeCheckResult;
static bool MT4OrderSelect( const long &Index, const int &Select, const int &Pool )
{
return((Select == SELECT_BY_POS) ?
((Pool == MODE_TRADES) ? _B2(MT4ORDERS::SelectByPos((int)Index)) : _B2(MT4ORDERS::SelectByPosHistory((int)Index))) :
_B2(MT4ORDERS::SelectByTicket(Index, Pool)));
}
static int MT4OrdersTotal( void )
{
#ifdef MT4ORDERS_SELECTFILTER_OFF
return(::OrdersTotal() + ::PositionsTotal());
#else // MT4ORDERS_SELECTFILTER_OFF
int Res;
if (MT4ORDERS::IsTester)
return(::OrdersTotal() + ::PositionsTotal());
else
{
int PrevTotal;
do
{
PrevTotal = ::PositionsTotal();
Res = _B2(MT4ORDERS::OrdersTotal()) + PrevTotal;
} while (PrevTotal != ::PositionsTotal()); // We only track changes in positions, because orders are tracked in MT4ORDERS :: OrdersTotal ()
}
return(Res); //
#endif //MT4ORDERS_SELECTFILTER_OFF
}
static int MT4OrdersTotal( const bool )
{
return(::OrdersTotal());
}
static int MT4OrdersHistoryTotal( void )
{
return(MT4ORDERS::History.GetAmount());
}
static long MT4OrderSend( const string &Symb, const int &Type, const double &dVolume, const double &Price, const int &SlipPage, const double &SL, const double &TP,
const string &comment, const MAGIC_TYPE &magic, const datetime &dExpiration, const color &arrow_color )
{
::ZeroMemory(MT4ORDERS::LastTradeRequest);
MT4ORDERS::LastTradeRequest.action = (((Type == OP_BUY) || (Type == OP_SELL)) ? TRADE_ACTION_DEAL : TRADE_ACTION_PENDING);
MT4ORDERS::LastTradeRequest.magic = magic;
MT4ORDERS::LastTradeRequest.symbol = ((Symb == NULL) ? ::Symbol() : Symb);
MT4ORDERS::LastTradeRequest.volume = dVolume;
MT4ORDERS::LastTradeRequest.price = Price;
MT4ORDERS::LastTradeRequest.tp = TP;
MT4ORDERS::LastTradeRequest.sl = SL;
MT4ORDERS::LastTradeRequest.deviation = SlipPage;
MT4ORDERS::LastTradeRequest.type = (ENUM_ORDER_TYPE)Type;
MT4ORDERS::LastTradeRequest.type_filling = _B2(MT4ORDERS::GetFilling(MT4ORDERS::LastTradeRequest.symbol, (uint)MT4ORDERS::LastTradeRequest.deviation));
if (MT4ORDERS::LastTradeRequest.action == TRADE_ACTION_PENDING)
{
MT4ORDERS::LastTradeRequest.type_time = _B2(MT4ORDERS::GetExpirationType(MT4ORDERS::LastTradeRequest.symbol, (uint)dExpiration));
if (dExpiration > ORDER_TIME_DAY)
MT4ORDERS::LastTradeRequest.expiration = dExpiration;
}
if (comment != NULL)
MT4ORDERS::LastTradeRequest.comment = comment;
return((arrow_color == INT_MAX) ? (MT4ORDERS::NewOrderCheck() ? 0 : -1) :
((((int)arrow_color != INT_MIN) || MT4ORDERS::NewOrderCheck()) &&
MT4ORDERS::OrderSend(MT4ORDERS::LastTradeRequest, MT4ORDERS::LastTradeResult) ?
(MT4ORDERS::IsHedging ? (long)MT4ORDERS::LastTradeResult.order : // PositionID == Result.order - особенность MT5-Hedge
((MT4ORDERS::LastTradeRequest.action == TRADE_ACTION_DEAL) ?
(MT4ORDERS::IsTester ? (_B2(::PositionSelect(MT4ORDERS::LastTradeRequest.symbol)) ? PositionGetInteger(POSITION_TICKET) : 0) :
::HistoryDealGetInteger(MT4ORDERS::LastTradeResult.deal, DEAL_POSITION_ID)) :
(long)MT4ORDERS::LastTradeResult.order)) : -1));
}
static bool MT4OrderModify( const long &Ticket, const double &Price, const double &SL, const double &TP, const datetime &Expiration, const color &Arrow_Color )
{
::ZeroMemory(MT4ORDERS::LastTradeRequest);
bool Res = (Ticket < 0) ? MT4ORDERS::ModifyOrder(-Ticket, Price, Expiration, MT4ORDERS::LastTradeRequest) :
((MT4ORDERS::Order.Ticket != ORDER_SELECT) ?
(MT4ORDERS::ModifyPosition(Ticket, MT4ORDERS::LastTradeRequest) || MT4ORDERS::ModifyOrder(Ticket, Price, Expiration, MT4ORDERS::LastTradeRequest)) :
(MT4ORDERS::ModifyOrder(Ticket, Price, Expiration, MT4ORDERS::LastTradeRequest) || MT4ORDERS::ModifyPosition(Ticket, MT4ORDERS::LastTradeRequest)));
{
MT4ORDERS::LastTradeRequest.tp = TP;
MT4ORDERS::LastTradeRequest.sl = SL;
Res = MT4ORDERS::NewOrderSend(Arrow_Color);
}
return(Res);
}
static bool MT4OrderClose( const long &Ticket, const double &dLots, const double &Price, const int &SlipPage, const color &Arrow_Color, const string &comment )
{
_B2(::PositionSelectByTicket(Ticket));
::ZeroMemory(MT4ORDERS::LastTradeRequest);
MT4ORDERS::LastTradeRequest.action = TRADE_ACTION_DEAL;
MT4ORDERS::LastTradeRequest.position = Ticket;
MT4ORDERS::LastTradeRequest.symbol = ::PositionGetString(POSITION_SYMBOL);
MT4ORDERS::LastTradeRequest.comment = (comment == NULL) ? ::PositionGetString(POSITION_COMMENT) : comment;
MT4ORDERS::LastTradeRequest.volume = dLots;
MT4ORDERS::LastTradeRequest.price = Price;
#ifdef MT4ORDERS_SLTP_OLD
MT4ORDERS::LastTradeRequest.tp = ::PositionGetDouble(POSITION_SL);
MT4ORDERS::LastTradeRequest.sl = ::PositionGetDouble(POSITION_TP);
if (MT4ORDERS::LastTradeRequest.tp || MT4ORDERS::LastTradeRequest.sl)
{
const double __StopLevel = ::SymbolInfoInteger(MT4ORDERS::LastTradeRequest.symbol, SYMBOL_TRADE_STOPS_LEVEL) *
::SymbolInfoDouble(MT4ORDERS::LastTradeRequest.symbol, SYMBOL_POINT);
const bool FlagBuy = (::PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY);
const double CurrentPrice = SymbolInfoDouble(MT4ORDERS::LastTradeRequest.symbol, FlagBuy ? SYMBOL_ASK : SYMBOL_BID);
if (CurrentPrice)
{
if (FlagBuy)
MT4ORDERS::CheckPrices(MT4ORDERS::LastTradeRequest.tp, MT4ORDERS::LastTradeRequest.sl, CurrentPrice - __StopLevel, CurrentPrice + __StopLevel);
else
MT4ORDERS::CheckPrices(MT4ORDERS::LastTradeRequest.sl, MT4ORDERS::LastTradeRequest.tp, CurrentPrice - __StopLevel, CurrentPrice + __StopLevel);
}
else
{
MT4ORDERS::LastTradeRequest.tp = 0;
MT4ORDERS::LastTradeRequest.sl = 0;
}
}
#endif // MT4ORDERS_SLTP_OLD
MT4ORDERS::LastTradeRequest.deviation = SlipPage;
MT4ORDERS::LastTradeRequest.type = (ENUM_ORDER_TYPE)(1 - ::PositionGetInteger(POSITION_TYPE));
MT4ORDERS::LastTradeRequest.type_filling = _B2(MT4ORDERS::GetFilling(MT4ORDERS::LastTradeRequest.symbol, (uint)MT4ORDERS::LastTradeRequest.deviation));
return(MT4ORDERS::NewOrderSend(Arrow_Color));
}
static bool MT4OrderCloseBy( const long &Ticket, const long &Opposite, const color &Arrow_Color )
{
::ZeroMemory(MT4ORDERS::LastTradeRequest);
MT4ORDERS::LastTradeRequest.action = TRADE_ACTION_CLOSE_BY;
MT4ORDERS::LastTradeRequest.position = Ticket;
MT4ORDERS::LastTradeRequest.position_by = Opposite;
if ((!MT4ORDERS::IsTester) && _B2(::PositionSelectByTicket(Ticket))) // Need for MT4ORDERS::SymbolTrade ()
MT4ORDERS::LastTradeRequest.symbol = ::PositionGetString(POSITION_SYMBOL);
return(MT4ORDERS::NewOrderSend(Arrow_Color));
}
static bool MT4OrderDelete( const long &Ticket, const color &Arrow_Color )
{
::ZeroMemory(MT4ORDERS::LastTradeRequest);
MT4ORDERS::LastTradeRequest.action = TRADE_ACTION_REMOVE;
MT4ORDERS::LastTradeRequest.order = Ticket;
if ((!MT4ORDERS::IsTester) && _B2(::OrderSelect(Ticket))) // Need for MT4ORDERS::SymbolTrade ()
MT4ORDERS::LastTradeRequest.symbol = ::OrderGetString(ORDER_SYMBOL);
return(MT4ORDERS::NewOrderSend(Arrow_Color));
}
#define MT4_ORDERFUNCTION(NAME,T,A,B,C) \
static T MT4Order##NAME( void ) \
{ \
return(POSITION_ORDER((T)(A), (T)(B), MT4ORDERS::Order.NAME, C)); \
}
#define POSITION_ORDER(A,B,C,D) (((MT4ORDERS::Order.Ticket == POSITION_SELECT) && (D)) ? (A) : ((MT4ORDERS::Order.Ticket == ORDER_SELECT) ? (B) : (C)))
MT4_ORDERFUNCTION(Ticket, long, ::PositionGetInteger(POSITION_TICKET), ::OrderGetInteger(ORDER_TICKET), true)
MT4_ORDERFUNCTION(Type, int, ::PositionGetInteger(POSITION_TYPE), ::OrderGetInteger(ORDER_TYPE), true)
MT4_ORDERFUNCTION(Lots, double, ::PositionGetDouble(POSITION_VOLUME), ::OrderGetDouble(ORDER_VOLUME_CURRENT), true)
MT4_ORDERFUNCTION(OpenPrice, double, ::PositionGetDouble(POSITION_PRICE_OPEN), (::OrderGetDouble(ORDER_PRICE_OPEN) ? ::OrderGetDouble(ORDER_PRICE_OPEN) : ::OrderGetDouble(ORDER_PRICE_CURRENT)), true)
MT4_ORDERFUNCTION(OpenTimeMsc, long, ::PositionGetInteger(POSITION_TIME_MSC), ::OrderGetInteger(ORDER_TIME_SETUP_MSC), true)
MT4_ORDERFUNCTION(OpenTime, datetime, ::PositionGetInteger(POSITION_TIME), ::OrderGetInteger(ORDER_TIME_SETUP), true)
MT4_ORDERFUNCTION(StopLoss, double, ::PositionGetDouble(POSITION_SL), ::OrderGetDouble(ORDER_SL), true)
MT4_ORDERFUNCTION(TakeProfit, double, ::PositionGetDouble(POSITION_TP), ::OrderGetDouble(ORDER_TP), true)
MT4_ORDERFUNCTION(ClosePrice, double, ::PositionGetDouble(POSITION_PRICE_CURRENT), ::OrderGetDouble(ORDER_PRICE_CURRENT), true)
MT4_ORDERFUNCTION(CloseTimeMsc, long, 0, 0, true)
MT4_ORDERFUNCTION(CloseTime, datetime, 0, 0, true)
MT4_ORDERFUNCTION(Expiration, datetime, 0, ::OrderGetInteger(ORDER_TIME_EXPIRATION), true)
MT4_ORDERFUNCTION(MagicNumber, long, ::PositionGetInteger(POSITION_MAGIC), ::OrderGetInteger(ORDER_MAGIC), true)
MT4_ORDERFUNCTION(Profit, double, ::PositionGetDouble(POSITION_PROFIT), 0, true)
MT4_ORDERFUNCTION(Swap, double, ::PositionGetDouble(POSITION_SWAP), 0, true)
MT4_ORDERFUNCTION(Symbol, string, ::PositionGetString(POSITION_SYMBOL), ::OrderGetString(ORDER_SYMBOL), true)
MT4_ORDERFUNCTION(Comment, string, MT4ORDERS::Order.Comment, ::OrderGetString(ORDER_COMMENT), MT4ORDERS::CheckPositionCommissionComment())
MT4_ORDERFUNCTION(Commission, double, MT4ORDERS::Order.Commission, 0, MT4ORDERS::CheckPositionCommissionComment())
MT4_ORDERFUNCTION(OpenPriceRequest, double, MT4ORDERS::Order.OpenPriceRequest, ::OrderGetDouble(ORDER_PRICE_OPEN), MT4ORDERS::CheckPositionOpenPriceRequest())
MT4_ORDERFUNCTION(ClosePriceRequest, double, ::PositionGetDouble(POSITION_PRICE_CURRENT), ::OrderGetDouble(ORDER_PRICE_CURRENT), true)
MT4_ORDERFUNCTION(TicketOpen, long, MT4ORDERS::Order.TicketOpen, ::OrderGetInteger(ORDER_TICKET), MT4ORDERS::CheckPositionTicketOpen())
MT4_ORDERFUNCTION(OpenReason, ENUM_DEAL_REASON, ::PositionGetInteger(POSITION_REASON), ::OrderGetInteger(ORDER_REASON), true)
MT4_ORDERFUNCTION(CloseReason, ENUM_DEAL_REASON, 0, ::OrderGetInteger(ORDER_REASON), true)
MT4_ORDERFUNCTION(TicketID, long, ::PositionGetInteger(POSITION_IDENTIFIER), ::OrderGetInteger(ORDER_TICKET), true)
#undef POSITION_ORDER
#undef MT4_ORDERFUNCTION
static void MT4OrderPrint( void )
{
if (MT4ORDERS::Order.Ticket == POSITION_SELECT)
MT4ORDERS::CheckPositionCommissionComment();
::Print(MT4ORDERS::Order.ToString());
return;
}
#undef ORDER_SELECT
#undef POSITION_SELECT
};
static MT4_ORDER MT4ORDERS::Order = {0};
static MT4HISTORY MT4ORDERS::History;
static const bool MT4ORDERS::IsTester = ::MQLInfoInteger(MQL_TESTER);
static const bool MT4ORDERS::IsHedging = ((ENUM_ACCOUNT_MARGIN_MODE)::AccountInfoInteger(ACCOUNT_MARGIN_MODE) ==
ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
static int MT4ORDERS::OrderSendBug = 0;
static uint MT4ORDERS::OrderSend_MaxPause = 1000000; // Maximum time for synchronization in microseconds
static MqlTradeResult MT4ORDERS::LastTradeResult = {0};
static MqlTradeRequest MT4ORDERS::LastTradeRequest;// = {0};
static MqlTradeCheckResult MT4ORDERS::LastTradeCheckResult = {0};
bool OrderClose( const long Ticket, const double dLots, const double Price, const int SlipPage, const color Arrow_Color = clrNONE, const string comment = NULL )
{
return(MT4ORDERS::MT4OrderClose(Ticket, dLots, Price, SlipPage, Arrow_Color, comment));
}
bool OrderModify( const long Ticket, const double Price, const double SL, const double TP, const datetime Expiration, const color Arrow_Color = clrNONE )
{
return(MT4ORDERS::MT4OrderModify(Ticket, Price, SL, TP, Expiration, Arrow_Color));
}
bool OrderCloseBy( const long Ticket, const long Opposite, const color Arrow_Color = clrNONE )
{
return(MT4ORDERS::MT4OrderCloseBy(Ticket, Opposite, Arrow_Color));
}
bool OrderDelete( const long Ticket, const color Arrow_Color = clrNONE )
{
return(MT4ORDERS::MT4OrderDelete(Ticket, Arrow_Color));
}
void OrderPrint( void )
{
MT4ORDERS::MT4OrderPrint();
return;
}
#define MT4_ORDERGLOBALFUNCTION(NAME,T) \
T Order##NAME( void ) \
{ \
return((T)MT4ORDERS::MT4Order##NAME()); \
}
MT4_ORDERGLOBALFUNCTION(sHistoryTotal, int)
MT4_ORDERGLOBALFUNCTION(Ticket, TICKET_TYPE)
MT4_ORDERGLOBALFUNCTION(Type, int)
MT4_ORDERGLOBALFUNCTION(Lots, double)
MT4_ORDERGLOBALFUNCTION(OpenPrice, double)
MT4_ORDERGLOBALFUNCTION(OpenTimeMsc, long)
MT4_ORDERGLOBALFUNCTION(OpenTime, datetime)
MT4_ORDERGLOBALFUNCTION(StopLoss, double)
MT4_ORDERGLOBALFUNCTION(TakeProfit, double)
MT4_ORDERGLOBALFUNCTION(ClosePrice, double)
MT4_ORDERGLOBALFUNCTION(CloseTimeMsc, long)
MT4_ORDERGLOBALFUNCTION(CloseTime, datetime)
MT4_ORDERGLOBALFUNCTION(Expiration, datetime)
MT4_ORDERGLOBALFUNCTION(MagicNumber, MAGIC_TYPE)
MT4_ORDERGLOBALFUNCTION(Profit, double)
MT4_ORDERGLOBALFUNCTION(Commission, double)
MT4_ORDERGLOBALFUNCTION(Swap, double)
MT4_ORDERGLOBALFUNCTION(Symbol, string)
MT4_ORDERGLOBALFUNCTION(Comment, string)
MT4_ORDERGLOBALFUNCTION(OpenPriceRequest, double)
MT4_ORDERGLOBALFUNCTION(ClosePriceRequest, double)
MT4_ORDERGLOBALFUNCTION(TicketOpen, long)
MT4_ORDERGLOBALFUNCTION(OpenReason, ENUM_DEAL_REASON)
MT4_ORDERGLOBALFUNCTION(CloseReason, ENUM_DEAL_REASON)
MT4_ORDERGLOBALFUNCTION(TicketID, long)
#undef MT4_ORDERGLOBALFUNCTION
#define OrdersTotal MT4ORDERS::MT4OrdersTotal // AFTER Expert / Expert.mqh - there is a call to MT5-OrdersTotal ()
bool OrderSelect( const long Index, const int Select, const int Pool = MODE_TRADES )
{
return(_B2(MT4ORDERS::MT4OrderSelect(Index, Select, Pool)));
}
TICKET_TYPE OrderSend( const string Symb, const int Type, const double dVolume, const double Price, const int SlipPage, const double SL, const double TP,
const string comment = NULL, const MAGIC_TYPE magic = 0, const datetime dExpiration = 0, color arrow_color = clrNONE )
{
return((TICKET_TYPE)MT4ORDERS::MT4OrderSend(Symb, Type, dVolume, Price, SlipPage, SL, TP, comment, magic, dExpiration, arrow_color));
}
#define RETURN_ASYNC(A) return((A) && ::OrderSendAsync(MT4ORDERS::LastTradeRequest, MT4ORDERS::LastTradeResult) && \
(MT4ORDERS::LastTradeResult.retcode == TRADE_RETCODE_PLACED) ? MT4ORDERS::LastTradeResult.request_id : 0);
uint OrderCloseAsync( const long Ticket, const double dLots, const double Price, const int SlipPage, const color Arrow_Color = clrNONE )
{
RETURN_ASYNC(OrderClose(Ticket, dLots, Price, SlipPage, INT_MAX))
}
uint OrderModifyAsync( const long Ticket, const double Price, const double SL, const double TP, const datetime Expiration, const color Arrow_Color = clrNONE )
{
RETURN_ASYNC(OrderModify(Ticket, Price, SL, TP, Expiration, INT_MAX))
}
uint OrderDeleteAsync( const long Ticket, const color Arrow_Color = clrNONE )
{
RETURN_ASYNC(OrderDelete(Ticket, INT_MAX))
}
uint OrderSendAsync( const string Symb, const int Type, const double dVolume, const double Price, const int SlipPage, const double SL, const double TP,
const string comment = NULL, const MAGIC_TYPE magic = 0, const datetime dExpiration = 0, color arrow_color = clrNONE )
{
RETURN_ASYNC(!OrderSend(Symb, Type, dVolume, Price, SlipPage, SL, TP, comment, magic, dExpiration, INT_MAX))
}
#undef RETURN_ASYNC
#undef MT4ORDERS_SLTP_OLD
#undef _BV2
#undef _B3
#undef _B2
#ifdef MT4ORDERS_BENCHMARK_MINTIME
#undef MT4ORDERS_BENCHMARK_MINTIME
#endif // MT4ORDERS_BENCHMARK_MINTIME
#endif // __MT4ORDERS__
#else // __MQL5__
#define TICKET_TYPE int
#define MAGIC_TYPE int
#endif // __MQL5__
#ifdef __MQL5__
#include <StdLibErr.mqh>
ENUM_TIMEFRAMES TFMigrate(int __timeframe)
{
switch (__timeframe)
{
case 0:
return (PERIOD_CURRENT);
case 1:
return (PERIOD_M1);
case 5:
return (PERIOD_M5);
case 15:
return (PERIOD_M15);
case 30:
return (PERIOD_M30);
case 60:
return (PERIOD_H1);
case 240:
return (PERIOD_H4);
case 1440:
return (PERIOD_D1);
case 10080:
return (PERIOD_W1);
case 43200:
return (PERIOD_MN1);
case 2:
return (PERIOD_M2);
case 3:
return (PERIOD_M3);
case 4:
return (PERIOD_M4);
case 6:
return (PERIOD_M6);
case 10:
return (PERIOD_M10);
case 12:
return (PERIOD_M12);
case 16385:
return (PERIOD_H1);
case 16386:
return (PERIOD_H2);
case 16387:
return (PERIOD_H3);
case 16388:
return (PERIOD_H4);
case 16390:
return (PERIOD_H6);
case 16392:
return (PERIOD_H8);
case 16396:
return (PERIOD_H12);
case 16408:
return (PERIOD_D1);
case 32769:
return (PERIOD_W1);
case 49153:
return (PERIOD_MN1);
default:
return (PERIOD_CURRENT);
}
}
ENUM_APPLIED_PRICE PriceMigrate(int __price)
{
switch (__price)
{
case 1:
return (PRICE_CLOSE);
case 2:
return (PRICE_OPEN);
case 3:
return (PRICE_HIGH);
case 4:
return (PRICE_LOW);
case 5:
return (PRICE_MEDIAN);
case 6:
return (PRICE_TYPICAL);
case 7:
return (PRICE_WEIGHTED);
default:
return (PRICE_CLOSE);
}
}
ENUM_MA_METHOD MethodMigrate(int __method)
{
switch (__method)
{
case 0:
return (MODE_SMA);
case 1:
return (MODE_EMA);
case 2:
return (MODE_SMMA);
case 3:
return (MODE_LWMA);
default:
return (MODE_SMA);
}
}
ENUM_STO_PRICE StoFieldMigrate(int __field)
{
switch (__field)
{
case 0:
return (STO_LOWHIGH);
case 1:
return (STO_CLOSECLOSE);
default:
return (STO_LOWHIGH);
}
}
#define Point _Point
#define Digits _Digits
#define Bid (::SymbolInfoDouble(_Symbol, ::SYMBOL_BID))
#define Ask (::SymbolInfoDouble(_Symbol, ::SYMBOL_ASK))
#define DoubleToStr DoubleToString
#define StringGetChar StringGetCharacter
#define StrToInteger (int)StringToInteger
#define StrToTime StringToTime
#define TimeToStr TimeToString
#define EMPTY -1
#define ERR_NO_ERROR 0
#define ERR_NO_RESULT 1
#define ERR_SERVER_BUSY 4
#define ERR_NO_CONNECTION 6
#define ERR_TRADE_TIMEOUT 128
#define ERR_INVALID_PRICE 129
#define ERR_NOT_ENOUGH_MONEY 134
#define ERR_PRICE_CHANGED 135
#define ERR_OFF_QUOTES 136
#define ERR_BROKER_BUSY 137
#define ERR_REQUOTE 138
#define ERR_TRADE_MODIFY_DENIED 145
#define ERR_TRADE_CONTEXT_BUSY 146
#define MODE_TIME 5
#define MODE_BID 9
#define MODE_ASK 10
#define MODE_POINT 11
#define MODE_DIGITS 12
#define MODE_SPREAD 13
#define MODE_STOPLEVEL 14
#define MODE_LOTSIZE 15
#define MODE_TICKVALUE 16
#define MODE_TICKSIZE 17
#define MODE_SWAPLONG 18
#define MODE_SWAPSHORT 19
#define MODE_STARTING 20
#define MODE_EXPIRATION 21
#define MODE_TRADEALLOWED 22
#define MODE_MINLOT 23
#define MODE_LOTSTEP 24
#define MODE_MAXLOT 25
#define MODE_SWAPTYPE 26
#define MODE_PROFITCALCMODE 27
#define MODE_MARGINCALCMODE 28
#define MODE_MARGININIT 29
#define MODE_MARGINMAINTENANCE 30
#define MODE_MARGINHEDGED 31
#define MODE_MARGINREQUIRED 32
#define MODE_FREEZELEVEL 33
#define LONG_VALUE INT_VALUE
#define OBJPROP_TIME1 OBJPROP_TIME
#define OBJPROP_PRICE1 OBJPROP_PRICE
#define MODE_ASCEND 0
#define MODE_DESCEND 1
#define MODE_TENKANSEN 1
#define MODE_KIJUNSEN 2
#define MODE_SENKOUSPANA 3
#define MODE_SENKOUSPANB 4
#define MODE_CHIKOUSPAN 5
void HideTestIndicators(bool __status = true)
{
TesterHideIndicators(__status);
}
bool IsTradeContextBusy(void)
{
return (false);
}
bool RefreshRates(void)
{
return (true);
}
double AccountFreeMarginCheck(const string __symbol, const int __cmd, const double __volume)
{
double __Margin = 0;
return (::AccountInfoDouble(::ACCOUNT_MARGIN_FREE) -
(::OrderCalcMargin((ENUM_ORDER_TYPE)__cmd, __symbol, __volume, ::SymbolInfoDouble(__symbol, (__cmd == ::ORDER_TYPE_BUY) ? ::SYMBOL_ASK : ::SYMBOL_BID), __Margin) ? __Margin : 0));
}
bool ObjectCreate(string __name, ENUM_OBJECT __type, int __window, datetime __time1, double __price1, datetime __time2 = 0, double __price2 = 0, datetime __time3 = 0, double __price3 = 0)
{
return (ObjectCreate(0, __name, __type, __window, __time1, __price1, __time2, __price2, __time3, __price3));
}
bool ObjectDelete(string __name)
{
return (ObjectDelete(0, __name));
}
int ObjectFind(string __name)
{
return (ObjectFind(0, __name));
}
bool ObjectMove(string __name, int __point, datetime __time1, double __price1)
{
return (ObjectMove(0, __name, __point, __time1, __price1));
}
string ObjectName(int __index)
{
return (ObjectName(0, __index));
}
bool ObjectSet(string __name, ENUM_OBJECT_PROPERTY_INTEGER __index, long __value)
{
return ((bool)ObjectSetInteger(0, __name, __index, __value));
}
bool ObjectSet(string __name, ENUM_OBJECT_PROPERTY_DOUBLE __index, double __value)
{
return ((bool)ObjectSetDouble(0, __name, __index, __value));
}
bool ObjectSetText(string __name, string __text, int __font_size, string __font = "", color __text_color = CLR_NONE)
{
int __ObjType = ObjectType(__name);
if (__ObjType != OBJ_LABEL && __ObjType != OBJ_TEXT)
return (false);
if (StringLen(__text) > 0 && __font_size > 0)
{
if (ObjectSetString(0, __name, OBJPROP_TEXT, __text) == true && ObjectSetInteger(0, __name, OBJPROP_FONTSIZE, __font_size) == true)
{
if (StringLen(__font) > 0 && ObjectSetString(0, __name, OBJPROP_FONT, __font) == false)
return (false);
if (ObjectSetInteger(0, __name, OBJPROP_COLOR, __text_color) == false)
return (false);
return (true);
}
return (false);
}
return (false);
}
bool ObjectSetText(string __name, string __text)
{
int __ObjType = ObjectType(__name);
if (__ObjType != OBJ_LABEL && __ObjType != OBJ_TEXT)
return (false);
if (StringLen(__text) > 0)
{
if (ObjectSetString(0, __name, OBJPROP_TEXT, __text) == true)
return (true);
return (false);
}
return (false);
}
int ObjectType(string __name)
{
return ((int)ObjectGetInteger(0, __name, OBJPROP_TYPE));
}
int ObjectsTotal(int __type = EMPTY, int __window = -1)
{
return (ObjectsTotal(0, __window, __type));
}
void WindowRedraw()
{
ChartRedraw(0);
}
int Year(void)
{
MqlDateTime __Time;
::TimeToStruct(TimeCurrent(), __Time);
return (__Time.year);
}
int DayOfWeek(void)
{
MqlDateTime __Time;
::TimeToStruct(TimeCurrent(), __Time);
return (__Time.day_of_week);
}
int TimeDayOfWeek(const datetime __date)
{
MqlDateTime __Time;
::TimeToStruct(__date, __Time);
return (__Time.day_of_week);
}
double GetMarginRequired(const string __symbol)
{
MqlTick __Tick;
double __MarginInit, __MarginMain;
return (SymbolInfoTick(__symbol, __Tick) && SymbolInfoMarginRate(__symbol, ORDER_TYPE_BUY, __MarginInit, __MarginMain)
? __MarginInit * __Tick.ask * SymbolInfoDouble(__symbol, SYMBOL_TRADE_TICK_VALUE) / (SymbolInfoDouble(__symbol, SYMBOL_TRADE_TICK_SIZE) * AccountInfoInteger(ACCOUNT_LEVERAGE))
: 0);
}
double MarketInfo(const string __symbol, const int __type)
{
switch(__type)
{
case MODE_BID:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_BID));
case MODE_ASK:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_ASK));
case MODE_POINT:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_POINT));
case MODE_DIGITS:
return ((double)::SymbolInfoInteger(__symbol, ::SYMBOL_DIGITS));
case MODE_SPREAD:
return ((double)::SymbolInfoInteger(__symbol, ::SYMBOL_SPREAD));
case MODE_LOW:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_LASTLOW));
case MODE_HIGH:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_LASTHIGH));
case MODE_TIME:
return double(::SymbolInfoInteger(__symbol, ::SYMBOL_TIME));
case MODE_STOPLEVEL:
return ((double)::SymbolInfoInteger(__symbol, ::SYMBOL_TRADE_STOPS_LEVEL));
case MODE_LOTSIZE:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_TRADE_CONTRACT_SIZE));
case MODE_MINLOT:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_VOLUME_MIN));
case MODE_LOTSTEP:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_VOLUME_STEP));
case MODE_MAXLOT:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_VOLUME_MAX));
case MODE_TICKSIZE:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_TRADE_TICK_SIZE));
case MODE_TICKVALUE:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_TRADE_TICK_VALUE));
case MODE_SWAPTYPE:
return double(::SymbolInfoInteger(__symbol, ::SYMBOL_SWAP_MODE));
case MODE_SWAPLONG:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_SWAP_LONG));
case MODE_SWAPSHORT:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_SWAP_SHORT));
case MODE_STARTING:
return ((double)::SymbolInfoInteger(__symbol, ::SYMBOL_START_TIME));
case MODE_EXPIRATION:
return ((double)::SymbolInfoInteger(__symbol, ::SYMBOL_EXPIRATION_TIME));
case MODE_TRADEALLOWED:
return ((double)::SymbolInfoInteger(__symbol, ::SYMBOL_TRADE_MODE) != SYMBOL_TRADE_MODE_DISABLED);
case MODE_PROFITCALCMODE:
return ((double)::SymbolInfoInteger(__symbol, ::SYMBOL_TRADE_CALC_MODE));
case MODE_MARGINCALCMODE:
return ((double)::SymbolInfoInteger(__symbol, ::SYMBOL_TRADE_CALC_MODE));
case MODE_MARGININIT:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_MARGIN_INITIAL));
case MODE_MARGINMAINTENANCE:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_MARGIN_MAINTENANCE));
case MODE_MARGINHEDGED:
return (::SymbolInfoDouble(__symbol, ::SYMBOL_MARGIN_HEDGED));
case MODE_MARGINREQUIRED:
return (GetMarginRequired(__symbol));
case MODE_FREEZELEVEL:
return ((double)::SymbolInfoInteger(__symbol, ::SYMBOL_TRADE_FREEZE_LEVEL));
}
return (-1);
}
string ErrorDescription(int __error)
{
switch (__error)
{
case ERR_SUCCESS:
return ("The operation completed successfully");
case ERR_INTERNAL_ERROR:
return ("Unexpected internal Error ");
case ERR_WRONG_INTERNAL_PARAMETER:
return ("Wrong parameter in the inner call of the client terminal function");
case ERR_INVALID_PARAMETER:
return ("Wrong parameter when calling the system function");
case ERR_NOT_ENOUGH_MEMORY:
return ("Not enough memory to perform the system function");
case ERR_STRUCT_WITHOBJECTS_ORCLASS:
return ("The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes");
case ERR_INVALID_ARRAY:
return ("Array of a wrong type, wrong size, or a damaged object of a dynamic array");
case ERR_ARRAY_RESIZE_ERROR:
return ("Not enough memory for the relocation of an array, or an attempt to change the size of a static array");
case ERR_STRING_RESIZE_ERROR:
return ("Not enough memory for the relocation of string");
case ERR_NOTINITIALIZED_STRING:
return ("Not initialized string");
case ERR_INVALID_DATETIME:
return ("Invalid date and/or time");
case ERR_ARRAY_BAD_SIZE:
return ("Requested array size exceeds 2GB");
case ERR_INVALID_POINTER:
return ("Wrong pointer");
case ERR_INVALID_POINTER_TYPE:
return ("Wrong type of pointer");
case ERR_FUNCTION_NOT_ALLOWED:
return ("Function is not allowed for call");
case ERR_RESOURCE_NAME_DUPLICATED:
return ("The names of the dynamic and the static resource match");
case ERR_RESOURCE_NOT_FOUND:
return ("Resource with this name has not been found in EX5");
case ERR_RESOURCE_UNSUPPOTED_TYPE:
return ("Unsupported resource type or its size exceeds 16MB");
case ERR_RESOURCE_NAME_IS_TOO_LONG:
return ("The resource name exceeds 63 characters");
case ERR_CHART_WRONG_ID:
return ("Wrong chart ID");
case ERR_CHART_NO_REPLY:
return ("Chart does not respond");
case ERR_CHART_NOT_FOUND:
return ("Chart not found");
case ERR_CHART_NO_EXPERT:
return ("No Expert Advisor in the chart that could handle the event");
case ERR_CHART_CANNOT_OPEN:
return ("Chart opening Error ");
case ERR_CHART_CANNOT_CHANGE:
return ("Failed to change chart symbol and period");
case ERR_CHART_WRONG_PARAMETER:
return ("Error value of the parameter for the function of working with charts");
case ERR_CHART_CANNOT_CREATE_TIMER:
return ("Failed to create timer");
case ERR_CHART_WRONG_PROPERTY:
return ("Wrong chart property ID");
case ERR_CHART_SCREENSHOT_FAILED:
return ("Error creating screenshots");
case ERR_CHART_NAVIGATE_FAILED:
return ("Error navigating through chart");
case ERR_CHART_TEMPLATE_FAILED:
return ("Error applying template");
case ERR_CHART_WINDOW_NOT_FOUND:
return ("Subwindow containing the indicator was not found");
case ERR_CHART_INDICATOR_CANNOT_ADD:
return ("Error adding an indicator to chart");
case ERR_CHART_INDICATOR_CANNOT_DEL:
return ("Error deleting an indicator from the chart");
case ERR_CHART_INDICATOR_NOT_FOUND:
return ("Indicator not found on the specified chart");
case ERR_OBJECT_ERROR:
return ("Error working with a graphical object");
case ERR_OBJECT_NOT_FOUND:
return ("Graphical object was not found");
case ERR_OBJECT_WRONG_PROPERTY:
return ("Wrong ID of a graphical object property");
case ERR_OBJECT_GETDATE_FAILED:
return ("Unable to get date corresponding to the value");
case ERR_OBJECT_GETVALUE_FAILED:
return ("Unable to get value corresponding to the date");
case ERR_MARKET_UNKNOWN_SYMBOL:
return ("Unknown symbol");
case ERR_MARKET_NOT_SELECTED:
return ("Symbol is not selected in MarketWatch");
case ERR_MARKET_WRONG_PROPERTY:
return ("Wrong identifier of a symbol property");
case ERR_MARKET_LASTTIME_UNKNOWN:
return ("Time of the last tick is not known (no ticks)");
case ERR_MARKET_SELECT_ERROR:
return ("Error adding or deleting a symbol in MarketWatch");
case ERR_HISTORY_NOT_FOUND:
return ("Requested history not found");
case ERR_HISTORY_WRONG_PROPERTY:
return ("Wrong ID of the history property");
case ERR_HISTORY_TIMEOUT:
return ("Exceeded history request timeout");
case ERR_HISTORY_BARS_LIMIT:
return ("Number of requested bars limited by terminal settings");
case ERR_HISTORY_LOAD_ERRORS:
return ("Multiple errors when loading history");
case ERR_HISTORY_SMALL_BUFFER:
return ("Receiving array is too small to store all requested data");
case ERR_GLOBALVARIABLE_NOT_FOUND:
return ("Global variable of the client terminal is not found");
case ERR_GLOBALVARIABLE_EXISTS:
return ("Global variable of the client terminal with the same name already exists");
case ERR_MAIL_SEND_FAILED:
return ("Email sending failed");
case ERR_PLAY_SOUND_FAILED:
return ("Sound playing failed");
case ERR_MQL5_WRONG_PROPERTY:
return ("Wrong identifier of the program property");
case ERR_TERMINAL_WRONG_PROPERTY:
return ("Wrong identifier of the terminal property");
case ERR_FTP_SEND_FAILED:
return ("File sending via ftp failed");
case ERR_NOTIFICATION_SEND_FAILED:
return ("Failed to send a notification");
case ERR_NOTIFICATION_WRONG_PARAMETER:
return ("Invalid parameter for sending a notification – an empty string or NULL has been passed to the SendNotification() function");
case ERR_NOTIFICATION_WRONG_SETTINGS:
return ("Wrong settings of notifications in the terminal (ID is not specified or permission is not set)");
case ERR_NOTIFICATION_TOO_FREQUENT:
return ("Too frequent sending of notifications");
case ERR_FTP_NOSERVER:
return ("FTP server is not specified");
case ERR_FTP_NOLOGIN:
return ("FTP login is not specified");
case ERR_FTP_FILE_ERROR:
return ("File not found in the MQL5\\Files directory to send on FTP server");
case ERR_FTP_CONNECT_FAILED:
return ("FTP connection failed");
case ERR_FTP_CHANGEDIR:
return ("FTP path not found on server");
case ERR_BUFFERS_NO_MEMORY:
return ("Not enough memory for the distribution of indicator buffers");
case ERR_BUFFERS_WRONG_INDEX:
return ("Wrong indicator buffer index");
case ERR_CUSTOM_WRONG_PROPERTY:
return ("Wrong ID of the custom indicator property");
case ERR_ACCOUNT_WRONG_PROPERTY:
return ("Wrong account property ID");
case ERR_TRADE_WRONG_PROPERTY:
return ("Wrong trade property ID");
case ERR_TRADE_DISABLED:
return ("Trading by Expert Advisors prohibited");
case ERR_TRADE_POSITION_NOT_FOUND:
return ("Position not found");
case ERR_TRADE_ORDER_NOT_FOUND:
return ("Order not found");
case ERR_TRADE_DEAL_NOT_FOUND:
return ("Deal not found");
case ERR_TRADE_SEND_FAILED:
return ("Trade request sending failed");
case ERR_INDICATOR_UNKNOWN_SYMBOL:
return ("Unknown symbol");
case ERR_INDICATOR_CANNOT_CREATE:
return ("Indicator cannot be created");
case ERR_INDICATOR_NO_MEMORY:
return ("Not enough memory to add the indicator");
case ERR_INDICATOR_CANNOT_APPLY:
return ("The indicator cannot be applied to another indicator");
case ERR_INDICATOR_CANNOT_ADD:
return ("Error applying an indicator to chart");
case ERR_INDICATOR_DATA_NOT_FOUND:
return ("Requested data not found");
case ERR_INDICATOR_WRONG_HANDLE:
return ("Wrong indicator handle");
case ERR_INDICATOR_WRONG_PARAMETERS:
return ("Wrong number of parameters when creating an indicator");
case ERR_INDICATOR_PARAMETERS_MISSING:
return ("No parameters when creating an indicator");
case ERR_INDICATOR_CUSTOM_NAME:
return ("The first parameter in the array must be the name of the custom indicator");
case ERR_INDICATOR_PARAMETER_TYPE:
return ("Invalid parameter type in the array when creating an indicator");
case ERR_INDICATOR_WRONG_INDEX:
return ("Wrong index of the requested indicator buffer");
case ERR_BOOKS_CANNOT_ADD:
return ("Depth Of Market can not be added");
case ERR_BOOKS_CANNOT_DELETE:
return ("Depth Of Market can not be removed");
case ERR_BOOKS_CANNOT_GET:
return ("The data from Depth Of Market can not be obtained");
case ERR_BOOKS_CANNOT_SUBSCRIBE:
return ("Error in subscribing to receive new data from Depth Of Market");
case ERR_TOO_MANY_FILES:
return ("More than 64 files cannot be opened at the same time");
case ERR_WRONG_FILENAME:
return ("Invalid file name");
case ERR_TOO_LONG_FILENAME:
return ("Too long file name");
case ERR_CANNOT_OPEN_FILE:
return ("File opening Error ");
case ERR_FILE_CACHEBUFFER_ERROR:
return ("Not enough memory for cache to read");
case ERR_CANNOT_DELETE_FILE:
return ("File deleting Error ");
case ERR_INVALID_FILEHANDLE:
return ("A file with this handle was closed, or was not opening at all");
case ERR_WRONG_FILEHANDLE:
return ("Wrong file handle");
case ERR_FILE_NOTTOWRITE:
return ("The file must be opened for writing");
case ERR_FILE_NOTTOREAD:
return ("The file must be opened for reading");
case ERR_FILE_NOTBIN:
return ("The file must be opened as a binary one");
case ERR_FILE_NOTTXT:
return ("The file must be opened as a text");
case ERR_FILE_NOTTXTORCSV:
return ("The file must be opened as a text or CSV");
case ERR_FILE_NOTCSV:
return ("The file must be opened as CSV");
case ERR_FILE_READERROR:
return ("File reading Error ");
case ERR_FILE_BINSTRINGSIZE:
return ("String size must be specified, because the file is opened as binary");
case ERR_INCOMPATIBLE_FILE:
return ("A text file must be for string arrays, for other arrays - binary");
case ERR_FILE_IS_DIRECTORY:
return ("This is not a file, this is a directory");
case ERR_FILE_NOT_EXIST:
return ("File does not exist");
case ERR_FILE_CANNOT_REWRITE:
return ("File can not be rewritten");
case ERR_DIRECTORY_NOT_EXIST:
return ("Directory does not exist");
case ERR_FILE_ISNOT_DIRECTORY:
return ("This is a file, not a directory");
case ERR_CANNOT_DELETE_DIRECTORY:
return ("The directory cannot be removed");
case ERR_CANNOT_CLEAN_DIRECTORY:
return ("Failed to clear the directory (probably one or more files are blocked and removal operation failed)");
case ERR_FILE_WRITEERROR:
return ("Failed to write a resource to a file");
case ERR_FILE_ENDOFFILE:
return ("Unable to read the next piece of data from a CSV file (FileReadString, FileReadNumber, FileReadDatetime, FileReadBool), since the end of file is reached");
case ERR_NO_STRING_DATE:
return ("No date in the string");
case ERR_WRONG_STRING_DATE:
return ("Wrong date in the string");
case ERR_WRONG_STRING_TIME:
return ("Wrong time in the string");
case ERR_STRING_TIME_ERROR:
return ("Error converting string to date");
case ERR_STRING_OUT_OF_MEMORY:
return ("Not enough memory for the string");
case ERR_STRING_SMALL_LEN:
return ("The string length is less than expected");
case ERR_STRING_TOO_BIGNUMBER:
return ("Too large number, more than ULONG_MAX");
case ERR_WRONG_FORMATSTRING:
return ("Invalid format string");
case ERR_TOO_MANY_FORMATTERS:
return ("Amount of format specifiers more than the parameters");
case ERR_TOO_MANY_PARAMETERS:
return ("Amount of parameters more than the format specifiers");
case ERR_WRONG_STRING_PARAMETER:
return ("Damaged parameter of string type");
case ERR_STRINGPOS_OUTOFRANGE:
return ("Position outside the string");
case ERR_STRING_ZEROADDED:
return ("0 added to the string end, a useless operation");
case ERR_STRING_UNKNOWNTYPE:
return ("Unknown data type when converting to a string");
case ERR_WRONG_STRING_OBJECT:
return ("Damaged string object");
case ERR_INCOMPATIBLE_ARRAYS:
return ("Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only");
case ERR_SMALL_ASSERIES_ARRAY:
return ("The receiving array is declared as AS_SERIES, and it is of insufficient size");
case ERR_SMALL_ARRAY:
return ("Too small array, the starting position is outside the array");
case ERR_ZEROSIZE_ARRAY:
return ("An array of zero length");
case ERR_NUMBER_ARRAYS_ONLY:
return ("Must be a numeric array");
case ERR_ONEDIM_ARRAYS_ONLY:
return ("Must be a one-dimensional array");
case ERR_SERIES_ARRAY:
return ("Timeseries cannot be used");
case ERR_DOUBLE_ARRAY_ONLY:
return ("Must be an array of type double");
case ERR_FLOAT_ARRAY_ONLY:
return ("Must be an array of type float");
case ERR_LONG_ARRAY_ONLY:
return ("Must be an array of type long");
case ERR_INT_ARRAY_ONLY:
return ("Must be an array of type int");
case ERR_SHORT_ARRAY_ONLY:
return ("Must be an array of type short");
case ERR_CHAR_ARRAY_ONLY:
return ("Must be an array of type char");
case ERR_OPENCL_NOT_SUPPORTED:
return ("OpenCL functions are not supported on this computer");
case ERR_OPENCL_INTERNAL:
return ("Internal error occurred when running OpenCL");
case ERR_OPENCL_INVALID_HANDLE:
return ("Invalid OpenCL handle");
case ERR_OPENCL_CONTEXT_CREATE:
return ("Error creating the OpenCL context");
case ERR_OPENCL_QUEUE_CREATE:
return ("Failed to create a run queue in OpenCL");
case ERR_OPENCL_PROGRAM_CREATE:
return ("Error occurred when compiling an OpenCL program");
case ERR_OPENCL_TOO_LONG_KERNEL_NAME:
return ("Too long kernel name (OpenCL kernel)");
case ERR_OPENCL_KERNEL_CREATE:
return ("Error creating an OpenCL kernel");
case ERR_OPENCL_SET_KERNEL_PARAMETER:
return ("Error occurred when setting parameters for the OpenCL kernel");
case ERR_OPENCL_EXECUTE:
return ("OpenCL program runtime Error ");
case ERR_OPENCL_WRONG_BUFFER_SIZE:
return ("Invalid size of the OpenCL buffer");
case ERR_OPENCL_WRONG_BUFFER_OFFSET:
return ("Invalid offset in the OpenCL buffer");
case ERR_OPENCL_BUFFER_CREATE:
return ("Failed to create an OpenCL buffer");
case ERR_WEBREQUEST_INVALID_ADDRESS:
return ("Invalid URL");
case ERR_WEBREQUEST_CONNECT_FAILED:
return ("Failed to connect to specified URL");
case ERR_WEBREQUEST_TIMEOUT:
return ("Timeout exceeded");
case ERR_WEBREQUEST_REQUEST_FAILED:
return ("HTTP request failed");
case ERR_USER_ERROR_FIRST:
return ("User defined errors start with this code");
default:
return ("");
}
}
double CopyBufferMQL4(int __handle, int __index, int __shift)
{
double __Buffer[];
switch (__index)
{
case 0:
if (CopyBuffer(__handle, 0, __shift, 1, __Buffer) > 0)
return (__Buffer[0]);
break;
case 1:
if (CopyBuffer(__handle, 1, __shift, 1, __Buffer) > 0)
return (__Buffer[0]);
break;
case 2:
if (CopyBuffer(__handle, 2, __shift, 1, __Buffer) > 0)
return (__Buffer[0]);
break;
case 3:
if (CopyBuffer(__handle, 3, __shift, 1, __Buffer) > 0)
return (__Buffer[0]);
break;
case 4:
if (CopyBuffer(__handle, 4, __shift, 1, __Buffer) > 0)
return (__Buffer[0]);
break;
default:
break;
}
return (EMPTY_VALUE);
}
double iATRMQL4(string __symbol, int __timeframe, int __period, int __shift)
{
ENUM_TIMEFRAMES __TimeFrame = TFMigrate(__timeframe);
int __Handle = iATR(__symbol, __TimeFrame, __period);
if (__Handle < 0)
{
Print("The iATR object was not created: Error ", GetLastError());
return (-1);
}
else
return (CopyBufferMQL4(__Handle, 0, __shift));
}
#define iATR iATRMQL4
double iCloseMQL4(string __symbol, int __tf, int __index)
{
if (__index < 0)
return (-1);
double __Array[];
ENUM_TIMEFRAMES __Timeframe = TFMigrate(__tf);
if (CopyClose(__symbol, __Timeframe, __index, 1, __Array) > 0)
return (__Array[0]);
return (-1);
}
#define iClose iCloseMQL4
double iCCIMQL4(string __symbol, int __timeframe, int __period, int __price, int __shift)
{
ENUM_TIMEFRAMES __TimeFrame = TFMigrate(__timeframe);
ENUM_APPLIED_PRICE __AppliedPrice = PriceMigrate(__price);
int __Handle = iCCI(__symbol, __TimeFrame, __period, __AppliedPrice);
if (__Handle < 0)
{
Print("The iCCI object was not created: Error ", GetLastError());
return (-1);
}
else
return (CopyBufferMQL4(__Handle, 0, __shift));
}
#define iCCI iCCIMQL4
double iIchimokuMQL4(string __symbol, int __timeframe, int __tenkan_sen, int __kijun_sen, int __senkou_span_b, int __mode, int __shift)
{
ENUM_TIMEFRAMES __TimeFrame = TFMigrate(__timeframe);
int __Handle = iIchimoku(__symbol, __TimeFrame, __tenkan_sen, __kijun_sen, __senkou_span_b);
if (__Handle < 0)
{
Print("The iIchimoku object was not created: Error ", GetLastError());
return (-1);
}
else
return (CopyBufferMQL4(__Handle, __mode - 1, __shift));
}
#define iIchimoku iIchimokuMQL4
double iMAMQL4(string __symbol, int __timeframe, int __period, int __ma_shift, int __method, int __price, int __shift)
{
ENUM_TIMEFRAMES __TimeFrame = TFMigrate(__timeframe);
ENUM_MA_METHOD __Method = MethodMigrate(__method);
ENUM_APPLIED_PRICE __AppliedPrice = PriceMigrate(__price);
int __Handle = iMA(__symbol, __TimeFrame, __period, __ma_shift, __Method, __AppliedPrice);
if (__Handle < 0)
{
Print("The iMA object was not created: Error ", GetLastError());
return (-1);
}
else
return (CopyBufferMQL4(__Handle, 0, __shift));
}
#define iMA iMAMQL4
double iMAOnArrayMQL4(double &__array[], int __total, int __period, int __ma_shift, int __ma_method, int __shift)
{
double __Buffer[], __Array[];
if (__total == 0)
__total = ArraySize(__Array);
if (__total > 0 && __total <= __period)
return (0);
if (__shift > __total - __period - __ma_shift)
return (0);
switch (__ma_method)
{
case MODE_SMA :
{
__total = ArrayCopy(__Array, __array, 0, __shift + __ma_shift, __period);
if (ArrayResize(__Buffer, __total) < 0)
return (0);
double __Sum = 0;
int __Position = __total - 1;
for (int __Index = 1; __Index < __period; __Index++, __Position--)
__Sum += __Array[__Position];
while (__Position >= 0)
{
__Sum += __Array[__Position];
__Buffer[__Position] = __Sum / __period;
__Sum -= __Array[__Position + __period - 1];
__Position--;
}
return (__Buffer[0]);
}
case MODE_EMA :
{
if (ArrayResize(__Buffer, __total) < 0)
return (0);
double __pr = 2.0 / (__period + 1);
int __Position = __total - 2;
while (__Position >= 0)
{
if (__Position == __total - 2)
__Buffer[__Position + 1] = __array[__Position + 1];
__Buffer[__Position] = __array[__Position] * __pr + __Buffer[__Position + 1] * (1 - __pr);
__Position--;
}
return (__Buffer[__shift + __ma_shift]);
}
case MODE_SMMA :
{
if (ArrayResize(__Buffer, __total) < 0)
return (0);
double __Sum = 0;
int __Position = __total - __period;
while (__Position >= 0)
{
if (__Position == __total - __period)
{
for (int __Index = 0, __Element = __Position; __Index < __period; __Index++, __Element++)
{
__Sum += __array[__Element];
__Buffer[__Element] = 0;
}
}
else
__Sum = __Buffer[__Position + 1] * (__period - 1) + __array[__Position];
__Buffer[__Position] = __Sum / __period;
__Position--;
}
return (__Buffer[__shift + __ma_shift]);
}
case MODE_LWMA :
{
if (ArrayResize(__Buffer, __total) < 0)
return (0);
double __Sum = 0.0, __LinearSum = 0.0;
double __Price;
int __Index, __Weight = 0, __Position = __total - 1;
for(__Index = 1; __Index <= __period; __Index++, __Position--)
{
__Price = __array[__Position];
__Sum += __Price * __Index;
__LinearSum += __Price;
__Weight += __Index;
}
__Position++;
__Index = __Position + __period;
while (__Position >= 0)
{
__Buffer[__Position] = __Sum / __Weight;
if (__Position == 0)
break;
__Position--;
__Index--;
__Price = __array[__Position];
__Sum = __Sum - __LinearSum + __Price * __period;
__LinearSum -= __array[__Index];
__LinearSum += __Price;
}
return (__Buffer[__shift + __ma_shift]);
}
default:
return (0);
}
return (0);
}
#define iMAOnArray iMAOnArrayMQL4
double iMACDMQL4(string __symbol, int __timeframe, int __fast_ema_period, int __slow_ema_period, int __signal_period, int __price, int __mode, int __shift)
{
ENUM_TIMEFRAMES __TimeFrame = TFMigrate(__timeframe);
ENUM_APPLIED_PRICE __AppliedPrice = PriceMigrate(__price);
int __Handle = iMACD(__symbol, __TimeFrame, __fast_ema_period, __slow_ema_period, __signal_period, __AppliedPrice);
if (__Handle < 0)
{
Print("The iMACD object was not created: Error ", GetLastError());
return (-1);
}
else
return (CopyBufferMQL4(__Handle, __mode, __shift));
}
#define iMACD iMACDMQL4
double iRSIMQL4(string __symbol, int __timeframe, int __period, int __price, int __shift)
{
ENUM_TIMEFRAMES __TimeFrame = TFMigrate(__timeframe);
ENUM_APPLIED_PRICE __AppliedPrice = PriceMigrate(__price);
int __Handle = iRSI(__symbol, __TimeFrame, __period, __AppliedPrice);
if (__Handle < 0)
{
Print("The iRSI object was not created: Error ", GetLastError());
return (-1);
}
else
return (CopyBufferMQL4(__Handle, 0, __shift));
}
#define iRSI iRSIMQL4
double iStdDevMQL4(string __symbol, int __timeframe, int __ma_period, int __ma_shift, int __method, int __price, int __shift)
{
ENUM_TIMEFRAMES __TimeFrame = TFMigrate(__timeframe);
ENUM_MA_METHOD __Method = MethodMigrate(__method);
ENUM_APPLIED_PRICE __AppliedPrice = PriceMigrate(__price);
int __Handle = iStdDev(__symbol, __TimeFrame, __ma_period, __ma_shift, __Method, __AppliedPrice);
if (__Handle < 0)
{
Print("The iStdDev object was not created: Error ", GetLastError());
return (-1);
}
else
return (CopyBufferMQL4(__Handle, 0, __shift));
}
#define iStdDev iStdDevMQL4
double iStochasticMQL4(string __symbol, int __timeframe, int __Kperiod, int __Dperiod, int __slowing, int __method, int __price, int __mode, int __shift)
{
ENUM_TIMEFRAMES __TimeFrame = TFMigrate(__timeframe);
ENUM_MA_METHOD __Method = MethodMigrate(__method);
ENUM_STO_PRICE __Price = StoFieldMigrate(__price);
int __Handle = iStochastic(__symbol, __TimeFrame, __Kperiod, __Dperiod, __slowing, __Method, __Price);
if (__Handle < 0)
{
Print("The iStochastic object was not created: Error ", GetLastError());
return (-1);
}
else
return (CopyBufferMQL4(__Handle, __mode, __shift));
}
#define iStochastic iStochasticMQL4
template <typename T>
void SwitchRow(T &__array[], const int __upper, const int __lower)
{
const T __Saved = __array[__upper];
__array[__upper] = __array[__lower];
__array[__lower] = __Saved;
}
template <typename T>
bool ArraySortMQL4(T &__array[], int __count = WHOLE_ARRAY, int __start = 0, int __sort_dir = MODE_DESCEND)
{
const bool __Result = ArraySort(__array);
if (__Result && (__sort_dir == MODE_DESCEND))
{
const int __Size = ArraySize(__array);
for (int __Index = (__Size >> 1) - 1; __Index >= 0; __Index--)
SwitchRow(__array, __Index, __Size - 1 - __Index);
}
return (__Result);
}
template <typename T>
void SwitchRow(T &__array[][2], const int __upper, const int __lower)
{
T __Saved[99];
const int __Cells = ArrayRange(__array, 1);
for (int __Cell = 0; __Cell < __Cells; __Cell++)
{
__Saved[__Cell] = __array[__upper][__Cell];
__array[__upper][__Cell] = __array[__lower][__Cell];
__array[__lower][__Cell] = __Saved[__Cell];
}
}
template <typename T>
bool ArraySortMQL4(T &__array[][2], int __count = WHOLE_ARRAY, int __start = 0, int __sort_dir = MODE_DESCEND)
{
const bool __Result = ArraySort(__array);
if (__Result && (__sort_dir == MODE_DESCEND))
{
const int __Size = ArrayRange(__array, 0);
for (int __Index = (__Size >> 1) - 1; __Index >= 0; __Index--)
SwitchRow(__array, __Index, __Size - 1 - __Index);
}
return (__Result);
}
#define ArraySort ArraySortMQL4
#endif // __MQL5__
#ifndef __MQL5__
#include <StdLib.mqh>
#include <StdError.mqh>
#include <WinUser32.mqh>
#endif // __MQL5__
#define A 1 //All (Basket + Hedge)
#define B 2 //Basket
#define H 3 //Hedge
#define T 4 //Ticket
#define P 5 //Pending
enum portChgs
{
no_change = 0, // No changes
increase = 1, // Increase only
any = -1 // Increase / decrease
};
enum mktCond
{
uptrend = 0, // Long only
downtrend = 1, // Short only
range = 2, // Long & short
automatic = 3 // Automatic
};
enum entType
{
disable = 0, // Disabled
enable = 1, // Enabled
reverse = 2 // Reverse
};
enum crossType
{
ic_disable = 0, // Disabled
ic_enabled = 1, // Cross
ic_cloud = 2 // Cross Cloud Direction
};
enum tFrame
{
current = 0, // Current
m1 = 1, // M1
m5 = 2, // M5
m15 = 3, // M15
m30 = 4, // M30
h1 = 5, // H1
h4 = 6, // H4
d1 = 7, // Daily
w1 = 8, // Weekly
mn1 = 9 // Monthly
};
input string Version_3_9_6_23 = "EA Settings:";
input string TradeComment = "b3_v396.23";
input string Notes = "";
input int EANumber = 1; // EA Magic Number
input bool EmergencyCloseAll = false; // *** CLOSE ALL NOW ***
input string s1 = ""; //.
input bool ShutDown = false; // *** NO NEW TRADES ***
input string s2 = ""; //.
input string LabelAcc = ""; // == ACCOUNT SETTINGS ==
input double StopTradePercent = 10;; // Percentage of balance lost before trading stops
input bool NanoAccount = false;; // Small Lot Account (0.01)
input string s3 = "... PortionPC > 100 forces effective balance to that amount (e.g. 1000)"; //.
input double PortionPC = 100;; // Percentage of account you want to trade on this pair
input portChgs PortionChange = increase;; // Permitted Portion change with open basket
input double MaxDDPercent = 50;; // Percent of portion for max drawdown level.
input double MaxSpread = 5;; // Maximum allowed spread while placing trades
input bool UseHolidayShutdown = true;; // Enable holiday shut-downs
input string Holidays = "18/12-01/01";; // Comma-separated holiday list (format: [day]/[mth]-[day]/[mth])
input bool PlaySounds = false;; // Audible alerts
input string AlertSound = "Alert.wav";; // Alert sound
input string eopb = ""; // -- Opt. with 'Open prices only' --
input bool EnableOncePerBar = true;
input bool UseMinMarginPercent = false;
input double MinMarginPercent = 1500;
input string eopb1 = ""; //.
input string LabelTST = ""; // ------ CUSTOM TESTER SETTINGS ------
input double TesterMinMarginPercent = 500;;
input int TesterSelection = 1;; // 1: Balance 2: (Balance^2 * min Drawdown * Trades)
input string LabelTST2; // .
input bool B3Traditional = true;; // Stop/Limits for entry if true, Buys/Sells if false
input mktCond ForceMarketCond = 3;; // Market condition
input bool UseAnyEntry = false;; // true = ANY entry can be used to open orders, false = ALL entries used to open orders
input string LabelLS = ""; // ----------- LOT SIZE -----------
input bool UseMM = true;; // UseMM (Money Management)
input double LAF = 0.5;; // Adjusts MM base lot for large accounts
input double Lot = 0.01;; // Starting lots if Money Management is off
input double Multiplier = 1.4;; // Multiplier on each level
input string LabelGS = ""; // ------ GRID SETTINGS ------
input bool AutoCal = false;; // Auto calculation of TakeProfit and Grid size;
input tFrame ATRTF = 0;; // TimeFrame for ATR calculation
input int ATRPeriods = 21;; // Number of periods for the ATR calculation
input double GAF = 1.0;; // Widens/Squishes Grid in increments/decrements of .1
input int EntryDelay = 2400;; // Time Grid in seconds, avoid opening lots of levels in fast market
input double EntryOffset = 5;; // In pips, used in conjunction with logic to offset first trade entry
input bool UseSmartGrid = true;; // True = use RSI/MA calculation for next grid order
input string LabelTS = ""; // ===== TRADING =====
input int MaxTrades = 15;; // Maximum number of trades to place (stops placing orders when reaches MaxTrades)
input int BreakEvenTrade = 12;; // Close All level, when reaches this level, doesn't wait for TP to be hit
input double BEPlusPips = 2;; // Pips added to Break Even Point before BE closure
input bool UseCloseOldest = false;; // True = will close the oldest open trade after CloseTradesLevel is reached
input int CloseTradesLevel = 5;; // will start closing oldest open trade at this level
input bool ForceCloseOldest = true;; // Will close the oldest trade whether it has potential profit or not
input int MaxCloseTrades = 4;; // Maximum number of oldest trades to close
input double CloseTPPips = 10;; // After Oldest Trades have closed, Forces Take Profit to BE +/- xx Pips
input double ForceTPPips = 0;; // Force Take Profit to BE +/- xx Pips
input double MinTPPips = 0;; // Ensure Take Profit is at least BE +/- xx Pips
input string LabelES = ""; // ----------- EXITS -----------
input bool MaximizeProfit = false;; // Turns on TP move and Profit Trailing Stop Feature
input double ProfitSet = 70;; // Profit trailing stop: Lock in profit at set percent of Total Profit Potential
input double MoveTP = 30;; // Moves TP this amount in pips
input int TotalMoves = 2;; // Number of times you want TP to move before stopping movement
input bool UseStopLoss = false;; // Use Stop Loss and/or Trailing Stop Loss
input double SLPips = 30;; // Pips for fixed StopLoss from BE, 0=off
input double TSLPips = 10;; // Pips for trailing stop loss from BE + TSLPips: +ve = fixed trail; -ve = reducing trail; 0=off
input double TSLPipsMin = 3;; // Minimum trailing stop pips if using reducing TS
input bool UsePowerOutSL = false;; // Transmits a SL in case of internet loss
input double POSLPips = 600;; // Power Out Stop Loss in pips
input bool UseFIFO = false;; // Close trades in FIFO order
input string LabelEE = ""; // --------- EARLY EXITS ---------
input bool UseEarlyExit = false;; // Reduces ProfitTarget by a percentage over time and number of levels open
input double EEStartHours = 3;; // Number of Hours to wait before EE over time starts
input bool EEFirstTrade = true;; // true = StartHours from FIRST trade: false = StartHours from LAST trade
input double EEHoursPC = 0.5;; // Percentage reduction per hour (0 = OFF)
input int EEStartLevel = 5;; // Number of Open Trades before EE over levels starts
input double EELevelPC = 10;; // Percentage reduction at each level (0 = OFF)
input bool EEAllowLoss = false;; // true = Will allow the basket to close at a loss : false = Minimum profit is Break Even
input string LabelAdv = ""; //.
input string LabelGrid = ""; // --------- GRID SIZE ---------
input string SetCountArray = "4,4";; // Specifies number of open trades in each block (separated by a comma)
input string GridSetArray = "25,50,100";; // Specifies number of pips away to issue limit order (separated by a comma)
input string TP_SetArray = "50,100,200";; // Take profit for each block (separated by a comma)
input string LabelEST0 = ""; // .
input string LabelEST = ""; // == ENTRY PARAMETERS ==
input string LabelMA = ""; // ------------- MA -------------
input entType MAEntry = 1;; // MA Entry
input tFrame MA_TF = 0;; // Time frame for MA calculation, r.f. ********
input int MAPeriod = 100;; // Period of MA (H4 = 100, H1 = 400)
input double MADistance = 10;; // Distance from MA to be treated as Ranging Market
input string LabelCCI = ""; // ------------- CCI -------------
input entType CCIEntry = 0;; // CCI Entry
input int CCIPeriod = 14;; // Period for CCI calculation
input string LabelBBS = ""; // ----- BOLLINGER BANDS -----
input entType BollingerEntry = 0;; // Bollinger Entry
input int BollPeriod = 10;; // Period for Bollinger
input double BollDistance = 10;; // Up/Down spread
input double BollDeviation = 2.0;; // Standard deviation multiplier for channel
input string LabelIchi = ""; // ----- ICHIMOKU CLOUD -----
input entType IchimokuEntry = 0; // Ichimoku Entry
input tFrame ICHI_TF = 0; // TF setting, but only current will work
input int Tenkan_Sen = 9; // Tenkan
input int Kijun_Sen = 26; // Kijun
input int Senkou_Span = 52; // Senkou
input bool useCloudBreakOut = true; // Trade if price breaks cloud / Kumo
input crossType useTenken_Kijun_cross = 2; // Trade if Tenken crosses Kijun
input bool usePriceCrossTenken = false; // Trade if Price crosses Tenken
input bool usePriceCrossKijun = false; // Trade if price crosses Kijun
input bool useChikuspan = false; // Trade if chiku crosses Price
input bool useCloudSL = false; // Close all orders if price dives into the cloud/kumo
input string LabelSto = ""; // --------- STOCHASTIC --------
input entType StochEntry = 0;; // Stochastic Entry
input int BuySellStochZone = 20;; // Determines Overbought and Oversold Zones
input int KPeriod = 10;; // Stochastic KPeriod
input int DPeriod = 2;; // Stochastic DPeriod
input int Slowing = 2;; // Stochastic Slowing
input string LabelMACD = ""; // ------------ MACD ------------
input entType MACDEntry = 0;; // MACD Entry
input tFrame MACD_TF = 0;; // Time frame for MACD calculation
input int FastPeriod = 12;; // MACD EMA Fast Period
input int SlowPeriod = 26;; // MACD EMA Slow Period
input int SignalPeriod = 9;; // MACD EMA Signal Period
#ifdef __MQL5__
input ENUM_APPLIED_PRICE MACDPrice = PRICE_CLOSE;; // MACD Applied Price
#else
input ENUM_APPLIED_PRICE MACDPrice = 0;; // MACD Applied Price
#endif // __MQL5__
input string LabelSG = ""; // --------- SMART GRID ---------
input tFrame RSI_TF = 3;; // Timeframe for RSI calculation (should be lower than chart TF)
input int RSI_Period = 14;; // Period for RSI calculation
#ifdef __MQL5__
input ENUM_APPLIED_PRICE RSI_Price = PRICE_CLOSE;; // RSI Applied Price
#else
input ENUM_APPLIED_PRICE RSI_Price = 0;; // RSI Applied Price
#endif // __MQL5__
input int RSI_MA_Period = 10;; // Period for MA of RSI calculation
input ENUM_MA_METHOD RSI_MA_Method = 0;; // RSI MA Method
input string LabelHS0 = ""; //.
input string LabelHS = ""; // ------ HEDGE SETTINGS -----
input string HedgeSymbol = "";; // Enter the Symbol of the same/correlated pair EXACTLY as used by your broker.
input int CorrPeriod = 30;; // Number of days for checking Hedge Correlation
input bool UseHedge = false;; // Turns DD hedge on/off
input string DDorLevel = "DD";; // DD = start hedge at set DD;Level = Start at set level
input double HedgeStart = 20;; // DD Percent or Level at which Hedge starts
input double hLotMult = 0.8;; // Hedge Lots = Open Lots * hLotMult
input double hMaxLossPips = 30;; // DD Hedge maximum pip loss - also hedge trailing stop
input bool hFixedSL = false;; // true = fixed SL at hMaxLossPips
input double hTakeProfit = 30;; // Hedge Take Profit
input double hReEntryPC = 5;; // Increase to HedgeStart to stop early re-entry of the hedge
input bool StopTrailAtBE = true;; // True = Trailing Stop will stop at BE;False = Hedge will continue into profit
input bool ReduceTrailStop = true;; // False = Trailing Stop is Fixed;True = Trailing Stop will reduce after BE is reached
input string LabelOS0 Показано первые 50% кода (символов: 185892)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.