1010 linhas
59 KiB
MQL5
1010 linhas
59 KiB
MQL5
|
|
#property copyright "Copyright © 2022, ХАЛИТ"
|
|
|
|
|
|
#property link "https://t.me/mo_elnoby"
|
|
//#property version "3.4.2" // Такая версия несовместима с MQL-маркетом
|
|
#property description "CONNECT EA"
|
|
#property description "MAKE SURE YOU HAVE BROKER WITH LOWER SPREAD TO WORK WELL"
|
|
#property description "PAIRS: GBPUSD,USDCHF,USDCAD,USDJPY"
|
|
#property description "TF: M5"
|
|
#property description "UNL"
|
|
//#property strict
|
|
//#property icon "\\Images\\CONNECT.ico"
|
|
|
|
#define BANDS_PERIOD 20
|
|
#define BANDS_MA_SHIFT 0
|
|
#define BANDS_DEVIATION 2.0
|
|
#define BANDS_APPLIED_PRICE PRICE_MEDIAN
|
|
|
|
#define MA_PERIOD 20
|
|
|
|
#define ATR_PERIOD 14
|
|
|
|
|
|
#include <Indicators\Trend.mqh> // Включаемый файл, необходим для индикатора iBands
|
|
#include <Indicators\Oscilators.mqh> // Включаемый файл, необходим для индикатора iAtr
|
|
#include <Indicators\Trend.mqh> // Включаемый файл, необходим для индикатора iMA
|
|
#include <Trade\Trade.mqh> // Включаемый файл, необходим для торгового процессора.
|
|
|
|
|
|
|
|
//------------------
|
|
input string FULL = "UNL"; // FULL
|
|
input string SETTINGS = "CONNECT EA";
|
|
input string TF = "M5";
|
|
input string CURRENCY = "GBPUSD,USDCHF,USDCAD,USDJPY";
|
|
input uint uiIBandsPeriod = BANDS_PERIOD; // B.Bands Period
|
|
input int iIBandsMaShift = BANDS_MA_SHIFT; // B.Bands MA Shift
|
|
input double dIBandsDeviation = BANDS_DEVIATION; // B.Bands Deviation
|
|
input ENUM_APPLIED_PRICE apIBandsPrice = BANDS_APPLIED_PRICE; // B.Bands Applied Price
|
|
input bool bIUseATR = true; // Использовать ли ATR(14) для фильтра
|
|
input bool bIUseMA = true; // Использовать ли MA(20) для фильтра
|
|
input double Lots=0.01 ; // FIXED LOT
|
|
input bool UseRisk=true ; // USE RISK
|
|
input double MaxRisk=2 ; //RISK
|
|
input int StopLoss=65 ; // SL
|
|
input int TakeProfit=20 ; // TP
|
|
input double MaxSpread=5 ; // MAX SPREAD
|
|
input int MaxSlippage=1 ; // MAX SLIPPAGE (int)
|
|
|
|
input uint HourStart=22 ;
|
|
input uint HourEnd=1 ;
|
|
input int Magic = 1;
|
|
int Magic2 = Magic ;
|
|
string DATA_1_st = "CONNECT EA";
|
|
double d45QuotesRatio = 1.0; // Если котировки четырёхзначные, то остаётся 1, если котировки пятизначные - ставится 10.
|
|
string DATA_4_st = "\n";
|
|
int iDigits = 4;
|
|
int DATA_6_in = 0;
|
|
int DATA_7_in = 0;
|
|
double dMaxRisk = 1.0;
|
|
int DATA_9_in = 0;
|
|
int DATA_10_in = 0;
|
|
int DATA_11_in = 0;
|
|
datetime DATA_12_da = 0;
|
|
string Ai_1 = "2022.07.07";
|
|
|
|
static const int MIN_AVAILIBLE_BARS = 10;
|
|
|
|
|
|
string ErrorDescription( int mu_0_in)
|
|
{
|
|
return(" " + IntegerToString(mu_0_in));
|
|
};
|
|
|
|
// Очередной тик
|
|
MqlTick mtLastTick;
|
|
|
|
// Выбранный тикет позиции MT5
|
|
ulong ulSelectedPosTicket;
|
|
ulong ulSelectedHistoryPosTicket;
|
|
|
|
|
|
// Индикаторы, используемые в эксперте.
|
|
CiBands ibBands;
|
|
CiATR iaATR;
|
|
CiMA imMA;
|
|
|
|
// Торговый процессор
|
|
CTrade tTradeProcessor;
|
|
|
|
// Момент вызова функции HistorySelect
|
|
datetime dtHistorySelectMoment;
|
|
|
|
// Функция преобразования величины long в величину int с проверкой диапазона и удаления эксперта с графика, в случае его превышения
|
|
int _Long2Int(long lValue)
|
|
{
|
|
if(lValue < INT_MIN || lValue > INT_MAX)
|
|
{
|
|
Print("Невозможно преобразовать long-значение " + IntegerToString(lValue) + " к представлению int. Эксперт остановлен.");
|
|
ExpertRemove();
|
|
};
|
|
|
|
return((int)lValue);
|
|
}
|
|
|
|
// Функция, прячущая все индикаторы
|
|
// Аналог HideTestIndicators() МТ4
|
|
void _HideTestIndicators(bool bFlag)
|
|
{
|
|
#ifdef __MQL5__
|
|
// Print("В МТ5 индикаторы пока не скрываются. TODO: написать функцию _HideTestIndicators(bool bFlag)" );
|
|
#else // __MQL5__
|
|
_HideTestIndicators(bFlag);
|
|
#endif // __MQL5__
|
|
};
|
|
|
|
// Функция, возвращающая число баров на текущем графике
|
|
// Аналог Bars МТ4
|
|
int _Bars()
|
|
{
|
|
#ifdef __MQL5__
|
|
int iRes = Bars(Symbol(),Period());
|
|
if(iRes <= NULL || iRes >= INT_MAX)
|
|
{
|
|
Print("Ошибка функции Bars(), при запросе количества баров на чарте, вернулось:" + IntegerToString(iRes));
|
|
Print("GetLastError() = " + IntegerToString(GetLastError()));
|
|
};
|
|
return(iRes);
|
|
#else // __MQL5__
|
|
return(Bars);
|
|
#endif // __MQL5__
|
|
};
|
|
|
|
// Функции возвращающие Bid и Ask последней котировки
|
|
// Аналог переменных в МТ4
|
|
double _Bid()
|
|
{
|
|
#ifdef __MQL5__
|
|
return(mtLastTick.bid);
|
|
#else // __MQL5__
|
|
return(Bid);
|
|
#endif // __MQL5__
|
|
};
|
|
double _Ask()
|
|
{
|
|
#ifdef __MQL5__
|
|
return(mtLastTick.ask);
|
|
#else // __MQL5__
|
|
return(Ask);
|
|
#endif // __MQL5__
|
|
};
|
|
|
|
#define MODE_LOTSIZE 15
|
|
#define MODE_MINLOT 23
|
|
#define MODE_MAXLOT 25
|
|
|
|
// Аналог функции _MarketInfo
|
|
double _MarketInfo(string strSymbol,int iInfoID)
|
|
{
|
|
switch(iInfoID)
|
|
{
|
|
case MODE_LOTSIZE: return(SymbolInfoDouble(strSymbol,SYMBOL_TRADE_CONTRACT_SIZE));
|
|
case MODE_MINLOT: return(SymbolInfoDouble(strSymbol,SYMBOL_VOLUME_MIN));
|
|
case MODE_MAXLOT: return(SymbolInfoDouble(strSymbol,SYMBOL_VOLUME_MAX));
|
|
default:
|
|
break;
|
|
};
|
|
|
|
return(EMPTY_VALUE);
|
|
};
|
|
|
|
// Аналог функции AccountFreeMargin()
|
|
double _AccountFreeMargin()
|
|
{
|
|
return(AccountInfoDouble(ACCOUNT_MARGIN_FREE));
|
|
};
|
|
|
|
|
|
// Функция возвращает данные индикатора по указанному буфферу (нулевой индекс)
|
|
double _iBands(int iBuffer)
|
|
{
|
|
// Номера буфферов лент Боллинджера:
|
|
// 1 - верхняя
|
|
// 2 - нижняя
|
|
double dRes = ibBands.GetData(iBuffer,0);
|
|
return(dRes);
|
|
};
|
|
|
|
// Функция возвращающая данные индикатора ATR
|
|
double _iATR()
|
|
{
|
|
double dRes = iaATR.GetData(0,0);
|
|
|
|
if(bIUseATR == false)
|
|
dRes = NULL;
|
|
|
|
return(dRes);
|
|
};
|
|
|
|
// Функция возвращающая данные индикатора MA
|
|
double _iMA()
|
|
{
|
|
double dRes = imMA.GetData(0,0);
|
|
return(dRes);
|
|
}
|
|
|
|
// Функция возвращает час из указанной даты
|
|
uint _TimeHour(datetime dtFrom)
|
|
{
|
|
MqlDateTime mdtTime;
|
|
|
|
if(TimeToStruct(dtFrom,mdtTime)!=true)
|
|
return(UINT_MAX);
|
|
|
|
return(mdtTime.hour);
|
|
};
|
|
|
|
// Функция-аналог функции OrdersTotal() из MT4 для открытых ордеров
|
|
int _OrdersTotal()
|
|
{
|
|
return(PositionsTotal());
|
|
};
|
|
|
|
// Функция-аналог функции OrderSelect(SELECT_BY_POS) из MT4
|
|
// На вход передается индекс открытой позиции MT5 в списке. При успехе возвращается true
|
|
bool _OrderSelectByPos(uint uiPosIdx)
|
|
{
|
|
ulSelectedPosTicket = PositionGetTicket(uiPosIdx);
|
|
|
|
if(ulSelectedPosTicket == NULL)
|
|
return(false);
|
|
|
|
return(true);
|
|
};
|
|
|
|
// Функция-аналог функции OrderSelect(SELECT_BY_TICKET) из MT4 для открытых ордеров.
|
|
// На вход передается индекс открытой позиции MT5 в списке. При успехе возвращается true
|
|
bool _OrderSelectByTicket(uint uiTicket)
|
|
{
|
|
if(PositionSelectByTicket(uiTicket)==true)
|
|
{
|
|
ulSelectedPosTicket = uiTicket;
|
|
return(true);
|
|
};
|
|
|
|
ulSelectedPosTicket = NULL;
|
|
|
|
return(false);
|
|
};
|
|
|
|
// Функция-аналог функции OrderSymbol из MT4
|
|
// Возвращает строку-символ выбранного ордера
|
|
string _OrderSymbol()
|
|
{
|
|
string strRes = PositionGetString(POSITION_SYMBOL);
|
|
return(strRes);
|
|
};
|
|
|
|
// Функция-аналог функции OrderMagicNumber из MT4
|
|
long _OrderMagicNumber()
|
|
{
|
|
long lRes = PositionGetInteger(POSITION_MAGIC);
|
|
return(lRes);
|
|
};
|
|
|
|
// Функция-аналог функции OrderOpenPrice из MT4
|
|
double _OrderOpenPrice()
|
|
{
|
|
return(PositionGetDouble(POSITION_PRICE_OPEN));
|
|
};
|
|
|
|
|
|
// Функция-аналог функции OrderLots из MT4
|
|
double _OrderLots()
|
|
{
|
|
return(PositionGetDouble(POSITION_VOLUME));
|
|
};
|
|
|
|
|
|
// Функция-аналог функции OrdersTotal() из MT4 для исторических ордеров
|
|
int _OrdersHistoryTotal()
|
|
{
|
|
return(HistoryDealsTotal());
|
|
};
|
|
|
|
#define OT_BUY 0
|
|
#define OT_SELL 1
|
|
|
|
// Функция-аналог функции OrderType из MT4
|
|
int _OrderType()
|
|
{
|
|
ENUM_POSITION_TYPE ptType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
|
|
switch(ptType)
|
|
{
|
|
case POSITION_TYPE_BUY: return(0);
|
|
case POSITION_TYPE_SELL: return(1);
|
|
default:
|
|
break;
|
|
};
|
|
|
|
return(WRONG_VALUE);
|
|
};
|
|
|
|
// Функция-аналог функции OrderOpenTime из MT4
|
|
datetime _OrderOpenTime()
|
|
{
|
|
return((datetime)PositionGetInteger(POSITION_TIME));
|
|
};
|
|
|
|
// Функция-аналог функции OrderTicket из MT4
|
|
ulong _OrderTicket()
|
|
{
|
|
return(ulSelectedPosTicket);
|
|
};
|
|
|
|
// Функция, подменяющая (не аналог!) функцию _OrderClosePrice из MT4
|
|
// Данная функция предназначена для определения цены закрытия исторических ордеров.
|
|
// Однако, в данном случае определяется цена закрытия открытого ордера - что не есть документированная возможность.
|
|
// Используем Bid или Ask для открытого ордера
|
|
double _OrderClosePrice()
|
|
{
|
|
if(_OrderType() == 1)
|
|
return(_Ask());
|
|
|
|
return(_Bid());
|
|
};
|
|
|
|
// Функция получает тикет открытой позиции по её идентификатору
|
|
long _GetOpenedComponentTicket(ulong ulDealID)
|
|
{
|
|
long lPosID = WRONG_VALUE;
|
|
|
|
// Выберем сделку в истории по идентификатору
|
|
if(HistoryDealSelect(ulDealID)!=true)
|
|
{
|
|
Print("ERROR !!! Не удалось выбрать в истории сделку, DealID = " + IntegerToString(ulDealID));
|
|
return(WRONG_VALUE);
|
|
};
|
|
|
|
// Выбираем PosID только что открытой сделки
|
|
if(HistoryDealGetInteger(ulDealID,DEAL_POSITION_ID,lPosID)!=true)
|
|
{
|
|
Print("ERROR !!! Не удалось получить PosID сделки! GetLastError: " + IntegerToString(GetLastError()));
|
|
return(WRONG_VALUE);
|
|
};
|
|
|
|
int iPosNum = PositionsTotal();
|
|
ulong ulCurTicket = 0;
|
|
|
|
// Перебираем все позиции
|
|
for(int iI=0; iI<iPosNum; ++iI)
|
|
{
|
|
// Выбираем очередную позицию, и получаем ее тикет
|
|
ulCurTicket = PositionGetTicket(iI);
|
|
|
|
if(ulCurTicket == NULL)
|
|
continue;
|
|
|
|
// Проверяем PosID
|
|
if(PositionGetInteger(POSITION_IDENTIFIER)!= lPosID)
|
|
continue;
|
|
|
|
// Нужная позиция найдена !
|
|
return((long)ulCurTicket);
|
|
};
|
|
|
|
Print("ERROR !!! Все сделки перебрали, но не нашли нужную! GetLastError: " + IntegerToString(GetLastError()));
|
|
|
|
return(WRONG_VALUE);
|
|
};
|
|
|
|
|
|
#define OP_BUY 0
|
|
#define OP_SELL 1
|
|
|
|
// Аналог функции OrderSend MT4
|
|
int _OrderSend(string strSymbol,int iOrderType,double dVolume,double dPrice,int iSlippage,double dSL,double dTP,string strComment = NULL,int iMagic = NULL,datetime dtExpiration = NULL,color clrColor = clrNONE)
|
|
{
|
|
// Можем выставлять только ордера на покупку или продажу. Проверим это
|
|
switch(iOrderType)
|
|
{
|
|
case OP_BUY:
|
|
if(tTradeProcessor.Buy(dVolume,strSymbol,dPrice,dSL,dTP,strComment)!=true)
|
|
return(WRONG_VALUE);
|
|
break;
|
|
|
|
case OP_SELL:
|
|
if(tTradeProcessor.Sell(dVolume,strSymbol,dPrice,dSL,dTP,strComment)!=true)
|
|
return(WRONG_VALUE);
|
|
break;
|
|
|
|
default:
|
|
return(WRONG_VALUE);
|
|
};
|
|
|
|
if(tTradeProcessor.ResultRetcode()!= TRADE_RETCODE_DONE)
|
|
return(WRONG_VALUE);
|
|
|
|
Print("Позиция открыта. ResultDeal()= " + IntegerToString(tTradeProcessor.ResultDeal()));
|
|
|
|
return((int)_GetOpenedComponentTicket(tTradeProcessor.ResultDeal()));
|
|
};
|
|
// Функция-аналог OrderModify() в МТ4
|
|
bool _OrderModify(int iTicket,double dOpenPrice,double dSL,double dTP,datetime dtExpiration,color clrColor)
|
|
{
|
|
return(tTradeProcessor.PositionModify(iTicket,dSL,dTP));
|
|
};
|
|
|
|
// Функция закрывает ордер по указанному тикету
|
|
bool _OrderClose(ulong ulTicket,double dLots,double dPrice, int iSlippage,color clrColor)
|
|
{
|
|
if(_OrderSelectByTicket((uint)ulTicket)!=true)
|
|
return(false);
|
|
|
|
double dUseLots = _OrderLots();
|
|
|
|
if(dLots >= dUseLots )
|
|
return(tTradeProcessor.PositionClose(ulTicket,iSlippage));
|
|
|
|
return(tTradeProcessor.PositionClosePartial(ulTicket,dLots,iSlippage));
|
|
};
|
|
|
|
// Функция-аналог функции OrderSelect(SELECT_BY_TICKET) из MT4 для исторических ордеров.
|
|
// На вход передается индекс открытой позиции MT5 в списке. При успехе возвращается true
|
|
bool _HstOrderSelectByPos(uint uiPosIdx)
|
|
{
|
|
ulSelectedHistoryPosTicket = HistoryDealGetTicket(uiPosIdx);
|
|
|
|
if(ulSelectedHistoryPosTicket == NULL)
|
|
return(false);
|
|
|
|
ENUM_DEAL_ENTRY deDealEntry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(ulSelectedHistoryPosTicket,DEAL_ENTRY);
|
|
|
|
if(deDealEntry != DEAL_ENTRY_OUT)
|
|
{
|
|
ulSelectedHistoryPosTicket = NULL;
|
|
return(false);
|
|
};
|
|
|
|
|
|
return(true);
|
|
};
|
|
|
|
string _HstOrderSymbol()
|
|
{
|
|
return(HistoryDealGetString(ulSelectedHistoryPosTicket,DEAL_SYMBOL));
|
|
};
|
|
|
|
long _HstOrderMagicNumber()
|
|
{
|
|
return(HistoryDealGetInteger(ulSelectedHistoryPosTicket,DEAL_MAGIC));
|
|
};
|
|
|
|
double _HstOrderProfit()
|
|
{
|
|
return(HistoryDealGetDouble(ulSelectedHistoryPosTicket,DEAL_PROFIT));
|
|
};
|
|
|
|
datetime _HstOrderCloseTime()
|
|
{
|
|
return((datetime)HistoryDealGetInteger(ulSelectedHistoryPosTicket,DEAL_TIME));
|
|
};
|
|
|
|
|
|
// Функция, предназначенная для обновления индикаторов
|
|
bool _Refresh()
|
|
{
|
|
SymbolInfoTick(Symbol(),mtLastTick);
|
|
|
|
ibBands.Refresh();
|
|
|
|
iaATR.Refresh();
|
|
|
|
imMA.Refresh();
|
|
|
|
if(HistorySelect(NULL,TimeCurrent())!=true)
|
|
return(false);
|
|
|
|
dtHistorySelectMoment = TimeCurrent();
|
|
|
|
return(true);
|
|
};
|
|
|
|
|
|
|
|
int OnInit()
|
|
{
|
|
// Устанвливаем число знаков и коррекцию для котировок
|
|
// По умолчанию d45QuotesRatio = 1
|
|
iDigits = Digits() ;
|
|
if (iDigits == 3 || iDigits == 5)
|
|
d45QuotesRatio = 10.0 ;
|
|
|
|
dMaxRisk = MaxRisk ;
|
|
_HideTestIndicators(true);
|
|
|
|
// Создадим индикаторы
|
|
if(ibBands.Create(Symbol(),PERIOD_CURRENT,uiIBandsPeriod,iIBandsMaShift,dIBandsDeviation,apIBandsPrice)!=true)
|
|
{
|
|
Print("Не удалось создать индикатор iBands! Работа невозможна.");
|
|
return(WRONG_VALUE);
|
|
};
|
|
|
|
if(iaATR.Create(Symbol(),PERIOD_CURRENT,ATR_PERIOD)!=true)
|
|
{
|
|
Print("Не удалось создать индикатор iATR! Работа невозможна.");
|
|
return(WRONG_VALUE);
|
|
};
|
|
|
|
if(imMA.Create(Symbol(),PERIOD_CURRENT,MA_PERIOD,0,MODE_SMA,PRICE_MEDIAN)!=true)
|
|
{
|
|
Print("Не удалось создать индикатор iMA! Работа невозможна.");
|
|
return(WRONG_VALUE);
|
|
};
|
|
|
|
// Инициализируем торговый процессор
|
|
tTradeProcessor.LogLevel(LOG_LEVEL_ALL);
|
|
tTradeProcessor.SetExpertMagicNumber(Magic);
|
|
tTradeProcessor.SetDeviationInPoints(MaxSlippage);
|
|
tTradeProcessor.SetMarginMode();
|
|
|
|
// Пока позиция не выбрана
|
|
ulSelectedPosTicket = NULL;
|
|
|
|
// Пока история не выбиралась.
|
|
dtHistorySelectMoment = NULL;
|
|
|
|
return(0);
|
|
}
|
|
//init <<==-------- --------
|
|
|
|
void OnTick()
|
|
{
|
|
|
|
// Обновим данные
|
|
_Refresh();
|
|
|
|
int iTotalOpenedOrders;
|
|
int iCurOrderIdx;
|
|
|
|
ChartSetInteger(ChartID(),CHART_SHOW_GRID,0);
|
|
ChartSetInteger(ChartID(),CHART_MODE,CHART_CANDLES);
|
|
_HideTestIndicators(true);
|
|
|
|
|
|
// Проверим, чтобы число доступных баров было больше десяти.
|
|
if ( _Bars() < MIN_AVAILIBLE_BARS )
|
|
{
|
|
Comment("Not enough bars");
|
|
return;
|
|
};
|
|
|
|
|
|
// Если Ask не выше верхней полосы Боллинджера и ATR не более 150 пунктов на пятизнаке
|
|
if ( !(_Ask()>=_iBands(2)) && !(_iATR() >=d45QuotesRatio * 15.0 * Point()))
|
|
{
|
|
// Если текущий час входит в пределы часа начала и часа конца.
|
|
if ((HourStart < HourEnd && _TimeHour(TimeCurrent()) >= HourStart && _TimeHour(TimeCurrent()) < HourEnd )||(HourStart > HourEnd && (_TimeHour(TimeCurrent()) < HourEnd || _TimeHour(TimeCurrent()) >= HourStart)))
|
|
{
|
|
// Посчитаем открытые ордера
|
|
iTotalOpenedOrders = 0;
|
|
for (iCurOrderIdx = _OrdersTotal() - 1 ; iCurOrderIdx >= 0 ; --iCurOrderIdx)
|
|
{
|
|
if ( _OrderSelectByPos(iCurOrderIdx) == true )
|
|
{
|
|
if ( _OrderSymbol() == Symbol() && _OrderMagicNumber() == Magic )
|
|
++iTotalOpenedOrders;
|
|
}
|
|
else
|
|
{
|
|
Print("_OrderSelectByPos() error - ",ErrorDescription(GetLastError()));
|
|
};
|
|
}; // цикл пересчёта открытых ордеров
|
|
|
|
if ( iTotalOpenedOrders < 1 )
|
|
{
|
|
if ( UseRisk == false )
|
|
liDATA_11();
|
|
|
|
if ( UseRisk == true )
|
|
liDATA_9();
|
|
};
|
|
}; // если текущий час входит в пределы часа начала и конца
|
|
}; // Если Ask не выше верхней полосы Боллинджера и ATR не более 150 пунктов на пятизнаке
|
|
|
|
|
|
// Если Bid не ниже нижней полосы Боллинджера и ATR не более 150 пунктов на пятизнаке
|
|
if ( !(_Bid()<=_iBands(1)) && !(_iATR()>=d45QuotesRatio * 15.0 * Point()) )
|
|
{
|
|
// Если текущий час входит в пределы часа начала и часа конца.
|
|
if((HourStart < HourEnd && _TimeHour(TimeCurrent()) >= HourStart && _TimeHour(TimeCurrent()) < HourEnd ) || (HourStart > HourEnd && (_TimeHour(TimeCurrent()) < HourEnd || _TimeHour(TimeCurrent()) >= HourStart)))
|
|
{
|
|
iTotalOpenedOrders = 0;
|
|
for (iCurOrderIdx = _OrdersTotal() - 1 ; iCurOrderIdx >= 0 ; --iCurOrderIdx)
|
|
{
|
|
if (_OrderSelectByPos(iCurOrderIdx))
|
|
{
|
|
if ( _OrderSymbol() == Symbol() && _OrderMagicNumber() == Magic )
|
|
++iTotalOpenedOrders;
|
|
}
|
|
else
|
|
Print("OrderSend() error - ",ErrorDescription(GetLastError()));
|
|
}; // цикл пересчёта открытых ордеров
|
|
|
|
if ( iTotalOpenedOrders < 1 )
|
|
{
|
|
if ( UseRisk == false )
|
|
liDATA_12();
|
|
|
|
if ( UseRisk == true )
|
|
liDATA_10();
|
|
};
|
|
}; // если текущий час входит в пределы часа начала и конца
|
|
}; // Если Bid не ниже нижней полосы Боллинджера и ATR не более 150 пунктов на пятизнаке
|
|
|
|
liDATA_7();
|
|
|
|
liDATA_8();
|
|
|
|
return;
|
|
}
|
|
|
|
//start <<==-------- --------
|
|
void OnDeinit(const int reason)
|
|
{
|
|
};
|
|
//deinit <<==-------- --------
|
|
|
|
void liDATA_7()
|
|
{
|
|
int REPUTK_1_in_si30si2[30][2];
|
|
int iTotalPos;
|
|
int REPUTK_3_in;
|
|
int iCurPos;
|
|
//----- -----
|
|
ArrayInitialize(REPUTK_1_in_si30si2,NULL); // Заполняем массив нулями, иначе выходит предупреждение
|
|
|
|
|
|
if (bIUseMA == true && _Ask()>=_iMA() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( _Ask() - _Bid() <=MaxSpread * d45QuotesRatio * Point() )
|
|
{
|
|
iTotalPos = _OrdersTotal() ;
|
|
REPUTK_3_in = 0 ;
|
|
|
|
for (iCurPos = 0 ; iCurPos < iTotalPos ; ++iCurPos)
|
|
{
|
|
if ( ( _OrderSelectByPos(iCurPos) && (_OrderType() != OT_SELL || _OrderSymbol() != Symbol() || _OrderMagicNumber() != Magic2) ) ) continue;
|
|
REPUTK_1_in_si30si2[REPUTK_3_in][0] = _Long2Int(_OrderOpenTime());
|
|
REPUTK_1_in_si30si2[REPUTK_3_in][1] = (int)_OrderTicket();
|
|
REPUTK_3_in = REPUTK_3_in + 1;
|
|
}
|
|
|
|
if ( REPUTK_3_in > 1 )
|
|
{
|
|
// ВНИМАНИЕ ! Закомментарено изменение размера массива.
|
|
// Массив статически определён, невозможно менять его размер, в МТ4 эта ошибка не отображалась.
|
|
// Размер массива в первом измерении 30, и, похоже, что это максимальное число позиций.
|
|
// Должно хватить - не изменяем размер статического массива.
|
|
// ArrayResize(REPUTK_1_in_si30si2,REPUTK_3_in,0);
|
|
|
|
//ArraySort(REPUTK_1_in_si30si2,0,0,1); // Так было в MT4
|
|
ArraySort(REPUTK_1_in_si30si2);
|
|
}
|
|
|
|
for (iCurPos = 0 ; iCurPos < REPUTK_3_in ; ++iCurPos)
|
|
{
|
|
if (_OrderSelectByTicket(REPUTK_1_in_si30si2[iCurPos][1]) != true || _OrderClose(_OrderTicket(),_OrderLots(),_OrderClosePrice(),MaxSlippage,Red) != false ) continue;
|
|
Print("OrderClose() error - ",ErrorDescription(GetLastError()));
|
|
}
|
|
|
|
} // if ( Ask - Bid<=MaxSpread * DATA_2_do * Point() )
|
|
} // void liDATA_7()
|
|
|
|
void liDATA_8()
|
|
{
|
|
int REPUTK_1_in_si30si2[30][2];
|
|
int REPUTK_2_in;
|
|
int REPUTK_3_in;
|
|
int REPUTK_4_in;
|
|
//----- -----
|
|
|
|
ArrayInitialize(REPUTK_1_in_si30si2,NULL);
|
|
|
|
if (bIUseMA == true && _Bid()<=_iMA() )
|
|
{
|
|
return;
|
|
}
|
|
if ( _Ask() - _Bid()<=MaxSpread * d45QuotesRatio * Point() )
|
|
{
|
|
REPUTK_2_in = _OrdersTotal() ;
|
|
REPUTK_3_in = 0 ;
|
|
for (REPUTK_4_in = 0 ; REPUTK_4_in < REPUTK_2_in ; REPUTK_4_in = REPUTK_4_in + 1)
|
|
{
|
|
if ( ( _OrderSelectByPos(REPUTK_4_in) && (_OrderType() != 0 || _OrderSymbol() != Symbol() || _OrderMagicNumber() != Magic) ) ) continue;
|
|
|
|
REPUTK_1_in_si30si2[REPUTK_3_in][0] = _Long2Int(_OrderOpenTime());
|
|
REPUTK_1_in_si30si2[REPUTK_3_in][1] = (int)_OrderTicket();
|
|
REPUTK_3_in = REPUTK_3_in + 1;
|
|
|
|
}
|
|
if ( REPUTK_3_in > 1 )
|
|
{
|
|
// ВНИМАНИЕ ! Закомментарено изменение размера массива.
|
|
// Массив статически определён, невозможно менять его размер, в МТ4 эта ошибка не отображалась.
|
|
// Размер массива в первом измерении 30, и, похоже, что это максимальное число позиций.
|
|
// Должно хватить - не изменяем размер статического массива.
|
|
// ArrayResize(REPUTK_1_in_si30si2,REPUTK_3_in,0);
|
|
|
|
// ArraySort(REPUTK_1_in_si30si2,0,0,1); Так было в МТ4
|
|
ArraySort(REPUTK_1_in_si30si2);
|
|
}
|
|
for (REPUTK_4_in = 0 ; REPUTK_4_in < REPUTK_3_in ; REPUTK_4_in = REPUTK_4_in + 1)
|
|
{
|
|
if ( _OrderSelectByTicket(REPUTK_1_in_si30si2[REPUTK_4_in][1]) != true || _OrderClose(_OrderTicket(),_OrderLots(),_OrderClosePrice(),MaxSlippage,Red) != false ) continue;
|
|
Print("OrderClose() error - ",ErrorDescription(GetLastError()));
|
|
|
|
}
|
|
}
|
|
}
|
|
//liDATA_8 <<==-------- --------
|
|
void liDATA_9()
|
|
{
|
|
double REPUTK_1_do;
|
|
double REPUTK_2_do;
|
|
double REPUTK_3_do;
|
|
double REPUTK_4_do;
|
|
double REPUTK_5_do;
|
|
double REPUTK_6_do;
|
|
int REPUTK_7_in;
|
|
double REPUTK_8_do;
|
|
double REPUTK_9_do;
|
|
int REPUTK_10_in;
|
|
bool REPUTK_11_bo = false;
|
|
//----- -----
|
|
datetime REPUT_da_1;
|
|
datetime REPUT_da_2;
|
|
int REPUT_in_3;
|
|
|
|
REPUT_da_1 = TimeCurrent();
|
|
REPUT_da_2 = 0;
|
|
if ( _OrdersHistoryTotal() > 0 )
|
|
{
|
|
for (REPUT_in_3 = _OrdersHistoryTotal() - 1 ; REPUT_in_3 >= 0 ; REPUT_in_3=REPUT_in_3 - 1)
|
|
{
|
|
if ( _HstOrderSelectByPos(REPUT_in_3) == true && _HstOrderSymbol() == Symbol() && ( _HstOrderMagicNumber() == Magic || _HstOrderMagicNumber() == Magic2 ) )
|
|
{
|
|
if ( !(_HstOrderProfit()<0.0) ) break;
|
|
REPUT_da_2 = _HstOrderCloseTime();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
REPUT_da_2 = -3600;
|
|
}
|
|
if ( REPUT_da_1 < REPUT_da_2 + 3600 || _Ask() - _Bid()>MaxSpread * d45QuotesRatio * Point() ) return;
|
|
REPUTK_1_do = _MarketInfo(Symbol(),MODE_LOTSIZE) ;
|
|
REPUTK_2_do = 1000.0 ;
|
|
REPUTK_3_do = _AccountFreeMargin() / 100.0 * dMaxRisk ;
|
|
if ( StopLoss == 0 )
|
|
{
|
|
Print("OrderSend() error - stoploss can not be zero");
|
|
}
|
|
REPUTK_4_do = REPUTK_3_do / StopLoss / d45QuotesRatio ;
|
|
REPUTK_5_do = 0.001 ;
|
|
REPUTK_6_do = _MarketInfo(Symbol(),MODE_MINLOT) ;
|
|
REPUTK_7_in = 0 ;
|
|
while (REPUTK_6_do<1.0)
|
|
{
|
|
REPUTK_6_do = REPUTK_6_do * MathPow(10.0,REPUTK_7_in) ;
|
|
REPUTK_7_in = REPUTK_7_in + 1;
|
|
}
|
|
REPUTK_5_do = NormalizeDouble(REPUTK_4_do,REPUTK_7_in - 1) ;
|
|
if ( REPUTK_5_do<_MarketInfo(Symbol(),MODE_MINLOT) )
|
|
{
|
|
REPUTK_5_do = _MarketInfo(Symbol(),MODE_MINLOT) ;
|
|
}
|
|
if ( REPUTK_5_do>_MarketInfo(Symbol(),MODE_MAXLOT) )
|
|
{
|
|
REPUTK_5_do = _MarketInfo(Symbol(),MODE_MAXLOT) ;
|
|
}
|
|
REPUTK_8_do = _Ask() - StopLoss * d45QuotesRatio * Point() ;
|
|
if ( StopLoss == 0 )
|
|
{
|
|
REPUTK_8_do = 0.0 ;
|
|
}
|
|
REPUTK_9_do = TakeProfit * d45QuotesRatio * Point() + _Ask();
|
|
if ( TakeProfit == 0 )
|
|
{
|
|
REPUTK_9_do = 0.0 ;
|
|
}
|
|
REPUTK_10_in = -1 ;
|
|
REPUTK_10_in = _OrderSend(Symbol(),OP_BUY,REPUTK_5_do,_Ask(),MaxSlippage,0.0,0.0,DATA_1_st,Magic,0,Blue);
|
|
if ( REPUTK_10_in > -1 )
|
|
{
|
|
if ( _OrderSelectByTicket(REPUTK_10_in) )
|
|
{
|
|
REPUTK_11_bo = _OrderModify((int)_OrderTicket(),_OrderOpenPrice(),REPUTK_8_do,REPUTK_9_do,0,Blue) ;
|
|
}
|
|
if ( REPUTK_11_bo != false ) return;
|
|
Print("OrderModify() error - ",ErrorDescription(GetLastError()));
|
|
return;
|
|
}
|
|
Print("OrderSend() error - ",ErrorDescription(GetLastError()));
|
|
}
|
|
//liDATA_9 <<==-------- --------
|
|
void liDATA_10()
|
|
{
|
|
double dTradeContractSize;
|
|
double REPUTK_2_do;
|
|
double REPUTK_3_do;
|
|
double REPUTK_4_do;
|
|
double REPUTK_5_do;
|
|
double REPUTK_6_do;
|
|
int REPUTK_7_in;
|
|
double REPUTK_8_do;
|
|
double REPUTK_9_do;
|
|
int REPUTK_10_in;
|
|
bool REPUTK_11_bo = false;
|
|
//----- -----
|
|
datetime REPUT_da_2;
|
|
int REPUT_in_3;
|
|
|
|
datetime dTimeCurrent = TimeCurrent();
|
|
REPUT_da_2 = 0;
|
|
if ( _OrdersHistoryTotal() > 0 )
|
|
{
|
|
for (REPUT_in_3 = _OrdersHistoryTotal() - 1 ; REPUT_in_3 >= 0 ; REPUT_in_3=REPUT_in_3 - 1)
|
|
{
|
|
if ( _HstOrderSelectByPos(REPUT_in_3) == true && _HstOrderSymbol() == Symbol() && ( _HstOrderMagicNumber() == Magic || _HstOrderMagicNumber() == Magic2 ) )
|
|
{
|
|
if ( !(_HstOrderProfit()<0.0) ) break;
|
|
REPUT_da_2 = _HstOrderCloseTime();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
REPUT_da_2 = -3600;
|
|
}
|
|
if ( dTimeCurrent < REPUT_da_2 + 3600 || _Ask() - _Bid()>MaxSpread * d45QuotesRatio * Point() ) return;
|
|
dTradeContractSize = _MarketInfo(Symbol(),MODE_LOTSIZE);
|
|
REPUTK_2_do = 1000.0 ;
|
|
REPUTK_3_do = _AccountFreeMargin() / 100.0 * dMaxRisk ;
|
|
if ( StopLoss == 0 )
|
|
{
|
|
Print("OrderSend() error - stoploss can not be zero");
|
|
}
|
|
REPUTK_4_do = REPUTK_3_do / StopLoss / d45QuotesRatio ;
|
|
REPUTK_5_do = 0.001 ;
|
|
REPUTK_6_do = _MarketInfo(Symbol(),MODE_MINLOT) ;
|
|
REPUTK_7_in = 0 ;
|
|
while (REPUTK_6_do<1.0)
|
|
{
|
|
REPUTK_6_do = REPUTK_6_do * MathPow(10.0,REPUTK_7_in) ;
|
|
REPUTK_7_in = REPUTK_7_in + 1;
|
|
}
|
|
REPUTK_5_do = NormalizeDouble(REPUTK_4_do,REPUTK_7_in - 1) ;
|
|
if ( REPUTK_5_do<_MarketInfo(Symbol(),MODE_MINLOT) )
|
|
{
|
|
REPUTK_5_do = _MarketInfo(Symbol(),MODE_MINLOT) ;
|
|
}
|
|
if ( REPUTK_5_do>_MarketInfo(Symbol(),MODE_MAXLOT) )
|
|
{
|
|
REPUTK_5_do = _MarketInfo(Symbol(),MODE_MAXLOT) ;
|
|
}
|
|
REPUTK_8_do = StopLoss * d45QuotesRatio * Point() + _Bid() ;
|
|
if ( StopLoss == 0 )
|
|
{
|
|
REPUTK_8_do = 0.0 ;
|
|
}
|
|
REPUTK_9_do = _Bid() - TakeProfit * d45QuotesRatio * Point() ;
|
|
if ( TakeProfit == 0 )
|
|
{
|
|
REPUTK_9_do = 0.0 ;
|
|
}
|
|
REPUTK_10_in = -1 ;
|
|
REPUTK_10_in = _OrderSend(Symbol(),OP_SELL,REPUTK_5_do,_Bid(),MaxSlippage,0.0,0.0,DATA_1_st,Magic2,0,Red) ;
|
|
if ( REPUTK_10_in > -1 )
|
|
{
|
|
if ( _OrderSelectByTicket(REPUTK_10_in) )
|
|
{
|
|
REPUTK_11_bo = _OrderModify((int)_OrderTicket(),_OrderOpenPrice(),REPUTK_8_do,REPUTK_9_do,0,Red) ;
|
|
}
|
|
if ( REPUTK_11_bo != false ) return;
|
|
Print("OrderModify() error - ",ErrorDescription(GetLastError()));
|
|
return;
|
|
}
|
|
Print("OrderSend() error - ",ErrorDescription(GetLastError()));
|
|
}
|
|
//liDATA_10 <<==-------- --------
|
|
void liDATA_11()
|
|
{
|
|
double REPUTK_1_do;
|
|
double REPUTK_2_do;
|
|
int REPUTK_3_in;
|
|
bool REPUTK_4_bo = false;
|
|
//----- -----
|
|
datetime REPUT_da_1;
|
|
datetime REPUT_da_2;
|
|
int REPUT_in_3;
|
|
|
|
REPUT_da_1 = TimeCurrent();
|
|
REPUT_da_2 = 0;
|
|
if ( _OrdersHistoryTotal() > 0 )
|
|
{
|
|
for (REPUT_in_3 = _OrdersHistoryTotal() - 1 ; REPUT_in_3 >= 0 ; REPUT_in_3=REPUT_in_3 - 1)
|
|
{
|
|
if ( _HstOrderSelectByPos(REPUT_in_3) == true && _HstOrderSymbol() == Symbol() && ( _HstOrderMagicNumber() == Magic || _HstOrderMagicNumber() == Magic2 ) )
|
|
{
|
|
if ( !(_HstOrderProfit()<0.0) ) break;
|
|
REPUT_da_2 = _HstOrderCloseTime();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
REPUT_da_2 = -3600;
|
|
}
|
|
if ( REPUT_da_1 < REPUT_da_2 + 3600 || _Ask() - _Bid()>MaxSpread * d45QuotesRatio * Point() ) return;
|
|
REPUTK_1_do = _Ask() - StopLoss * d45QuotesRatio * Point() ;
|
|
if ( StopLoss == 0 )
|
|
{
|
|
REPUTK_1_do = 0.0 ;
|
|
}
|
|
REPUTK_2_do = TakeProfit * d45QuotesRatio * Point() + _Ask();
|
|
if ( TakeProfit == 0 )
|
|
{
|
|
REPUTK_2_do = 0.0 ;
|
|
}
|
|
REPUTK_3_in = -1 ;
|
|
REPUTK_3_in = _OrderSend(Symbol(),OP_BUY,Lots,_Ask(),MaxSlippage,0.0,0.0,DATA_1_st,Magic,0,Blue) ;
|
|
if ( REPUTK_3_in > -1 )
|
|
{
|
|
if ( _OrderSelectByTicket(REPUTK_3_in) )
|
|
{
|
|
REPUTK_4_bo = _OrderModify((int)_OrderTicket(),_OrderOpenPrice(),REPUTK_1_do,REPUTK_2_do,0,Blue) ;
|
|
}
|
|
if ( REPUTK_4_bo != false ) return;
|
|
Print("OrderModify() error - ",ErrorDescription(GetLastError()));
|
|
return;
|
|
}
|
|
Print("OrderSend() error - ",ErrorDescription(GetLastError()));
|
|
}
|
|
//liDATA_11 <<==-------- --------
|
|
|
|
|
|
void liDATA_12()
|
|
{
|
|
double REPUTK_1_do;
|
|
double REPUTK_2_do;
|
|
int REPUTK_3_in;
|
|
bool REPUTK_4_bo = false;
|
|
//----- -----
|
|
datetime REPUT_da_1;
|
|
datetime REPUT_da_2;
|
|
int REPUT_in_3;
|
|
|
|
REPUT_da_1 = TimeCurrent();
|
|
REPUT_da_2 = 0;
|
|
if ( _OrdersHistoryTotal() > 0 )
|
|
{
|
|
for (REPUT_in_3 = _OrdersHistoryTotal() - 1 ; REPUT_in_3 >= 0 ; REPUT_in_3=REPUT_in_3 - 1)
|
|
{
|
|
if ( _HstOrderSelectByPos(REPUT_in_3) == true && _HstOrderSymbol() == Symbol() && ( _HstOrderMagicNumber() == Magic || _HstOrderMagicNumber() == Magic2 ) )
|
|
{
|
|
if ( !(_HstOrderProfit()<0.0) ) break;
|
|
REPUT_da_2 = _HstOrderCloseTime();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
REPUT_da_2 = -3600;
|
|
}
|
|
if ( REPUT_da_1 < REPUT_da_2 + 3600 || _Ask() - _Bid()>MaxSpread * d45QuotesRatio * Point() ) return;
|
|
REPUTK_1_do = StopLoss * d45QuotesRatio * Point() + _Bid() ;
|
|
if ( StopLoss == 0 )
|
|
{
|
|
REPUTK_1_do = 0.0 ;
|
|
}
|
|
REPUTK_2_do = _Bid() - TakeProfit * d45QuotesRatio * Point() ;
|
|
if ( TakeProfit == 0 )
|
|
{
|
|
REPUTK_2_do = 0.0 ;
|
|
}
|
|
REPUTK_3_in = -1 ;
|
|
REPUTK_3_in = _OrderSend(Symbol(),OP_SELL,Lots,_Bid(),MaxSlippage,0.0,0.0,DATA_1_st,Magic2,0,Red) ;
|
|
if ( REPUTK_3_in > -1 )
|
|
{
|
|
if ( _OrderSelectByTicket(REPUTK_3_in) )
|
|
{
|
|
REPUTK_4_bo = _OrderModify((int)_OrderTicket(),_OrderOpenPrice(),REPUTK_1_do,REPUTK_2_do,0,Red) ;
|
|
}
|
|
if ( REPUTK_4_bo != false ) return;
|
|
Print("OrderModify() error - ",ErrorDescription(GetLastError()));
|
|
return;
|
|
}
|
|
Print("OrderSend() error - ",ErrorDescription(GetLastError()));
|
|
}
|