LIP/Arch/RU/LIP_v01.001/Include/LIP_Fun1_5_v1.001.mqh
super.admin 291e846eab convert
2025-05-30 15:03:51 +02:00

5190 lines
No EOL
580 KiB
MQL5

//======================================================================================================
// LibreNetka Function1_5 v4.106 MQL5
// Основные функции алгоритма
// Librecoin (c)2014-2017
//======================================================================================================
#property strict
//======================================================================================================
// INCLUDE - подключаемые модули
//------------------------------------------------------------------------------------------------------
//----- Обратные ссылки на основной файл проекта
#include "LIP_Ref_5_v1.001.mqh"
//======================================================================================================
// MAIN FUNCTIONS
//------------------------------------------------------------------------------------------------------
//
//======================================================================================================
// B4BClose();//v66.154 - Закрывает все возможные ордера встречно
//======================================================================================================
bool B4BClose( long iMagic,
int inGrides){
//Print("****** B4BClose 0 >>");
if (!B4BCloseOn) {return(false);}
bool
Closed=false,
BePair=true;
double
//AddCom=0.0,
closeLot=0,
closeProfit=0,
lossLotBUY=0,
lossLotSELL=0,
lossBUY,
lossSELL,
profitLotBUY=0,
profitLotSELL=0,
profitBUY,
profitSELL;
long
OrderMagicN=iMagic,
Ord_Tick=-1,
nMLossBUY=-1,
nMLossSELL=-1,
nMProfitBUY=-1,
nMProfitSELL=-1;
// if (AccountFreeMargin()>B4BCloseLim*MathMax(AccountInfoDouble(ACCOUNT_EQUITY),AccountInfoDouble(ACCOUNT_BALANCE))) {return(true);}
// if (AccountFreeMargin()>iB4BCloseLim*AccountInfoDouble(ACCOUNT_BALANCE)) {return(true);}//Порог от Equity для инициации закрытия
//if (AccountInfoDouble(ACCOUNT_EQUITY)<iB4BCloseLim*AccountInfoDouble(ACCOUNT_BALANCE)) {return(true);}//Порог от Equity для инициации закрытия
while (BePair==true)
{
closeLot=0;
closeProfit=0;
lossLotBUY=0;
lossLotSELL=0;
profitLotBUY=0;
profitLotSELL=0;
lossBUY=99999;
lossSELL=99999;
profitBUY=-99999;
profitSELL=-99999;
nMLossBUY=-1;
nMLossSELL=-1;
nMProfitBUY=-1;
nMProfitSELL=-1;
{for(int i=PositionsTotal()-1;i>=0;i--)
{//перебор всех ордеров
ulong Pos_Tick=PositionGetTicket(i);//Выбираем позицию по номеру в списке
{if(Pos_Tick<=0){continue;}}//Неудачно - следующий
{if(!PositionSelectByTicket(Pos_Tick)){continue;}}//Выбираем позицию по тикету? Неудачно - следующий
{if(PositionGetString(POSITION_SYMBOL)!=TheSymbol){continue;}}
OrderMagicN=PositionGetInteger(POSITION_MAGIC);
{if((OrderMagicN<iMagic)||(OrderMagicN>=iMagic+inGrides)){continue;}} //Отбор по магику
//Ищем ордер с максимальной прибылью на лот
if (PositionGetDouble(POSITION_PROFIT)
//+PositionGetDouble(POSITION_COMISSION)
+PositionGetDouble(POSITION_SWAP)-10*AddComPrice*PositionGetDouble(POSITION_VOLUME)>0.00001)
{
if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_BUY)
{
if (PositionGetDouble(POSITION_PROFIT)
//+PositionGetDouble(POSITION_COMISSION)
+PositionGetDouble(POSITION_SWAP)-10*AddComPrice*PositionGetDouble(POSITION_VOLUME)>profitBUY)
{
nMProfitBUY=Ord_Tick;
profitBUY=PositionGetDouble(POSITION_PROFIT)
//+PositionGetDouble(POSITION_COMISSION)
+PositionGetDouble(POSITION_SWAP)-10*AddComPrice*PositionGetDouble(POSITION_VOLUME);
profitLotBUY=PositionGetDouble(POSITION_VOLUME);
}//if(OrderProfit
}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)
if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)
{
if (PositionGetDouble(POSITION_PROFIT)
//+PositionGetDouble(POSITION_COMISSION)
+PositionGetDouble(POSITION_SWAP)-10*AddComPrice*PositionGetDouble(POSITION_VOLUME)>profitSELL)
{
nMProfitSELL=Ord_Tick;
profitSELL=PositionGetDouble(POSITION_PROFIT)
//+PositionGetDouble(POSITION_COMISSION)
+PositionGetDouble(POSITION_SWAP)-10*AddComPrice*PositionGetDouble(POSITION_VOLUME);
profitLotSELL=PositionGetDouble(POSITION_VOLUME);
}//if(OrderProfit
}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)
}//if(OrderProfit
//Ищем ордер с максимальным убытком на лот
//Ord_inf=PositionSelect(Ord_Tick,SELECT_BY_TICKET,MODE_TRADES);
//if (!Ord_inf) {break;}
if (PositionGetDouble(POSITION_PROFIT)
//+PositionGetDouble(POSITION_COMISSION)
+PositionGetDouble(POSITION_SWAP)-10*AddComPrice*PositionGetDouble(POSITION_VOLUME)<-0.00001)
{
if (((OP_TYPE)PositionGetInteger(POSITION_TYPE))==OP_BUY)
{
if (PositionGetDouble(POSITION_PROFIT)
//+PositionGetDouble(POSITION_COMISSION)
+PositionGetDouble(POSITION_SWAP)-10*AddComPrice*PositionGetDouble(POSITION_VOLUME)<lossBUY)
{
nMLossBUY=Ord_Tick;
lossBUY=PositionGetDouble(POSITION_PROFIT)
//+PositionGetDouble(POSITION_COMISSION)
+PositionGetDouble(POSITION_SWAP)-10*AddComPrice*PositionGetDouble(POSITION_VOLUME);
lossLotBUY=PositionGetDouble(POSITION_VOLUME);
}//if(OrderProfit
}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)
if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)
{
if (PositionGetDouble(POSITION_PROFIT)
//+PositionGetDouble(POSITION_COMISSION)
+PositionGetDouble(POSITION_SWAP)-10*AddComPrice*PositionGetDouble(POSITION_VOLUME)<lossSELL)
{
nMLossSELL=Ord_Tick;
lossSELL=PositionGetDouble(POSITION_PROFIT)
//+PositionGetDouble(POSITION_COMISSION)
+PositionGetDouble(POSITION_SWAP)-10*AddComPrice*PositionGetDouble(POSITION_VOLUME);
lossLotSELL=PositionGetDouble(POSITION_VOLUME);
}//if(OrderProfit
}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)
}//if(OrderProfit
}}//for(int y=PositionsTotal()-1;y>=0;y--)
double lim=100;
//Print("****** B4BClose 1 >>");
bool pairFoundBuy=false;
if ((profitBUY>0.00001)&&(lossSELL<-0.00001))//&&(profitBUY>=-lim*lossSELL))//&&(tTrendBid[iB4BTrend]<-0.0000001))//прибыльный BUY - убыточный SELL
{
closeLot=MathMin(profitLotBUY,lossLotSELL);
closeProfit=closeLot*(profitBUY/profitLotBUY+lossSELL/lossLotSELL);
pairFoundBuy=true;
if (Prn1) Print(" profitLotBUY=",profitLotBUY," lossLotSELL=",lossLotSELL);//," ltSprad=",ltSprad);
}
bool pairFoundSell=false;
if ((profitSELL>0.00001)&&(lossBUY<-0.00001))//&&(profitSELL>=-lim*lossBUY))//&&(tTrendAsk[iB4BTrend]>0.0000001))//прибыльный SELL - убыточный BUY
{
closeLot=MathMin(profitLotSELL,lossLotBUY);
closeProfit=closeLot*(profitSELL/profitLotSELL+lossBUY/lossLotBUY);
pairFoundSell=true;
if (Prn1) Print(" profitLotSELL=",profitLotSELL," lossLotBUY=",lossLotBUY);//," ltSprad=",ltSprad);
}
//Если пары есть - закрываем, пар нет - снимаем флаг продолжения
//Print("****** B4BClose 3 >>");
{if (true
//&&(false
// ||((profitBUY>0.01)&&(lossSELL<-0.01)&&(profitBUY>=-lim*lossSELL))
// ||((profitSELL>0.01)&&(lossBUY<-0.01)&&(profitSELL>=-lim*lossBUY)))
//&&(closeProfit>0.01*closeLot*ltSprad/Point)
&&((pairFoundBuy)||(pairFoundSell))
)
{
//if (Prn1) Print("**************** Close B4B *********************");
//if (Prn1) Print(" profitBUY=",profitBUY," lossSELL=",lossSELL," profitSELL=",profitSELL," lossBUY=",lossBUY);
//if (closeProfit>4*closeLot*ltSprad/Point)
{//Если пары есть - закрываем
//Закрываем прибыльный BUY на убыточный SELL
//if ((profitBUY>0.00001)&&(lossSELL<-0.00001)&&(profitBUY>=-lim*lossSELL)&&(tTrendBid[iB4BTrend]<-0.0000001))//прибыльный BUY - убыточный SELL
if (pairFoundBuy)
{
ulong Pos_Tick=PositionSelectByTicket(nMProfitBUY);
{if(Pos_Tick<=0){continue;}}//Неудачно - следующий
Ord_inf=PositionCloseBy(PositionGetInteger(POSITION_TICKET),nMLossSELL);
//if (Ord_inf) {B4BCloseN++;B4BCloseBN++;}
if (Ord_inf) {Closed=true;}
if (Prn1) Print(" profitBUY="+DoubleToString(profitBUY,2)+" nMProfitBUY="+IntegerToString(nMProfitBUY)
+" lossSELL="+DoubleToString(lossSELL,2)+" nMLossSELL="+IntegerToString(nMLossSELL)
+" Ord_inf="+((Ord_inf)?("true"):("false")));//," B4BCloseN (A/B/S)=",B4BCloseN,"/",B4BCloseBN,"/",B4BCloseSN);
}
//Если все быстрые тренды по убытку BUY убыточные - убыток увеличивается
//if ((TrendMB[0])&&(TrendMB[0]))//&&(!TrendMB[1])&&(TrendMB[2])&&(TrendMB[3]))//&&(!TrendCB[2]))
//Закрываем прибыльный SELL на убыточный BUY
//if ((profitSELL>0.00001)&&(lossBUY<-0.00001)&&(profitSELL>=-lim*lossBUY)&&(tTrendAsk[iB4BTrend]>0.0000001))//прибыльный SELL - убыточный BUY
if (pairFoundSell)
{
ulong Pos_Tick=PositionSelectByTicket(nMProfitSELL);
{if(Pos_Tick<=0){continue;}}//Неудачно - следующий
Ord_inf=PositionCloseBy(PositionGetInteger(POSITION_TICKET),nMLossBUY);
//if (Ord_inf) {B4BCloseN++;B4BCloseSN++;}
if (Ord_inf) {Closed=true;}
if (Prn1) Print(" profitSELL="+DoubleToString(profitSELL,2)+" nMProfitSELL="+IntegerToString(nMProfitSELL)
+" lossBUY="+DoubleToString(lossBUY,2)+" nMLossBUY="+IntegerToString(nMLossBUY)
+" Ord_inf="+((Ord_inf)?("true"):("false")));//," B4BCloseN (A/B/S)=",B4BCloseN,"/",B4BCloseBN,"/",B4BCloseSN);
}
//тогда Bepair=true и будет следующий расчет
}
}else{
//Print("**************** BePair=false *********************");
//Если нет пар - снимаем флаг продолжения
BePair=false;//расчет окончен, всё что смогли - закрыли
}}//if (true
}//end while
return(Closed);
}//B4BClose()
//
//======================================================================================================
// CheckBounceStop() - проверка для остановки торговли по броску
//======================================================================================================
bool CheckBounceStop(string iSymbol,
//int inBars, //глубина просмотра в барах М1 (минутах)
bool &iBonceStopUp, //запрет вверх
bool &iBonceStopDown){ //запрет вниз
int
nnBars=MathMax3int(BonceDeep,BonceDeep2,BonceDeep3);
bool
Result = false; //не стоп
iBonceStopUp = false; //нет запрета вверх
iBonceStopDown = false; //нет запрета вниз
//-----
{if(Bars(iSymbol,PERIOD_M1)<nnBars+5)
{
iBonceStopUp = true; //запрет вверх
iBonceStopDown = true; //запрет вниз
return(true);
}}//if(Bars(TheSymbol,PERIOD_M1)<nnBars+5)
//----- Параметры ограничения по броскам вынес в параметры
double BonceMax=0;//
double BonceMin=Max_Int;//
double BonceMax2=0;//
double BonceMin2=Max_Int;//
double BonceMax3=0;//
double BonceMin3=Max_Int;//
int nBonceMax=0;
int nBonceMin=0;
int nBonceMax2=0;
int nBonceMin2=0;
int nBonceMax3=0;
int nBonceMin3=0;
iBonceStopUp=false;//Признак остановки по броску сбрасываем
iBonceStopDown=false;//Признак остановки по броску сбрасываем
{for(int nCurBar=0; nCurBar<=nnBars-1; nCurBar++)//Перебираем на глубину просмотра в барах М1 (минутах)
{
//Проверка на отсутствие броска
{if(nCurBar<BonceDeep)//Если глубина просмотра для определения броска не превышена
//Тут всё переделать именно на односторонний бросок - сейчас блокируются любые колебания превышенные по амплитуде
{
//Запоминаем минимаксы
{if(High[nCurBar]>BonceMax)
{
BonceMax=High[nCurBar];
nBonceMax=nCurBar;
}}//if(High[nCurBar]>BonceMax)
{if(Low[nCurBar]<BonceMin)
{
BonceMin=Low[nCurBar];
nBonceMin=nCurBar;
}}//if(Low[nCurBar]<BonceMin)
//Оцениваем амплитуду броска
{if((BonceMax-BonceMin>BonceAmpMax*_Point)&&(nBonceMax>BonceMin))
{
iBonceStopDown=true;
//break;//Амплитуда броска превышена - прекращаем расчет канала
}}//if(BonceMax-BonceMin>BunceAmpMax)
{if((BonceMax-BonceMin>BonceAmpMax*_Point)&&(nBonceMax<BonceMin))
{
iBonceStopUp=true;
//break;//Амплитуда броска превышена - прекращаем расчет канала
}}//if(BonceMax-BonceMin>BunceAmpMax)
}}//if(nCurBar<BonceDeep)
{if(nCurBar<BonceDeep2)//Если глубина просмотра для определения броска не превышена
//Тут всё переделать именно на односторонний бросок - сейчас блокируются любые колебания превышенные по амплитуде
{
//Запоминаем минимаксы
{if(High[nCurBar]>BonceMax2)
{
BonceMax2=High[nCurBar];
nBonceMax2=nCurBar;
}}//if(High[nCurBar]>BonceMax)
{if(Low[nCurBar]<BonceMin2)
{
BonceMin2=Low[nCurBar];
nBonceMin2=nCurBar;
}}//if(Low[nCurBar]<BonceMin)
//Оцениваем амплитуду броска
{if((BonceMax2-BonceMin2>BonceAmpMax2*_Point)&&(nBonceMax2>BonceMin2))
{
iBonceStopDown=true;
//break;//Амплитуда броска превышена - прекращаем расчет канала
}}//if(BonceMax-BonceMin>BunceAmpMax)
{if((BonceMax2-BonceMin2>BonceAmpMax2*_Point)&&(nBonceMax2<BonceMin2))
{
iBonceStopUp=true;
//break;//Амплитуда броска превышена - прекращаем расчет канала
}}//if(BonceMax-BonceMin>BunceAmpMax)
}}//if(nCurBar<BonceDeep2)
{if(nCurBar<BonceDeep3)//Если глубина просмотра для определения броска не превышена
//Тут всё переделать именно на односторонний бросок - сейчас блокируются любые колебания превышенные по амплитуде
{
//Запоминаем минимаксы
{if(High[nCurBar]>BonceMax3)
{
BonceMax3=High[nCurBar];
nBonceMax3=nCurBar;
}}//if(High[nCurBar]>BonceMax)
if(nCurBar>=ArraySize(Low))Print(" ArraySize=",ArraySize(Low)," nCurBar=",nCurBar);
{if(Low[nCurBar]<BonceMin3)
{
BonceMin3=Low[nCurBar];
nBonceMin3=nCurBar;
}}//if(Low[nCurBar]<BonceMin)
//Оцениваем амплитуду броска
{if((BonceMax3-BonceMin3>BonceAmpMax3*_Point)&&(nBonceMax3>BonceMin3))
{
iBonceStopDown=true;
//break;//Амплитуда броска превышена - прекращаем расчет канала
}}//if(BonceMax-BonceMin>BunceAmpMax)
{if((BonceMax3-BonceMin3>BonceAmpMax*_Point)&&(nBonceMax3<BonceMin3))
{
iBonceStopUp=true;
//break;//Амплитуда броска превышена - прекращаем расчет канала
}}//if(BonceMax-BonceMin>BunceAmpMax)
}}//if(nCurBar<BonceDeep3)
}}//for(int nCurBar=isBars; nCurBar<=nnBars-1; nCurBar++)
return(iBonceStopUp||iBonceStopDown);
}//CheckBounceStop()
//
//======================================================================================================
// CalcSRLevels2() - расчет уровней поддержки - сопротивления
// Вход:
// inBars - глубина просмотра в барах М1 (минутах)
// isBars - стартовая глубина просмотра в барах М1 (минутах)
// inSRLevels - количество анализируемых микроуровней поддержки (сопротивления)
// inLevelsIn - количество микроуровней поддержки (сопротивления) в интервале
// inLevelsStep - шаг по анализируемым микроуровням поддержки (сопротивления)
// inStAnaliseSR - Start Numbers of Analise Levels граница анализа по цене, отступ от цены (в количестве интервалов)
// Выход:
// iChan - признак наличия канала
// iRLevel - граница канала сверху (сопротивление)
// iSLevel - граница канала снизу (поддержка)
// Примечание: реализован примитивный способ расчета пучков плотности ордеров. Надо бы переработать.
// Например строить поперечный разрез с накоплением плотности от центра и определять максимум.
// Или делать два (три) прохода со смешением границ на полинтервала (третьинтервала).
// Открытым остается так же вопрос по какой границе (центру) пучка устанавливать границу канала.
//======================================================================================================
bool CalcSRLevels2( int inBars, //глубина просмотра в барах М1 (минутах)
int isBars, //стартовая глубина просмотра в барах М1 (минутах)
int inSRLevels, //количество анализируемых микроуровней поддержки (сопротивления)
int inLevelsIn, //количество микроуровней поддержки (сопротивления) в интервале
int inLevelsStep, //шаг по анализируемым микроуровням поддержки (сопротивления)
int inStAnaliseSR, //Start Numbers of Analise Levels граница анализа по цене, отступ от цены (в количестве интервалов)
bool &iChan, //признак наличия канала
double &iSLevel, //граница канала сверху (сопротивление)
double &iRLevel){ //граница канала снизу (поддержка)
double
HiBid1,
LoBid1,
HiAsk1,
LoAsk1,
HiBid2,
LoBid2,
HiAsk2,
LoAsk2,
Mid3Bid1,
Mid3Bid2,
Mid3Ask1,
Mid3Ask2;
int
nnBars;//Глубина просмотра в барах М1 (минутах)
double
iSLevelOld=iSLevel,
iRLevelOld=iRLevel;
bool
iFoundS=false,
iFoundR=false;
//----- Ограничение при недостатке баров
//Тут надо бы разобраться поподробнее
{if(Bars(TheSymbol,PERIOD_M1)<50)
{
return(false);
//Print("Bars<50");
}}//if(Bars<50)
{if(Bars(TheSymbol,PERIOD_M1)<inBars+50)
{
nnBars=Bars(TheSymbol,PERIOD_M1)-50;
//Print("Bars<inBars+50");
}else{
nnBars=inBars;
}}//if(Bars<nBars+50)
//Print("nnBars=",nnBars);
//if(nnBars+2>=ArraySize(Low))Print("CalcSRLevels2.0 >> nnBars=",nnBars," ArraySize=",ArraySize(Low));
//----- Уровни сопротивления и поддержки
//Print("inSRLevels=",inSRLevels);
//int MaxnLevels=MathMax(inSRLevels,inLevelsIn)+1;
int MaxnLevels=inSRLevels+inLevelsIn+1;
//Цены микроуровней
ArrayResize(r,MaxnLevels); ArrayFill(r,0,MaxnLevels,Max_Int);
ArrayResize(s,MaxnLevels); ArrayFill(s,0,MaxnLevels,0);
//Время формирования микроуровней
ArrayResize(rt,MaxnLevels); ArrayFill(rt,0,MaxnLevels,0);
ArrayResize(st,MaxnLevels); ArrayFill(st,0,MaxnLevels,0);
//Массив количества уровней сопротивления попавших в n-й интервал
ArrayResize(rP,MaxnLevels); ArrayFill(rP,0,MaxnLevels,0);
//Массив значений цены групп уровней сопротивления
ArrayResize(rL,MaxnLevels); ArrayFill(rL,0,MaxnLevels,0);
//Массив количества уровней поддержки попавших в n-й интервал
ArrayResize(sP,MaxnLevels); ArrayFill(sP,0,MaxnLevels,0);
//Массив значений цены групп уровней поддержки
ArrayResize(sL,MaxnLevels); ArrayFill(sL,0,MaxnLevels,0);
//
double MinLow=High[isBars];
double MaxHi=Low[isBars];
//
double MaxsP=0;
double MaxrP=0;
int nLow=isBars;
int nHi=isBars;
int nrP=isBars;
int nsP=isBars;
double nMaxrP=0;
//iRmax=High[1]*2;
//Отключил обнуление канала
//iSLevel=iRmin;
//iRLevel=iRmax;//Максимально широкий канал
//Параметры ограничения по броскам (вынес в параметры)
//int BonceDeep=120;//Глубина просмотра в барах (минутах)
//double BonceAmpMax=100;//Максимально допустимая амплитуда по броску
iChan=true;//Признак наличия канала устанавливаем
double LowLim;
double HiLim;
int MaxNRP=isBars;
int MaxNSP=isBars;
{for(int nCurBar=isBars; nCurBar<=nnBars-1; nCurBar++)//Перебираем на глубину просмотра в барах М1 (минутах)
{
//Print("nCurBar=",nCurBar);
//Print("Bars=",Bars," nnBars=",nnBars," nCurBar=",nCurBar);
//SR - Уровни
HiBid1=High[nCurBar+1]; //Хай1 определяется по Bid 1бар
LoBid1=Low[nCurBar+1]; //Лоу1 определяется по Bid 1бар
HiAsk1=High[nCurBar+1]+gSpread; //Хай1 определяется по Ask 1бар
LoAsk1=Low[nCurBar+1]+gSpread; //Лоу1 определяется по Ask 1бар
HiBid2=High[nCurBar+2]; //Хай2 определяется по Bid 2бар
LoBid2=Low[nCurBar+2]; //Лоу2 определяется по Bid 2бар
HiAsk2=High[nCurBar+2]+gSpread; //Хай2 определяется по Ask 2бар
LoAsk2=Low[nCurBar+2]+gSpread; //Лоу2 определяется по Ask 2бар
Mid3Bid1=(High[nCurBar+1]+Low[nCurBar+1]+Close[nCurBar+1])/3.0;//Среднее1 по Bid HLC 1бар
Mid3Bid2=(High[nCurBar+2]+Low[nCurBar+2]+Close[nCurBar+2])/3.0;//Среднее2 по Bid HLC 2бар
Mid3Ask1=Mid3Bid1+gSpread; //Среднее1 по Ask HLC 1бар
Mid3Ask2=Mid3Bid2+gSpread; //Среднее2 по Ask HLC 2бар
//Resistense
{if(//Проверка наличия (микро)уровня
(HiAsk1>gAsk) //По любому (хай по биду) больше Ask (или Bid + Spread)//Учитываем, что хай определён по биду и рассчитываем на спред вверх
&&(nHi<=inSRLevels-1) //Количество (микро)уровней сопротивления не превышено
&&(HiAsk1>=MaxHi-dLevel*_Point) //Собственно условие определения (микро)уровня - больше чем чуть менее (-dLevel глубина заглядывания) раннего макса
&&(HiAsk1>=HiAsk2) // (-2)-й бар ниже (-1)-го по хаям по Ask (или Bid + Spread)
//&&(LoAsk2<=LoAsk1) // и по лоу
&&(Mid3Ask1>=Mid3Ask2) // и по среднему
//&&(HiAsk3<=HiAsk2) // (-3)-й бар ниже (-2)-го по хаям
//&&(LoAsk3]<LoAsk2]) // и по лоу
)
{//Запомним найденный (микро)уровень
{if(HiAsk1>MaxHi){MaxHi=HiAsk1;}} //Новый максимум дальше в прошлом для поиска следующих (микро)уровней
r[nHi]=HiAsk1; //Значение (микро)уровня сопротивления
rt[nHi]=nCurBar+1; //Время возникновения (микро)уровня
nHi++; //Увеличение счетчика найденных (микро)уровней
//Тут увеличиваем счетчики всех групп, куда попал уровень
double nAnaliseSR_Point=nAnaliseSR*_Point;
{for(nrP=0;nrP<inSRLevels/inLevelsStep;nrP++)//перебираем группы по номерам
{
//Проверяем попадание уровня в группу
LowLim=gAsk+(inLevelsIn+nrP*inLevelsStep)*_Point;//Нижняя граница n-й группы: (Ask + inLevelsIn*point + n * inLevelsStep*point)
HiLim=LowLim+nAnaliseSR_Point;//Верхняя (дальняя) граница, ширина (nAnaliseSR*point)
rL[nrP]=HiLim; //Верхний (дальний) уровень группы
{if((HiAsk1>=LowLim)&&(HiAsk1<HiLim))
{
rP[nrP]++; //Наращиваем если в группе
{if(rP[nrP]>=MaxrP) //Если превышен или равен прежний макс по количеству уровней в группе
{
{if(MaxrP>inLevelsIn){iRLevel=0.75*HiLim+0.25*LowLim;}}//Если прежний макс больше начального количества уровней, то запомним суперуровень-границу канала по микроуровню
//{if(MaxrP>inLevelsIn){iRLevel=(HiLim+LowLim)/2;}}//Если прежний макс больше начального количества уровней, то запомним суперуровень-границу канала по микроуровню
iFoundR=true;
MaxrP=rP[nrP];//Запомним максимальное количество уровней в группе
MaxNRP=nrP;
}}//if(rP[nrP]>=MaxrP)
}}//if((LowLim<=HiAsk1)&&(HiAsk1<HiLim))
}}//for(nrP=0;nrP<inSRLevels/inLevelsStep;nrP++)
}}//if(
//Support
{if(//Проверка наличия (микро)уровня
(LoBid1<gBid) //Учитываем, что лоу определён по биду //???и рассчитываем за спредом внизу
&&(nLow<=inSRLevels-1) //Количество уровней поддержки не превышено
&&(LoBid1<=MinLow+dLevel*_Point) //dLevel - глубина заглядывания
&&(LoBid1<=LoBid2) //Это впадина (локальный минимум) по Лоу далее подъём (или равно)
//&&(HiBid2>=HiBid1)
&&(Mid3Bid1<=Mid3Bid2) //Это впадина (локальный минимум) по Среднему далее подъём (или равно)
//&&(LoBid3>=LoBid2)
//&&(Hi3Bid>Hi2Bid)
)
{
{if(LoBid1<MinLow){MinLow=LoBid1;}} //Новый минимум дальше в прошлом для поиска следующих (микро)уровней
s[nLow]=LoBid1; //Значение микроуровня
st[nLow]=nCurBar-1; //Время микроуровня
nLow++; //Количество обнаруженных микроуровней
//Тут увеличить счетчики всех групп, куда попал уровень
double nAnaliseSR_Point=nAnaliseSR*_Point;
{for(nsP=0;nsP<inSRLevels/inLevelsStep;nsP++)//перебираем группы по номерам
{
HiLim=gBid-(inLevelsIn-nsP*inLevelsStep)*_Point;//Верхняя граница n-й группы: (Бид - Минимальное число уровней - НомерГруппы*ШагГрупп*point)
LowLim=HiLim-nAnaliseSR_Point;//ширина (nAnaliseSR*point) число пунктов в интервале цены для сборки уровней
sL[nsP]=LowLim; //Нижний уровень группы
{if((LoBid1>LowLim)&&(LoBid1<=HiLim))
{
sP[nsP]++; //Число элементов в группе
{if(sP[nsP]>=MaxsP) //Если превышен или равен прежний макс по количеству уровней в группе
{
{if(MaxsP>inLevelsIn){iSLevel=0.75*LowLim+0.25*HiLim;}}
//{if(MaxsP>inLevelsIn){iSLevel=(HiLim+LowLim)/2;}}
iFoundS=true;
MaxsP=sP[nsP];
MaxNSP=nsP;
}}//if(rP[nrP]>=MaxrP)
}}//if((LowLim<LoCurr)&&(LoCurr<=HiLim))
}}//for(nsP=0;nsP<inSRLevels/inLevelsStep;nsP++)
}}//if(
}}//for(int nCurBar=isBars; nCurBar<=nnBars-1; nCurBar++)
//Print("MaxrP=",MaxrP,"MaxsP=",MaxsP);
//{if((iRLevel>=0.75*iRmax)||(iSLevel<=1.25*iRmin))//Если или не найден один из уровней (то взять предидущий? или бидаск?)
//{
// //iRLevel=iRmax;
// //iSLevel=iRmin;
// iChan=false;
//}}//if((iRLevel==iRmax)||(iSLevel==0.0))
{if((!iFoundS)&&(!iFoundR))//Если не найдены оба из уровней, то взять предидущие и нет канала
{
iSLevel=iSLevelOld;
iRLevel=iRLevelOld;
iChan=false;
}}//if((iRLevel==iRmax)||(iSLevel==0.0))
{if((!iFoundS)&&(iFoundR))//Если не найден один из уровней, то взять предидущий и есть канал
{
iSLevel=iSLevelOld;
}}//if((iRLevel==iRmax)||(iSLevel==0.0))
{if((!iFoundR)&&(iFoundS))//Если не найден один из уровней, то взять предидущий и есть канал
{
iRLevel=iRLevelOld;
}}//if((iRLevel==iRmax)||(iSLevel==0.0))
{if((rt[inLevelsIn+1]==0)||(MaxNRP<inStAnaliseSR))//Если (inLevelsIn+1)-й уровень по R не устанавливался ИЛИ номер группы меньше начальной
{
iRLevel=iRLevelOld;
}}//if(rt[inSRLevels-1]==0)
{if((st[inLevelsIn+1]==0)||(MaxNSP<inStAnaliseSR))//Если (inLevelsIn+1)-й уровень по S не устанавливался ИЛИ номер группы меньше начальной
{
iSLevel=iSLevelOld;
}}//if(rt[inSRLevels-1]==0)
{if(((rt[inLevelsIn+1]==0)||(MaxNRP<inStAnaliseSR))//Если (inLevelsIn+1)-й уровень по R не устанавливался ИЛИ номер группы меньше начальной
&&((st[inLevelsIn+1]==0)||(MaxNSP<inStAnaliseSR)))//Если (inLevelsIn+1)-й уровень по S не устанавливался ИЛИ номер группы меньше начальной
{
iSLevel=iSLevelOld;
iRLevel=iRLevelOld;
iChan=false;
}}//if(rt[inSRLevels-1]==0)
{if((iRLevel-iSLevel<nSpreadToChan*(gAsk-gBid)))//Если ширина канала меньше допустимой по спреду
{
iChan=false;
}}//if(rt[inSRLevels-1]==0)
{if(gBid>iRLevel+_Point)//Если превышение gBid
{
iRLevel=gBid;
}}//if(rt[inSRLevels-1]==0)
{if(gAsk<iSLevel-_Point)//Если превышение gAsk
{
iSLevel=gAsk;
}}//if(rt[inSRLevels-1]==0)
//{if(exMAOn)//Убрано - не работает
//{
// ima_o1=iMA(NULL,0,exMAPeriod,0,MODE_LWMA,PRICE_TYPICAL,0);
// {if((iRLevel<=ima_o1)||(iSLevel>=ima_o1+dSpread))//Если или не найден один из уровней (то взять предидущий? или бидаск?)
// {
// //iRLevel=iRmax;
// //iSLevel=iRmin;
// iChan=false;
// }}//if(rt[inSRLevels-1]==0)
//}}//if(exIMAOn)
//---- Object Move in Chart
{if(ViewSRmLevelsOn)
{
//Resistense
{for(int i=0; i<=inSRLevels-1; i++)//Перебор уровней сопротивления
{
{if(i<=(nHi-1))
{//Установить найденые уровни
//{if(i<=2)
//{
// //Print("Bars=",Bars," rt[i]=",rt[i]);
// ObjectMove("RES-"+IntegerToString(i),0,Time[rt[i]+5],r[i]);
// ObjectMove("RES-"+IntegerToString(i),1,Time[0]+0*Period(),r[i]-0*_Point);//Метим на удаленную точку, чтоб установить наклон
//}else{
// ObjectMove("RES-"+IntegerToString(i),0,Time[rt[i]+3],r[i]);
// ObjectMove("RES-"+IntegerToString(i),1,Time[0]+0*Period(),r[i]-0*_Point);
//}}//if(i==0)
{if(i<=2)
{
//Print("Bars=",Bars," rt[i]=",rt[i]);
ObjectMove(0,"RES-"+IntegerToString(i),0,Time[rt[i]+5],r[i]-gSpread);
ObjectMove(0,"RES-"+IntegerToString(i),1,Time[0]+0*Period(),r[i]-gSpread-0*_Point);//Метим на удаленную точку, чтоб установить наклон
}else{
ObjectMove(0,"RES-"+IntegerToString(i),0,Time[rt[i]+3],r[i]-gSpread);
ObjectMove(0,"RES-"+IntegerToString(i),1,Time[0]+0*Period(),r[i]-gSpread-0*_Point);
}}//if(i==0)
}else{//Не найденые уровни - убрать на край
ObjectMove(0,"RES-"+IntegerToString(i),0,Time[1],Max_Int);
ObjectMove(0,"RES-"+IntegerToString(i),1,Time[0],Max_Int);
}}//if(i<=(nHi-1))
}}//for(i=0; i<=nnSRLevels-1; i++)
//Support - всегда рисуем по Биду
{for(int i=0; i<=inSRLevels-1; i++)//Перебор уровней поддержки
{
{if(i<=(nLow-1))
{//Установить найденые уровни
{if(i<=2)
{
ObjectMove(0,"SUP-"+IntegerToString(i),0,Time[st[i]+5],s[i]);
ObjectMove(0,"SUP-"+IntegerToString(i),1,Time[0]+0*Period(),s[i]+0*_Point);
}else{
ObjectMove(0,"SUP-"+IntegerToString(i),0,Time[st[i]+3],s[i]);
ObjectMove(0,"SUP-"+IntegerToString(i),1,Time[0]+0*Period(),s[i]+0*_Point);
}}//if(i==0)
}else{//Не найденые уровни - убрать на край
ObjectMove(0,"SUP-"+IntegerToString(i),0,Time[1],0);
ObjectMove(0,"SUP-"+IntegerToString(i),1,Time[0],0);
}}//if(i<=(nLow-1))
}}//for(i=0; i<=nnSRLevels-1; i++)
}}//if(ViewSRmLevelsOn)
//iChan=true;//по такому способу расчета канал есть всегда
return(true);
}//CalcSRLevels2()
//
//======================================================================================================
// GridCreate()
// iSizeOfLot - объём ордера, если 0 - авторасчет
//======================================================================================================
int GridCreate( string iSymbol,
bool &iReady,
OP_TYPE iType,
long iMagic,
double iSLevel,
double iRLevel,
double &iSizeOfLot,
double imAlligator,
bool imAlligator2Buy,
bool imAlligator2Sel){
int
m=(int)iMagic-Grid[0].Magic;
bool
GridCreate=false;
bool
iStopUp=false,
iStopDown=false;
double
iSum,iVol;
ulong mDeal=0;
//-----
//Print("GridCreate >> ArraySize=",ArraySize(Low));
//Шаг сетки превышен и нет открытых ордеров и разрешенное время для торговли
{if(
(iReady)
&& (IsTradeTime2())
&& (!IsCloseTime(CloseHour,CloseMinutes,CloseInterval))
&& (!CheckBounceStop(iSymbol,iStopUp,iStopDown))
)
{
iReady=false;
//nAnaliseSR
OrderNumInGrid=0;//Непонятное присваивание ибо nOrdersOpen<1 то есть ноль
//Фактически это единственное условие для выбора направления сделки
//Попробовать добавить расчет уровней - к какому ближе, от того и отражаться
//if(TheSymbol=="GBPJPY")Print("LevelIs=",LevelIs," rLevel=",rLevel," sLevel=",sLevel);
//Print("NewGrid>> iSLevel=",iSLevel," iRLevel=",iRLevel," gAsk=",gAsk," gBid=",gBid);
double idMin0=((-CalcAddCommPrice(TheSymbol,AccSrv))/SymbolTradeTickValue)*_Point+gSpread;
//Print("GridCreate >> idMin0=",idMin0);
int val_index=-1;
{if(Mode1_SRL)//Отбой
{
{if( (iType==OP_SELL)
&&(!iStopDown)//Ограничение по броску в противоположную сторону (если бросок вверх, то StopDown - не продавать)
&&((imAlligator<0.0)||(!exMAOn))
&&((!HedgeFilterOn)||(CalcVolumeHedge(TheSymbol)>=-exHedgeLimit))
)
{
Order_Info=0;//Неопределено
{if(inBounceUp)//k*dR<dS
//{if(nOpenPos1*(iRLevel-gAsk)<(gBid-iSLevel))//k*dR<dS
{
//Print("NewGrid>> nOpenPos1=",nOpenPos1," k*dR<dS=",(nOpenPos1*(iRLevel-gAsk)<(gBid-iSLevel)));
{if(!GridCreate)
{
iSizeOfLot=((iSizeOfLot>0.0)?(iSizeOfLot):(CalcLotSize2(TheSymbol,OP_SELL,exCalcLotMode,OrderNumInGrid,iMagic,1)));
{if(iSizeOfLot>0.0)
{
{if((ShortEnable)
&&( (!exMAOn2) //без аллигатора
|| ((exMAOn2)&&(!Mode2Create)&&(Mode2Cont)) //с аллигатором, но аллигатор отключен для создания, включен для продолжения
|| ((exMAOn2)&&(Mode2Create)&&(imAlligator2Sel))//с аллигатором, включено для создания, сработало для продажи
)
&&((gBid>Grid[m].LastLevelSell-dGridOpenLoss*_Point)//Выше предидущей сетки Sell - сторона убытка???
||(gBid<Grid[m].LastLevelSell-dGridOpenProfit*_Point)//Ниже предидущей сетки Sell - сторона прибыли???
)
//1. Учесть тиковые МА (пока без передачи параметров)
&&(//Тиковый МА
(!TickMA)||//Выключатель фильтра
((true)
&&(ima_fast_main[0]<ima_slow_main[0]-p000*_Point)
&&(ima_fast_main[0]<ima_fast_main[1])
//&&((ima_slow_main[1]-ima_fast_main[1])<(ima_slow_main[0]-ima_fast_main[0]))
)
)
&&(//Прямые
((DirectOn)&&
((true)
//Тиковый длинный МА1
&&(
(!TickDirectMA)||//Выключатель фильтра
(
(ima_fast_dir[0]<ima_slow_dir[0]-p001*_Point)
&&(ima_fast_dir[0]<ima_fast_dir[1])
//&&((ima_fast_o21[1]-ima_slow_main[1])<(ima_fast_o21[0]-ima_slow_main[0]))
))
)//(DirectOn)&&
)//(true)
||
//Отскоки
((ReboundOn)&&
((true)
//Тиковый длинный МА1
&&(
(!TickReboundMA)||
(
(ima_fast_reb[0]>ima_slow_reb[0]+p102*_Point)
&&(ima_fast_reb[0]>ima_fast_reb[1])
//&&((ima_slow_main[1]-ima_fast_o21[1])<(ima_slow_main[0]-ima_fast_o21[0]))
))
)//(ReboundOn)&&
)//(true)
||
(
(!DirectOn)&&(!ReboundOn)//Режимы пробой - отбой отключены оба
)
)
//2. Учесть запрет на близкие открытия при убытке (тоже пока примитивно)
//Если в целом инструмент (или сетка) в убытке, то открываться не ближе mDistOpenOrd в сторону убытка
&&(
(CalcPositionProfitSum1(TheSymbol,OP_SELL,MagicNumber,nGrides)>=0.0)
||
(
(CalcPositionProfitSum1(TheSymbol,OP_SELL,MagicNumber,nGrides)<0.0)
&&(gBid>CalcSymMidPrice(TheSymbol,OP_SELL,MagicNumber,nGrides,iSum,iVol)+mDistOpenGrid*_Point)
//&&(gBid>Grid[m].LastLevelSell+mDistOpenOrd*_Point)
)
)
)
{
AlligatorCreateSell++;
//Print(//"*** Alligator Create Sell=",AlligatorCreateSell,
// " Alligator2Sel=",BoolToString(imAlligator2Sel),
// " exMAOn2=",BoolToString(exMAOn2),
// " (exMAOn2)&&(!Mode2Create)&&(Mode2Cont)=",BoolToString((exMAOn2)&&(!Mode2Create)&&(Mode2Cont)),
// " (exMAOn2)&&(Mode2Create)&&(imAlligator2Sel)=",BoolToString((exMAOn2)&&(Mode2Create)&&(imAlligator2Sel)),
// " ()||()||()=",BoolToString(((!exMAOn2)||((exMAOn2)&&(!Mode2Create)&&(Mode2Cont))||((exMAOn2)&&(Mode2Create)&&(imAlligator2Sel)))),
// ""
// );
//&&( (!exMAOn2) //без аллигатора
// || ((exMAOn2)&&(!Mode2Create)&&(Mode2Cont)) //с аллигатором, но аллигатор отключен для создания, включен для продолжения
// || ((exMAOn2)&&(Mode2Create)&&(imAlligator2Sel))//с аллигатором, включено для создания, сработало для продажи
// )
Order_Info=
fOrderSend(OP_SELL,iSizeOfLot,Slippage,0,0,TradeComment+" #"+string(OrderNumInGrid)+"-"+string(iMagic),iMagic,0,HotPink,mDeal);
{if(Order_Info<=0)
{
Print("NewGrid >> OP_SELL ERROR=",GetLastError()," RetCode=",Order_Info," SizeOfLot=",iSizeOfLot);
return(-2);//Выход - ошибка ордера
}}//if(Order_Info<=0)
{if(Order_Info>0)
{
//Пробуем выбрать сделку
//ResetLastError();
HistorySelect(0,TimeCurrent()+1000);
//Print("ERR 01=",GetLastError());
ulong HistoryOrders=0;
//ResetLastError();
HistoryOrders=HistoryOrdersTotal();//Количество ордеров в истории
//Print("ERR 02=",GetLastError());
ulong HistoryDeals=0;
//ResetLastError();
HistoryDeals=HistoryDealsTotal();//Количество сделок в истории
//Print("ERR 03=",GetLastError());
int HistoryPositions=0;
//ResetLastError();
HistoryPositions=PositionsTotal();//Количество позиций в истории
//Print("ERR 04=",GetLastError());
//ResetLastError();
HistoryDealSelect(mDeal);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 05=",GetLastError());
Grid[m].OpenRLevel=iRLevel;
//ResetLastError();
Grid[m].Ticket=HistoryDealGetInteger(mDeal,DEAL_POSITION_ID);//Получаем POSITION_IDENTIFIER
//Print("ERR 06=",GetLastError());
//ResetLastError();
Grid[m].LastLevelSell=HistoryDealGetDouble(mDeal,DEAL_PRICE);//Цена последней сделки для текущей позиции (сетки)
//Print("ERR 07=",GetLastError());
//Пробуем выбрать позицию
ResetLastError();
{if(PositionSelectByTicket(Grid[m].Ticket))//Выбираем позицию по POSITION_IDENTIFIER
{
GridCreate=true;
CreateSell=true;
//ArraySetAsSeries(High,true);
CopyHigh(TheSymbol,PERIOD_CURRENT,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),RCTuneInterval),High);
val_index=ArrayMaximum(High,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),RCTuneInterval));
{if(val_index!=-1)
{
Grid[m].RuptStopLevel=High[val_index]+idMin0+mdChan*_Point+gSpread;
Grid[m].RuptStopTime=0;
}}//if(val_index!=-1)
Print("NewGrid #",m,">> OP_SELL Placed...",
" POS(ID/TIC/GR)=",PositionGetInteger(POSITION_IDENTIFIER),"/",PositionGetInteger(POSITION_TICKET),"/",Grid[m].Ticket,
" DealTick=",mDeal," LastLevelSell=",Grid[m].LastLevelSell," HistOrders=",HistoryOrders," HistDeals=",HistoryDeals," HistoryPos=",HistoryPositions,
" RuptStopLevel=",Grid[m].RuptStopLevel," RetCode=",Order_Info);
}else{//не выбралось
Print("NewGrid #",iMagic-MagicNumber,">> OP_SELL ERROR=",GetLastError(),
" POS(ID/TIC/GR)=",PositionGetInteger(POSITION_IDENTIFIER),"/",PositionGetInteger(POSITION_TICKET),"/",Grid[m].Ticket,
" DealTick=",mDeal," LastLevelSell=",Grid[m].LastLevelSell," HistOrders=",HistoryOrders," HistDeals=",HistoryDeals," HistoryPos=",HistoryPositions,
" RuptStopLevel=",Grid[m].RuptStopLevel," RetCode=",Order_Info);
return(-9);//Ошибка выбора позиции
}}//if(PositionSelectByTicket(Grid[m].Ticket))
////***** TEST
////Для ордеров
////Ордера номеруются от 1 до HistoryDealsTotal()+1, но рекомендовано перебирать через HistoryOrderGetTicket(i) !!!!
//ResetLastError();
//HistoryOrderSelect(0);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 000(0)=",GetLastError());
//ResetLastError();
//HistoryOrderSelect(HistoryOrders-1);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 099(HistoryOrders-1)=",GetLastError());
//ResetLastError();
//HistoryOrderSelect(HistoryOrders);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 100(HistoryOrders)=",GetLastError());
//ResetLastError();
//HistoryOrderSelect(HistoryOrders+1);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 101(HistoryOrders+1)=",GetLastError());
////Для сделок
////Сделки номеруются от 1 до HistoryDealsTotal()
//ResetLastError();
//HistoryDealSelect(0);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 000(0)=",GetLastError());
//ResetLastError();
//HistoryDealSelect(HistoryDeals-1);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 099(HistoryDeals-1)=",GetLastError());
//ResetLastError();
//HistoryDealSelect(HistoryDeals);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 100(HistoryDeals)=",GetLastError());
////Для позиций
////Позиции перебираются от 0 до (HistoryPositions-1) с получением тикетов через PositionGetTicket(i)
//int HistoryPositions=0;
////ResetLastError();
//HistoryPositions=PositionsTotal();//Количество позиций в истории
//Print("ERR 04=",GetLastError());
//if(HistoryPositions>0)//Есть позиции
//{for(int i=0;i<=HistoryPositions;i++)//Перебираем позиции
//{
// ResetLastError();
// ulong Pos_Tick=PositionGetTicket(i);//Выбираем позицию по номеру в списке
// Print("ERR(200)=",GetLastError()," i=",i," Pos_Tick=",Pos_Tick);
// {if(Pos_Tick<=0){continue;}}//Неудачно - следующий
// //Выбираем позицию по тикету
// ResetLastError();
// {if(!PositionSelectByTicket(Pos_Tick))
// {//Неудачно - следующий
// Print("ERR(201)=",GetLastError()," i=",i," Pos_Tick=",Pos_Tick);
// continue;
// }else{
// Print("ERR(202)=",GetLastError()," i=",i," Pos_Tick=",Pos_Tick);
// }}//if(!PositionSelectByTicket(Pos_Tick))
//}}//for(int i=PositionsTotal();i>=0;i--)
}}//if(Order_Info>0)
}}//if(ShortEnable)
}}//if(Size_Of_Lot>0.0)
}}//if(GridNotCreate)
}else{
//Print(nOpenPos1,"Error: ошибка смещения в канале");
return(-3);//Выход - ошибка смещения в канале
}}//if(nOpenPos1*(iRLevel-gAsk)<(gBid-iSLevel))
}else{
//{if((iClose2<iClose1)&&(iClose1<iClose0)&&(true))
//{if((iClose2<iClose1)&&(true))
{if( (iType==OP_BUY)
&& (!iStopUp)//Ограничение по броску в противоположную сторону (если бросок вниз, то StopUp - не покупать)
&& ((imAlligator>0.0)||(!exMAOn))
&& ((!HedgeFilterOn)||(CalcVolumeHedge(TheSymbol)<=exHedgeLimit))
)
{
Order_Info=0;//Неопределено
{if(inBounceDn)
{
//Print("NewGrid>> nOpenPos1=",nOpenPos1," k*dS<dR=",(nOpenPos1*(gBid-iSLevel)<(iRLevel-gAsk)));
{if(!GridCreate)
{
iSizeOfLot=((iSizeOfLot>0.0)?(iSizeOfLot):(CalcLotSize2(TheSymbol,OP_BUY,exCalcLotMode,OrderNumInGrid,iMagic,1)));
{if(iSizeOfLot>0.0)
{
{if((LongEnable)
&&( (!exMAOn2) //без аллигатора
|| ((exMAOn2)&&(!Mode2Create)&&(Mode2Cont)) //с аллигатором, но аллигатор отключен для создания, включен для продолжения
|| ((exMAOn2)&&(Mode2Create)&&(imAlligator2Buy))//с аллигатором, включено для создания, сработало для покупки
)
&&((gAsk<Grid[m].LastLevelBuy+dGridOpenLoss*_Point)//Ниже последнего открытого ордера предидущей сетки Buy - сторона убытка???
||(gAsk>Grid[m].LastLevelBuy+dGridOpenProfit*_Point)//Выше последнего открытого ордера предидущей сетки Buy - сторона прибыли???
)
//1. Учесть тиковые МА (пока без передачи параметров)
&&(//Тиковый МА
(!TickMA)||//Для режима МА
((true)
&&((ima_fast_main_a[0]>ima_slow_main_a[0]+p000*_Point)
&&(ima_fast_main_a[0]>ima_fast_main_a[1]))
//&&((ima_fast_main[1]-ima_slow_main[1])<(ima_fast_main[0]-ima_slow_main[0]))
)
)
&&(//Прямые и отскоки
//Прямые
((DirectOn)&&
((true)
//Тиковый длинный МА1
&&(
(!TickDirectMA)||
((true)
&&(ima_fast_dir_a[0]>ima_slow_dir_a[0]+p001*_Point)
&&(ima_fast_dir_a[0]>ima_fast_dir_a[1])
//&&((ima_fast_o21[1]-ima_slow_main[1])<(ima_fast_o21[0]-ima_slow_main[0]))
))
)//(DirectOn)&&
)//(true)
||
//Отскоки
((ReboundOn)&&
((true)
//Тиковый длинный МА1
&&(
(!TickReboundMA)||
(
(ima_fast_reb_a[0]<ima_slow_reb_a[0]-p102*_Point)
&&(ima_fast_reb_a[0]<ima_fast_reb_a[1])
//&&((ima_fast_o21[1]-ima_slow_main[1])<(ima_fast_o21[0]-ima_slow_main[0]))
))
)//(ReboundOn)&&
)//(true)
||
(
(!DirectOn)&&(!ReboundOn)//Режимы пробой - отбой отключены оба
)
)//Прямые и отскоки
//2. Учесть запрет на близкие открытия при убытке (тоже пока примитивно)
//Если в целом инструмент (или сетка) в убытке, то открываться не ближе mDistOpenOrd в сторону убытка
&&(
(CalcPositionProfitSum1(TheSymbol,OP_BUY,MagicNumber,nGrides)>=0.0)
||
(
(CalcPositionProfitSum1(TheSymbol,OP_BUY,MagicNumber,nGrides)<0.0)
&&(gAsk<CalcSymMidPrice(TheSymbol,OP_BUY,MagicNumber,nGrides,iSum,iVol)-mDistOpenGrid*_Point)//Не влияет!!!
//&&(gAsk<Grid[m].LastLevelBuy-mDistOpenOrd*_Point)
)
)
)//(LongEnable)&&((imAlligator2>=0)||(!Mode2))
{
AlligatorCreateBuy++;
//Print("****************** Alligator Create Buy>>",AlligatorCreateBuy);
Order_Info=
fOrderSend(OP_BUY,iSizeOfLot,Slippage,0,0,TradeComment+" #"+string(OrderNumInGrid)+"-"+string(iMagic),iMagic,0,Lime,mDeal);
{if(Order_Info<=0)
{
Print("NewGrid >> OP_BUY ERROR=",GetLastError()," RetCode=",Order_Info," SizeOfLot=",iSizeOfLot);
return(-2);//Выход - ошибка ордера
}}//if(Order_Info<=0)
{if(Order_Info>0)
{
//Пробуем выбрать сделку
//ResetLastError();
HistorySelect(0,TimeCurrent()+1000);
//Print("ERR 01=",GetLastError());
ulong HistoryOrders=0;
//ResetLastError();
HistoryOrders=HistoryOrdersTotal();//Количество ордеров в истории
//Print("ERR 02=",GetLastError());
ulong HistoryDeals=0;
//ResetLastError();
HistoryDeals=HistoryDealsTotal();//Количество сделок в истории
//Print("ERR 03=",GetLastError());
int HistoryPositions=0;
//ResetLastError();
HistoryPositions=PositionsTotal();//Количество позиций в истории
//Print("ERR 04=",GetLastError());
//ResetLastError();
HistoryDealSelect(mDeal);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 05=",GetLastError());
Grid[m].OpenSLevel=iSLevel;
//ResetLastError();
Grid[m].Ticket=HistoryDealGetInteger(mDeal,DEAL_POSITION_ID);//Получаем POSITION_IDENTIFIER
//Print("ERR 06=",GetLastError());
//ResetLastError();
Grid[m].LastLevelBuy=HistoryDealGetDouble(mDeal,DEAL_PRICE);//Цена последней сделки для текущей позиции (сетки)
//Print("ERR 07=",GetLastError());
//Пробуем выбрать позицию
ResetLastError();
{if(PositionSelectByTicket(Grid[m].Ticket))//Выбираем позицию по POSITION_IDENTIFIER
{
GridCreate=true;
CreateBuy=true;
//ArraySetAsSeries(Low,true);
CopyLow(TheSymbol,PERIOD_CURRENT,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),RCTuneInterval),Low);
val_index=ArrayMinimum(Low,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),RCTuneInterval));
{if(val_index!=-1)
{
Grid[m].RuptStopLevel=Low[val_index]-idMin0-mdChan*_Point;
Grid[m].RuptStopTime=0;
}}//if(val_index!=-1)
Print("NewGrid #",m,">> OP_BUY Placed...",
" POS(ID/TIC/GR)=",PositionGetInteger(POSITION_IDENTIFIER),"/",PositionGetInteger(POSITION_TICKET),"/",Grid[m].Ticket,
" DealTick=",mDeal," LastLevelBuy=",Grid[m].LastLevelBuy," HistOrders=",HistoryOrders," HistDeals=",HistoryDeals," HistoryPos=",HistoryPositions,
" RuptStopLevel=",Grid[m].RuptStopLevel," RetCode=",Order_Info);
}else{//не выбралось
Print("NewGrid #",iMagic-MagicNumber,">> OP_BUY ERROR=",GetLastError(),
" POS(ID/TIC/GR)=",PositionGetInteger(POSITION_IDENTIFIER),"/",PositionGetInteger(POSITION_TICKET),"/",Grid[m].Ticket,
" DealTick=",mDeal," LastLevelBuy=",Grid[m].LastLevelBuy," HistOrders=",HistoryOrders," HistDeals=",HistoryDeals," HistoryPos=",HistoryPositions,
" RetCode=",Order_Info);
return(-9);//Ошибка выбора позиции
}}//if(PositionSelectByTicket(Grid[m].Ticket))
////***** TEST
////Для ордеров
////Ордера номеруются от 1 до HistoryDealsTotal()+1, но рекомендовано перебирать через HistoryOrderGetTicket(i) !!!!
//ResetLastError();
//HistoryOrderSelect(0);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 000(0)=",GetLastError());
//ResetLastError();
//HistoryOrderSelect(HistoryOrders-1);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 099(HistoryOrders-1)=",GetLastError());
//ResetLastError();
//HistoryOrderSelect(HistoryOrders);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 100(HistoryOrders)=",GetLastError());
//ResetLastError();
//HistoryOrderSelect(HistoryOrders+1);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 101(HistoryOrders+1)=",GetLastError());
////Для сделок
////Сделки номеруются от 1 до HistoryDealsTotal()
//ResetLastError();
//HistoryDealSelect(0);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 000(0)=",GetLastError());
//ResetLastError();
//HistoryDealSelect(HistoryDeals-1);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 099(HistoryDeals-1)=",GetLastError());
//ResetLastError();
//HistoryDealSelect(HistoryDeals);//Результат не проверяем - вроде всегда срабатывает
//Print("ERR 100(HistoryDeals)=",GetLastError());
////Для позиций
////Позиции перебираются от 0 до (HistoryPositions-1) с получением тикетов через PositionGetTicket(i)
//if(HistoryPositions>0)//Есть позиции
//{for(int i=0;i<=HistoryPositions;i++)//Перебираем позиции
//{
// ResetLastError();
// ulong Pos_Tick=PositionGetTicket(i);//Выбираем позицию по номеру в списке
// Print("ERR(200)=",GetLastError()," i=",i," Pos_Tick=",Pos_Tick);
// {if(Pos_Tick<=0){continue;}}//Неудачно - следующий
// //Выбираем позицию по тикету
// ResetLastError();
// {if(!PositionSelectByTicket(Pos_Tick))
// {//Неудачно - следующий
// Print("ERR(201)=",GetLastError()," i=",i," Pos_Tick=",Pos_Tick);
// continue;
// }else{
// Print("ERR(202)=",GetLastError()," i=",i," Pos_Tick=",Pos_Tick);
// }}//if(!PositionSelectByTicket(Pos_Tick))
//}}//for(int i=PositionsTotal();i>=0;i--)
}}//if(Order_Info>0)
}}//if(LongEnable)
}}//if(Size_Of_Lot>0.0)
}}//if(GridNotCreate)
}else{
//Print(nOpenPos1,"Error: ошибка смещения в канале");
return(-3);//Выход - ошибка смещения в канале
}}//if(nOpenPos1*(gBid-iSLevel)<(iRLevel-gAsk))
}}//if(iType==OP_BUY)
}}//if(iType==OP_SELL)
}}//if((Mode1_SRL)&&(true))
//{if(Mode2_SRL)//Пробой - предусмотреть выход за последний известный канал k*dS>(R-S)
//{
// {if(((nOpenPos2*(gBid-iSLevel)<(iRLevel-gAsk)))&&(iType==OP_SELL))//k*dS<dR
// {
// {if(!GridCreate)
// {
// iSizeOfLot=CalcLotSize(OP_SELL,exCalcLotMode,OrderNumInGrid,iMagic);
// {if(iSizeOfLot>0.0)
// {
// {if(ShortEnable)
// {
// Order_Info=
// fOrderSend(OP_SELL,iSizeOfLot,Slippage,0,0,TradeComment+" #"+string(OrderNumInGrid)+"-"+string(iMagic),iMagic,0,HotPink);
// }}//if(ShortEnable)
// {if(Order_Info<0)
// {
// Print(iSizeOfLot,"Error: ",GetLastError());
// return(-2);//Выход - ошибка ордера
// }}//if(Order_Info<0)
// ////dLastOpenPriceBuy=CalcLastOpenPrice(OP_BUY,iMagic);
// GridCreate=true;
// }}//if(Size_Of_Lot>0.0)
// }}//if(GridNotCreate)
// }else{
// //{if((iClose2<iClose1)&&(iClose1<iClose0)&&(true))
// //{if((iClose2<iClose1)&&(true))
// {if(((nOpenPos2*(iRLevel-gAsk)<(gBid-iSLevel)))&&(iType==OP_BUY))
// {
// {if(!GridCreate)
// {
// iSizeOfLot=CalcLotSize(OP_BUY,exCalcLotMode,OrderNumInGrid,iMagic);
// {if(iSizeOfLot>0.0)
// {
// {if(LongEnable)
// {
// Order_Info=
// fOrderSend(OP_BUY,iSizeOfLot,Slippage,0,0,TradeComment+" #"+string(OrderNumInGrid)+"-"+string(iMagic),iMagic,0,Lime);
// }}//if(LongEnable)
// {if(Order_Info<0)
// {
// Print(iSizeOfLot,"Error: ",GetLastError());
// return(-2);//Выход - ошибка ордера
// }}//if(Order_Info<0)
// ////dLastOpenPriceSell=CalcLastOpenPriceA1(OP_BUY,iMagic);
// GridCreate=true;
// }}//if(Size_Of_Lot>0.0)
// }}//if(GridNotCreate)
// }}//if((iClose1==iClose0)&&(iClose2<iClose1))
// }}//if((nOpenPos1*(rLevel-gAsk)<nOpenPos2*(gBid-sLevel)))
//}}//if((Mode2_SRL)&&(true))
{if(GridCreate)
{
//Grid[m].StopTime=datetime(TimeCurrent()-OffSetTimeBase+(int)60*(60*PosLifeTimeHours));//Librecoin добавил datatime
Grid[m].StopTime=datetime(TimeCurrent()+3600*PosLifeTimeHours+60*PosLifeTimeMinutes);//Librecoin добавил datatime
return(1);//Выход - новая сетка создана
}}//if(Order_Info>0)
}}//if((iReady)&&(IsTradeTime2())&&(!IsCloseTime(CloseHour,CloseMinutes,CloseInterval)))
iReady=false;
return(0);//Выход - нет ошибки результат не определен
}//GridCreate()
//
//======================================================================================================
// GridContinue()
//======================================================================================================
int GridContinue( string iSymbol,
bool iReady,
int iType,
int iMagic,
double iSLevel,
double iRLevel,
double &iVirtualSL,
double &iSizeOfLot,
int iOrderNumInGrid,
double imAlligator,
bool imAlligator2Buy,
bool imAlligator2Sel){
int
m=iMagic-Grid[0].Magic;
bool
GridCreate=false;
bool
iStopUp=false,
iStopDown=false;
double
iSum,iVol;
ulong mDeal=0;
//-----
//Print("GridCreate >> ArraySize=",ArraySize(Low));
{if(
(iReady)
&& (IsTradeTime2())
&& (!IsCloseTime(CloseHour,CloseMinutes,CloseInterval))
&& (!CheckBounceStop(iSymbol,iStopUp,iStopDown))
)
{
iReady=false;
double idMin0=((-CalcAddCommPrice(TheSymbol,AccSrv))/SymbolTradeTickValue)*_Point+gSpread;
int val_index=-1;
{if((iType==OP_SELL)//Найден SELL
&&(!iStopDown)//Ограничение по броску в противоположную сторону (если бросок вверх, то StopDown - не продавать)
&&((!HedgeFilterOn)||(CalcVolumeHedge(iSymbol)>=-exHedgeLimit))
//1. Учесть тиковые МА (пока без передачи параметров)
&&(//Тиковый МА
(!TickMA)||//Выключатель фильтра
((true)
&&(ima_fast_main[0]<ima_slow_main[0]-p000*_Point)
&&(ima_fast_main[0]<ima_fast_main[1])
//&&((ima_slow_main[1]-ima_fast_main[1])<(ima_slow_main[0]-ima_fast_main[0]))
)
)
&&(//Прямые
((DirectOn)&&
((true)
//Тиковый длинный МА1
&&(
(!TickDirectMA)||//Выключатель фильтра
(
(ima_fast_dir[0]<ima_slow_dir[0]-p001*_Point)
&&(ima_fast_dir[0]<ima_fast_dir[1])
//&&((ima_fast_o21[1]-ima_slow_main[1])<(ima_fast_o21[0]-ima_slow_main[0]))
))
)//(DirectOn)&&
)//(true)
||
//Отскоки
((ReboundOn)&&
((true)
//Тиковый длинный МА1
&&(
(!TickReboundMA)||
(
(ima_fast_reb[0]>ima_slow_reb[0]+p102*_Point)
&&(ima_fast_reb[0]>ima_fast_reb[1])
//&&((ima_slow_main[1]-ima_fast_o21[1])<(ima_slow_main[0]-ima_fast_o21[0]))
))
)//(ReboundOn)&&
)//(true)
||
(
(!DirectOn)&&(!ReboundOn)//Режимы пробой - отбой отключены оба
)
)
//2. Учесть запрет на близкие открытия при убытке (тоже пока примитивно)
//Если в целом инструмент (или сетка) в убытке, то открываться не ближе mDistOpenOrd в сторону убытка
&&(
(CalcPositionProfitSum1(iSymbol,OP_SELL,iMagic,1)>0.0)//Если в прибыли, то разрешить открытие
||
(
(CalcPositionProfitSum1(iSymbol,OP_SELL,iMagic,1)<=0.0)//Если в убытке
&&(gBid>CalcSymMidPrice(iSymbol,OP_SELL,iMagic,1,iSum,iVol)+mDistOpenOrd*_Point)//Бид больше средней цены на отступ!!!
&&
(
(StLotsMode==0)
||(gBid>Grid[m].LastLevelSell+mDistOpenOrd*_Point)//Бид больше последней цены на отступ!!!
)
)
)
)
{
{if(ShortEnable)//Продажи разрешены
{
{if(inBounceUp)//Цена у верхней границы канала
{
{if((imAlligator<0.0)||(!exMAOn))//Цена прекратила рост у верхнего края канала
{
{if( (!exMAOn2) //без аллигатора
|| ((exMAOn2)&&(!Mode2Cont)&&(Mode2Create)) //с аллигатором, продолжение выключено, создание включено
|| ((exMAOn2)&&(Mode2Cont)&&(imAlligator2Sel)) //с аллигатором, продолжение включено, сработало на продажу
)
{//Общий тренд - продажи для продолжения
AlligatorContBuy++;
//Print("****************** Alligator Count Buy>>",AlligatorCountBuy);
iOrderNumInGrid=CalcOrdersN(iSymbol,OP_SELL,iMagic,1);
{if(OneOrderMode) //Режим одиночного ордера
{//Режим одиночных ордеров - расчет размера лота
iSizeOfLot=2*CalcPosLastLotSize(iSymbol,OP_SELL,iMagic)+CalcLotSize2(iSymbol,OP_ALL,exCalcLotMode,iOrderNumInGrid,iMagic,1);//Уже нормализовано в процедуре
//iSizeOfLot=LotsMult*CalcPosLastLotSize(OP_SELL,iMagic); //и нарастили лот
if(CloseEnable)
fCloseBuySell(iSymbol,false,true,iMagic,iVirtualSL); //Закрыли продажу
}else{//Режим сетки ордеров - расчет размера лота
iSizeOfLot=CalcLotSize2(iSymbol,OP_ALL,exCalcLotMode,iOrderNumInGrid,iMagic,1);//Уже нормализовано в процедуре
//iSizeOfLot=CalcLotSize(OP_SELL,exCalcLotMode,iOrderNumInGrid,iMagic);//Уже нормализовано в процедуре
}}//if(OneOrderMode)
{if(iSizeOfLot>0.0)
{
//Print("CalcSymMidPrice(OP_SELL)==",CalcSymMidPrice(OP_SELL,iMagic,1,iSum,iVol));
iSizeOfLot=NormalizeDouble(MathMin(iSizeOfLot,SymbolInfoDouble(iSymbol,SYMBOL_VOLUME_MAX)),LotStepDigit);
Order_Info=0;//Неопределено
Order_Info=
fOrderSend(OP_SELL,iSizeOfLot,Slippage,0,0,TradeComment+" #"+string(iOrderNumInGrid)+"-"+string(iMagic),iMagic,0,HotPink,mDeal);
{if(Order_Info<=0)//Превышено количество (-4) или ошибка ордера (-1)
{
//{if(Order_Info==-1)//ошибка ордера (-1)
//{
// Print("Error: ",GetLastError());
// return(Order_Info);
//}else{
return(-1);
//}}//if(Order_Info==-1)//ошибка ордера (-1)
}else{
{if(Order_Info>0)
{
//Пробуем выбрать сделку
//ResetLastError();
HistorySelect(0,TimeCurrent());
//Print("ERR 01=",GetLastError());
ulong HistoryOrders=0;
//ResetLastError();
HistoryOrders=HistoryOrdersTotal();//Количество ордеров в истории
//Print("ERR 02=",GetLastError());
ulong HistoryDeals=0;
//ResetLastError();
HistoryDeals=HistoryDealsTotal();//Количество сделок в истории
//Print("ERR 03=",GetLastError());
int HistoryPositions=0;
//ResetLastError();
HistoryPositions=PositionsTotal();//Количество позиций в истории
//Print("ERR 04=",GetLastError());
//ResetLastError();
HistoryDealSelect(mDeal);//Результат не проверяем - вроде всегда срабатывает
//Grid[m].Ticket=HistoryDealGetInteger(mDeal,DEAL_POSITION_ID);//Уже храним в массиве - не нужно получать заново
//ResetLastError();
Grid[m].LastLevelSell=HistoryDealGetDouble(mDeal,DEAL_PRICE);//Цена последней сделки для текущей позиции (сетки) - собственно ради этого и выбирали сделку
//Пробуем выбрать позицию
ResetLastError();
{if(PositionSelectByTicket(Grid[m].Ticket))//Выбираем позицию по POSITION_IDENTIFIER (он был получен при первом ордере/сделке позиции)
{
GridCreate=true;
CreateSell=true;
//ArraySetAsSeries(High,true);
CopyHigh(iSymbol,PERIOD_CURRENT,0,MathMin(Bars(iSymbol,PERIOD_CURRENT),RCTuneInterval),High);
val_index=ArrayMaximum(High,0,MathMin(Bars(iSymbol,PERIOD_CURRENT),RCTuneInterval));
{if(val_index!=-1)
{
Grid[m].RuptStopLevel=High[val_index]+idMin0+mdChan*_Point+gSpread;
Grid[m].RuptStopTime=0;
}}//if(val_index!=-1)
Print("GridContinue #",iMagic-MagicNumber,">> OP_SELL Placed...",
" POS(ID/TI/GR)=",PositionGetInteger(POSITION_IDENTIFIER),"/",PositionGetInteger(POSITION_TICKET),"/",Grid[m].Ticket,
" DealTick=",mDeal," LastLevelSell=",Grid[m].LastLevelSell," HistOrders=",HistoryOrders," HistDeals=",HistoryDeals," HistoryPos=",HistoryPositions,
" RuptStopLevel=",Grid[m].RuptStopLevel," RetCode=",Order_Info);
}else{//не выбралось
Print("GridContinue #",iMagic-MagicNumber,">> OP_SELL ERROR=",GetLastError(),
" POS(ID/TI/GR)=",PositionGetInteger(POSITION_IDENTIFIER),"/",PositionGetInteger(POSITION_TICKET),"/",Grid[m].Ticket,
" DealTick=",mDeal," LastLevelSell=",Grid[m].LastLevelSell," HistOrders=",HistoryOrders," HistDeals=",HistoryDeals," HistoryPos=",HistoryPositions,
" RetCode=",Order_Info);
return(-9);//Ошибка выбора позиции
}}//if(PositionSelectByTicket(Grid[m].Ticket))
}else{
return(0);
}}//if(Order_Info>0)
}}//if(Order_Info<0)
}else{
return(-4);//Выход - ошибка размера лота
}}//if(Size_Of_Lot>0.0)
}else{
return(-8);//Выход - ошибка imAlligator2
}}//if((imAlligator2<0)||(!Mode2))
}else{
return(-7);//Выход - ошибка imAlligator
}}//if((imAlligator<0.0)||(!exMAOn))
}else{
//Print(nOpenPos1,"Error: ошибка смещения в канале");
return(-3);//Выход - ошибка смещения в канале, цена не в интервале отскока
}}//if(inBounceUp)
}else{
return(-9);//Выход - ошибка продажи запрещены
}}//if(ShortEnable)
}}//else{
//if(iType==OP_BUY){Print("0. iType==OP_BUY>>>");}
{if((iType==OP_BUY)//Найден BUY
&&(!iStopUp)//Ограничение по броску в противоположную сторону (если бросок вниз, то StopUp - не покупать)
&&((!HedgeFilterOn)||(CalcVolumeHedge(iSymbol)<=exHedgeLimit))
//1. Учесть тиковые МА (пока без передачи параметров)
&&(//Тиковый МА
(!TickMA)||//Для режима МА
((true)
&&((ima_fast_main_a[0]>ima_slow_main_a[0]+p000*_Point)
&&(ima_fast_main_a[0]>ima_fast_main_a[1]))
//&&((ima_fast_main[1]-ima_slow_main[1])<(ima_fast_main[0]-ima_slow_main[0]))
))
&&(//Прямые и отскоки
//Прямые
((DirectOn)&&
((true)
//Тиковый длинный МА1
&&(
(!TickDirectMA)||
((true)
&&(ima_fast_dir_a[0]>ima_slow_dir_a[0]+p001*_Point)
&&(ima_fast_dir_a[0]>ima_fast_dir_a[1])
//&&((ima_fast_o21[1]-ima_slow_main[1])<(ima_fast_o21[0]-ima_slow_main[0]))
))
)//(DirectOn)&&
)//(true)
||
//Отскоки
((ReboundOn)&&
((true)
//Тиковый длинный МА1
&&(
(!TickReboundMA)||
(
(ima_fast_reb_a[0]<ima_slow_reb_a[0]-p102*_Point)
&&(ima_fast_reb_a[0]<ima_fast_reb_a[1])
//&&((ima_fast_o21[1]-ima_slow_main[1])<(ima_fast_o21[0]-ima_slow_main[0]))
))
)//(ReboundOn)&&
)//(true)
||
(
(!DirectOn)&&(!ReboundOn)//Режимы пробой - отбой отключены оба
)
)//Прямые и отскоки
//2. Учесть запрет на близкие открытия при убытке (тоже пока примитивно)
//Если в целом инструмент (или сетка) в убытке, то открываться не ближе mDistOpenOrd в сторону убытка
&&(
(CalcPositionProfitSum1(iSymbol,OP_BUY,iMagic,1)>0.0)
||
(
(CalcPositionProfitSum1(iSymbol,OP_BUY,iMagic,1)<=0.0)
&&(gAsk<CalcSymMidPrice(iSymbol,OP_BUY,iMagic,1,iSum,iVol)-mDistOpenOrd*_Point)
&&
(
(StLotsMode==0)//0/1 - MidPrice(2.08)/LastPrice(2.15)
||(gAsk<Grid[m].LastLevelBuy-mDistOpenOrd*_Point)
)
)
)
)
{
//if(iType==OP_BUY){Print("1. iType==OP_BUY>>>"," gAsk=",gAsk," Grid[m].LastLevelBuy=",Grid[m].LastLevelBuy);}
{if(LongEnable)//Покупки разрешены
{
{if(inBounceDn)//Цена у нижней границы канала
{
{if((imAlligator>0.0)||(!exMAOn))//Цена прекратила рост у края канала
{
{if( (!exMAOn2) //без аллигатора
|| ((exMAOn2)&&(!Mode2Cont)&&(Mode2Create)) //с аллигатором, продолжение отключено, создание включено
|| ((exMAOn2)&&(Mode2Cont)&&(imAlligator2Buy)) //с аллигатором, продолжение включено, сработало на покупку
)
{//Общий тренд - покупать для продолжения
AlligatorContSell++;
//Print("****************** Alligator Count Sell>>",AlligatorCountSell);
iOrderNumInGrid=CalcOrdersN(iSymbol,OP_BUY,iMagic,1);
{if(OneOrderMode)
{
iSizeOfLot=2*CalcPosLastLotSize(iSymbol,OP_BUY,iMagic)+CalcLotSize2(iSymbol,OP_ALL,exCalcLotMode,iOrderNumInGrid,iMagic,1);//Уже нормализовано в процедуре
//iSizeOfLot=LotsMult*CalcPosLastLotSize(OP_BUY,iMagic);
if(CloseEnable)
fCloseBuySell(iSymbol,true,false,iMagic,iVirtualSL);
}else{
iSizeOfLot=CalcLotSize2(iSymbol,OP_ALL,exCalcLotMode,iOrderNumInGrid,iMagic,1);//Уже нормализовано в процедуре
//iSizeOfLot=CalcLotSize(OP_BUY,exCalcLotMode,iOrderNumInGrid,iMagic);//Уже нормализовано в процедуре
}}//if(OneOrderMode)
{if(iSizeOfLot>0.0)
{
//Print("CalcSymMidPrice(OP_BUY)==",CalcSymMidPrice(TheSymbol,OP_BUY,iMagic,1,iSum,iVol));
iSizeOfLot=NormalizeDouble(MathMin(iSizeOfLot,SymbolInfoDouble(iSymbol,SYMBOL_VOLUME_MAX)),LotStepDigit);
Order_Info=0;//Неопределено
Order_Info=
fOrderSend(OP_BUY,iSizeOfLot,Slippage,0,0,TradeComment+" #"+string(iOrderNumInGrid)+"-"+string(iMagic),iMagic,0,Lime,mDeal);
{if(Order_Info<=0)
{
//{if(Order_Info==-1)//ошибка ордера (-1)
//{
// Print("Error: ",GetLastError());
// return(Order_Info);
//}else{
return(-1);
//}}//
}else{
{if(Order_Info>0)
{
//Пробуем выбрать сделку
//ResetLastError();
HistorySelect(0,TimeCurrent());
//Print("ERR 01=",GetLastError());
ulong HistoryOrders=0;
//ResetLastError();
HistoryOrders=HistoryOrdersTotal();//Количество ордеров в истории
//Print("ERR 02=",GetLastError());
ulong HistoryDeals=0;
//ResetLastError();
HistoryDeals=HistoryDealsTotal();//Количество сделок в истории
//Print("ERR 03=",GetLastError());
int HistoryPositions=0;
//ResetLastError();
HistoryPositions=PositionsTotal();//Количество позиций в истории
//Print("ERR 04=",GetLastError());
//ResetLastError();
HistoryDealSelect(mDeal);//Результат не проверяем - вроде всегда срабатывает
//Grid[m].Ticket=HistoryDealGetInteger(mDeal,DEAL_POSITION_ID);//Уже храним в массиве - не нужно получать заново
//ResetLastError();
Grid[m].LastLevelBuy=HistoryDealGetDouble(mDeal,DEAL_PRICE);//Цена последней сделки для текущей позиции (сетки) - собственно ради этого и выбирали сделку
//Пробуем выбрать позицию
ResetLastError();
{if(PositionSelectByTicket(Grid[m].Ticket))//Выбираем позицию по POSITION_IDENTIFIER (он был получен при первом ордере/сделке позиции)
{
GridCreate=true;
CreateBuy=true;
//ArraySetAsSeries(Low,true);
CopyLow(iSymbol,PERIOD_CURRENT,0,MathMin(Bars(iSymbol,PERIOD_CURRENT),RCTuneInterval),Low);
val_index=ArrayMinimum(Low,0,MathMin(Bars(iSymbol,PERIOD_CURRENT),RCTuneInterval));
{if(val_index!=-1)
{
Grid[m].RuptStopLevel=Low[val_index]-idMin0-mdChan*_Point;
Grid[m].RuptStopTime=0;
}}//if(val_index!=-1)
Print("GridContinue #",iMagic-MagicNumber,">> OP_BUY Placed...",
" POS(ID/TI/GR)=",PositionGetInteger(POSITION_IDENTIFIER),"/",PositionGetInteger(POSITION_TICKET),"/",Grid[m].Ticket,
" DealTick=",mDeal," LastLevelBuy=",Grid[m].LastLevelBuy," HistOrders=",HistoryOrders," HistDeals=",HistoryDeals," HistoryPos=",HistoryPositions,
" RuptStopLevel=",Grid[m].RuptStopLevel," RetCode=",Order_Info);
}else{//не выбралось
Print("GridContinue #",iMagic-MagicNumber,">> OP_BUY ERROR=",GetLastError(),
" POS(ID/TI/GR)=",PositionGetInteger(POSITION_IDENTIFIER),"/",PositionGetInteger(POSITION_TICKET),"/",Grid[m].Ticket,
" DealTick=",mDeal," LastLevelBuy=",Grid[m].LastLevelBuy," HistOrders=",HistoryOrders," HistDeals=",HistoryDeals," HistoryPos=",HistoryPositions,
" RetCode=",Order_Info);
return(-9);//Ошибка выбора позиции
}}//if(PositionSelectByTicket(Grid[m].Ticket))
}else{
return(0);
}}//
}}//if(Order_Info<0)
}else{
return(-4);//Выход - ошибка размера лота
}}//if(Size_Of_Lot>0.0)
}else{
return(-8);//Выход - ошибка imAlligator2
}}//if((imAlligator2>0)||(!Mode2))
}else{
return(-7);//Выход - ошибка imAlligator
}}//if((imAlligator>0.0)||(!exMAOn))
}else{
//Print(nOpenPos1,"Error: ошибка смещения в канале");
return(-3);//Выход - ошибка смещения в канале
}}//if(inBounceDn)
}else{
return(-6);//Выход - ошибка покупка запрещена
}}//if(LongEnable)
}}//if(PositionIsBuy)
}}//if((iReady)&&(!IsCloseTime(CloseHour,CloseMinutes,CloseInterval)))
{if(GridCreate)
{
Grid[m].StopTime=datetime(TimeCurrent()+3600*PosLifeTimeHours+60*PosLifeTimeMinutes);//Librecoin добавил datatime
return(1);//Выход - новая сетка создана
}}//if(Order_Info>0)
iReady=false;
return(0);
}//GridContinue()
//
//======================================================================================================
// TrailingVSL1() - Трейлинг виртуальных ордеров
// Вход:
// iType - тип позиции
// iMagic - магик для идентификации позиции (сетки)
// iVirtualSL - старое значение виртуального SL для позиции
// iTrail_Start - начальное значение отступа для трейлинга (макс расстояние от цены до SL)
// iTrail_Work - рабочее значение отступа для трейлинга (макс расстояние от цены до SL)
// iPosPrice - цена позиции
// idMin - старый уровень добавки к VSL
// iVSLStart - коэфф для VSL промежуточного диапазона
// iVSLWrk - коэфф (0..1) увеличения шага при росте отклонения от цены
// ------
// TheSymbol - инструмент
// AccSrv - имя торг сервера
// gSpread - спред в деньгах
// Выход:
// iVirtualSL - новое значение виртуального SL для позиции
// idMin - новый уровень добавки к VSL
//------------------------------------------------------------------------------------------------------
// Техническое описание процедуры трейлинга
// 1. Первоначальная установка уровня VSL (на примере BUY)
// Если Бид превысил цену более чем на рабочее значение дистанции трейлинга,
// То
// устанавливаем добавку VSL как (Положительная разница между (Бид) и (Цена + Раб знач дистанции трейлинга)) умноженное на коэфф VSLTrailMult
// устанавливаем уровень VSL как (Цена + Минимальная дистанция трейлинга + Добавка VSL)
// Иначе
// сбрасываем уровень VSL (и добавку VSL)
// 2. Переустановка уровня VSL (на примере BUY)
//
//======================================================================================================
void TrailingVSL1( int iType,
int iMagic,
double &iVirtualSL,
int iTrail_Start,
int iTrail_Work,
double iPosPrice,
double &idMin,
double iVSLStart,
double iVSLWrk,
int iSLTuneInterval)
{
int val_index=0;
//-----
{if(
(iPosPrice<=0.0)//Нет цены позиции
||
((iType!=OP_BUY)&&(iType!=OP_SELL))//Не обрабатываемый тип ордера
)
{
iVirtualSL=0.0;
//Print("TrailingVSL1 exit>>> iType==OP_ALL");
return;
}}//if((iPosPrice<=0.0)...
//-----
//Print("TrailingVSL1 done>>> ...");
double ipStartVSL=iTrail_Start*_Point;
double ipWorkVSL=iTrail_Work*_Point;//Пересчет из пунктов в валюту
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin," Bid=",Bid," Ask=",Ask);
//<Начальное значение idMin в деньгах> = (<комиссия в (деньгах на лот)> / <цена пункта(денег на поинт)>)*_Point + <спред в деньгах>
double idMin0=((-CalcAddCommPrice(TheSymbol,AccSrv))/SymbolTradeTickValue)*_Point+gSpread;//Добавить своп???
{if(iVirtualSL<0.001)//VSL не был установлен
{
//Print("TrailingVSL1 NOVSL>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
idMin=idMin0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;
{if(iType==OP_BUY)
{
{if(gBid-ipStartVSL-idMin0>iPosPrice)//Bid превысил (цену + комспред) более чем на защитный интервал ipStartVSL
{
idMin=idMin0+(gBid-iPosPrice-idMin0-ipStartVSL)*iVSLStart;
//---iLowest
//ArraySetAsSeries(Low,true);
CopyLow(TheSymbol,PERIOD_CURRENT,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),iSLTuneInterval),Low);
val_index=ArrayMinimum(Low,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),iSLTuneInterval));
//---
iVirtualSL=MathMax3(iPosPrice+idMin0,gBid-ipStartVSL-idMin,((val_index!=-1)?(Low[val_index]-idMin0):(iPosPrice+idMin0)));//Устанавливаем VSL на ipStartVSL над ценой позиции
}else{//(gBid-ipStartVSL-idMin0<=iPosPrice)//WorkVSL не превышен
idMin=idMin0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;//Сбросить VSL хотя он и так =0
}}//if(gBid-ipStartVSL-idMin0>iPosPrice)
}else{//(iType==OP_SELL)
{if(gAsk+idMin0+ipStartVSL<iPosPrice)//Ask ниже цены более чем на MinVSL
{
idMin=idMin0+(iPosPrice-gAsk-idMin0-ipStartVSL)*iVSLStart;
//---iHighest
//ArraySetAsSeries(High,true);
CopyHigh(TheSymbol,PERIOD_CURRENT,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),iSLTuneInterval),High);
val_index=ArrayMaximum(High,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),iSLTuneInterval));
//---
iVirtualSL=MathMin3(iPosPrice-idMin0,gAsk+ipStartVSL+idMin,((val_index!=-1)?(High[val_index]+idMin0+gSpread):(iPosPrice-idMin0)));//VSL на ipStartVSL под ценой позиции
}else{//if(gAsk+idMin0+ipStartVSL>=iPosPrice)//WorkVSL не превышен
idMin=idMin0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;//Сбросить VSL хотя он и так =0
}}//if(gAsk+idMin0+ipStartVSL<iPosPrice)
}}//if(iType==OP_BUY)
}else{//if(iOldVSL>0.0)//VSL был установлен
{if(iType==OP_BUY)
{
{if(gBid-idMin0-ipWorkVSL>iPosPrice)//Bid превысил цену более чем на WorkVSL
{
idMin=MathMax(idMin0,MathMax(idMin,idMin0+(gBid-iPosPrice-idMin0-ipWorkVSL)*iVSLWrk));
//---iLowest
//ArraySetAsSeries(Low,true);
CopyLow(TheSymbol,PERIOD_CURRENT,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),iSLTuneInterval),Low);
val_index=ArrayMinimum(Low,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),iSLTuneInterval));
//---
iVirtualSL=MathMax3(iPosPrice+idMin0,MathMax(iVirtualSL,gBid-ipWorkVSL-idMin),((val_index!=-1)?(Low[val_index]-idMin0):(iPosPrice+2*idMin0)));//VSL на ipWorkVSL ниже аска
}else{//if(Bid<=iPosPrice+ipWorkVSL)//WorkVSL не превышен
idMin=MathMax(idMin0,MathMax(idMin,idMin0+(gBid-iPosPrice-idMin0-ipStartVSL)*iVSLStart));
iVirtualSL=MathMax(iPosPrice+idMin0,MathMax(iVirtualSL,gBid-ipStartVSL-idMin));//Устанавливаем VSL на MinVSL над ценой позиции
}}//if(Ask>iPositionPrice+iStartVSL)
}else{//(iPositionType==POSITION_TYPE_SELL)
{if(gAsk+idMin0+ipWorkVSL<iPosPrice)//Степ превышен
{
idMin=MathMax(idMin0,MathMax(idMin,idMin0+(iPosPrice-gAsk-idMin0-ipWorkVSL)*iVSLWrk));
//---iHighest
//ArraySetAsSeries(High,true);
CopyHigh(TheSymbol,PERIOD_CURRENT,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),iSLTuneInterval),High);
val_index=ArrayMaximum(High,0,MathMin(Bars(TheSymbol,PERIOD_CURRENT),iSLTuneInterval));
//---
iVirtualSL=MathMin3(iPosPrice-idMin0,MathMin(iVirtualSL,gAsk+ipWorkVSL+idMin),((val_index!=-1)?(High[val_index]+idMin0+gSpread):(iPosPrice-2*idMin0)));//VSL на ipWorkVSL выше бида
}else{//if(iAsk<=iPositionPrice+iStepVSL+iMinVSL)//Степ не превышен
idMin=MathMax(idMin0,MathMax(idMin,idMin0+(iPosPrice-gAsk-idMin0-ipStartVSL)*iVSLStart));
iVirtualSL=MathMin(iPosPrice-idMin0,MathMin(iVirtualSL,gAsk+ipStartVSL+idMin));//VSL на MinVSL под ценой позиции
}}//if(Bid<iPositionPrice-iStepVSL)
}}//if(iPositionType==POSITION_TYPE_BUY)
}}//if(iOldVSL<0.001)1
//-----
//Print("TrailingVSL1 OUT>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
ArrayResize(Low,ArraySize(Time));
ArrayResize(High,ArraySize(Time));
return;
}//TrailingVSL1()
//
/*
//======================================================================================================
// TrailingVSL1() - Трейлинг виртуальных ордеров
// Вход:
// iType - тип позиции
// iMagic - магик для идентификации позиции (сетки)
// iVirtualSL - старое значение виртуального SL для позиции
// iTrail_Start - начальное значение отступа для трейлинга
// iTrail_Step - рабочее значение отступа для трейлинга
// iPosPrice - цена позиции
// idMin - старый уровень добавки к VSL
// ----
// kVSL - коэфф (0..1) увеличения шага при росте отклонения от цены
// VSLTrailMult - коэфф для VSL промежуточного диапазона
// Выход:
// iVirtualSL - новое значение виртуального SL для позиции
// idMin - новый уровень добавки к VSL
//------------------------------------------------------------------------------------------------------
// Техническое описание процедуры трейлинга
// 1. Первоначальная установка уровня VSL (на примере BUY)
// Если Бид превысил цену более чем на рабочее значение дистанции трейлинга,
// То
// устанавливаем добавку VSL как (Положительная разница между (Бид) и (Цена + Раб знач дистанции трейлинга)) умноженное на коэфф VSLTrailMult
// устанавливаем уровень VSL как (Цена + Минимальная дистанция трейлинга + Добавка VSL)
// Иначе
// сбрасываем уровень VSL (и добавку VSL)
// 2. Переустановка уровня VSL (на примере BUY)
//
//======================================================================================================
void TrailingVSL1__( int iType,
int iMagic,
double &iVirtualSL,
int iTrail_Start,
int iTrail_Step,
double iPosPrice,
double &idMin)
{
//------
{if(iType==OP_ALL)
{
iVirtualSL=0.0;
}}//if(iType==OP_ALL)
//-----
{if((iPosPrice>0)&&((iType==OP_BUY)||(iType==OP_SELL)))//Есть цена позиции и тип позиции OP_BUY или OP_SELL
{
double iVSLStep=iTrail_Step*_Point;//Пересчет из пунктов в валюту
double iVSLStart=iTrail_Start*_Point;
{if(iType==OP_BUY)
{
double iVSLDelta=(gBid-iPosPrice-iVSLStep)*VSLTrailMult;
iVSLDelta=((iVSLDelta>0)?(iVSLDelta):(0.0));
{if(gBid>iPosPrice+iVSLStart)
{
{if(iVirtualSL>0)
{
iVirtualSL=MathMax3(gBid-iVSLStep-iVSLDelta,iPosPrice+_Point,iVirtualSL);
}else{
iVirtualSL=MathMax(gBid-iVSLStart,iPosPrice+_Point);
}}//if(iVirtualSL>0)
}else{
{if(gBid<iPosPrice+_Point)
{
iVirtualSL=0;
}}//if(gBid<iPosPrice+_Point)
}}//if(gBid>iPositionPrice+iTrail_Start*_Point*VSLTrailMult)
}}//if(PositionIsBuy)
{if(iType==OP_SELL)
{
double iVSLDelta=(iPosPrice-gAsk-iVSLStep)*VSLTrailMult;
iVSLDelta=((iVSLDelta>0)?(iVSLDelta):(0.0));
{if(gAsk<iPosPrice-iVSLStart*VSLTrailMult)
{
{if(iVirtualSL>0)
{
iVirtualSL=MathMin3(gAsk+iVSLStep+iVSLDelta,iPosPrice-_Point,iVirtualSL);
}else{
iVirtualSL=MathMin(gAsk+iVSLStart,iPosPrice-_Point);
}}
}else{
{if(gAsk>iPosPrice-_Point)
{
iVirtualSL=0;
}}//if(gAsk>iPosPrice-_Point)
}}//if(gBid>iPositionPrice+iTrail_Start*_Point*dDig4Mult)
}}//if(PositionIsSell)
}}//if((iPosPrice>0)&&((iType==OP_BUY)||(iType==OP_SELL)))
return;
}//TrailingVSL()
*/
//
/*
//======================================================================================================
// TrailingVSL1() - Трейлинг виртуальных ордеров
// Вход:
// iType - тип позиции
// iMagic - магик для идентификации позиции (сетки)
// iVirtualSL - старое значение виртуального SL для позиции
// iTrail_Start - начальное значение отступа для трейлинга
// iTrail_Step - рабочее значение отступа для трейлинга
// iPosPrice - цена позиции
// idMin - старый уровень добавки к VSL
// ----
// kVSL - коэфф (0..1) увеличения шага при росте отклонения от цены
// VSLTrailMult - коэфф для VSL промежуточного диапазона
// Выход:
// iVirtualSL - новое значение виртуального SL для позиции
// idMin - новый уровень добавки к VSL
//------------------------------------------------------------------------------------------------------
// Техническое описание процедуры трейлинга
// 1. Первоначальная установка уровня VSL (на примере BUY)
// Если Бид превысил цену более чем на рабочее значение дистанции трейлинга,
// То
// устанавливаем добавку VSL как (Положительная разница между (Бид) и (Цена + Раб знач дистанции трейлинга)) умноженное на коэфф VSLTrailMult
// устанавливаем уровень VSL как (Цена + Минимальная дистанция трейлинга + Добавка VSL)
// Иначе
// сбрасываем уровень VSL (и добавку VSL)
// 2. Переустановка уровня VSL (на примере BUY)
//
//======================================================================================================
void TrailingVSL1___( int iType,
int iMagic,
double &iVirtualSL,
int iTrail_Start,
int iTrail_Step,
double iPosPrice,
double &idMin)
{
{if(iType==OP_ALL)
{
iVirtualSL=0.0;
//Print("TrailingVSL1 exit>>> iType==OP_ALL");
return;
}}//if(iType==OP_ALL)
//-----
//Print("TrailingVSL1 done>>> ...");
{if((iPosPrice>0)&&((iType==OP_BUY)||(iType==OP_SELL)))//Есть цена позиции и тип позиции OP_BUY или OP_SELL
{
double ipWorkVSL=iTrail_Step*_Point;//Пересчет из пунктов в валюту
double ipMinVSL=iTrail_Start*_Point;
//double ipWorkVSL=VSLTrailWrk*_Point;//Пересчет из пунктов в валюту
//double ipMinVSL=VSLTrailMin*_Point;
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
{if(iVirtualSL<0.001)//VSL не был установлен
{
//Print("TrailingVSL1 NOVSL>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
idMin=0.0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;
{if(iType==OP_BUY)
{
{if(gBid>iPosPrice+ipWorkVSL)//gBid превысил цену более чем на WorkVSL
{
idMin=MathMax(idMin,((gBid-iPosPrice)-ipWorkVSL)*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=iPosPrice+ipMinVSL+idMin;//Устанавливаем VSL на MinVSL над ценой позиции
}else{//(gBid<=iPosPrice+ipWorkVSL)//WorkVSL не превышен
idMin=0.0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;//Сбросить VSL хотя он и так =0
}}//if(gBid>iPosPrice+ipWorkVSL)
}else{//(iType==OP_SELL)
{if(gAsk<iPosPrice-ipWorkVSL)//gAsk ниже цены более чем на WorkVSL
{
idMin=MathMax(idMin,((iPosPrice-gAsk)-ipWorkVSL)*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=iPosPrice-ipMinVSL-idMin;//VSL на MinVSL под ценой позиции
}else{//if(gBid>=iPositionPrice-WorkVSL)//WorkVSL не превышен
idMin=0.0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;//Сбросить VSL хотя он и так =0
}}//if(gAsk<iPosPrice-ipWorkVSL)
}}//if(iType==OP_BUY)
}else{//if(iOldVSL>0.0)//VSL был устанвлен
//Print("TrailingVSL1 VSL IS>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
{if(iType==OP_BUY)
{
{if(gBid>iPosPrice+ipWorkVSL)//gBid превысил цену более чем на WorkVSL
{
{if(gBid>iPosPrice+ipWorkVSL+ipMinVSL+idMin)//WorkVSL + MinVSL превышен
{
iVirtualSL=MathMax(iVirtualSL,gBid-ipWorkVSL+(gBid-iPosPrice-ipWorkVSL-ipMinVSL-idMin)*kVSL);//VSL на StartVSL ниже аска
//Print("iVirtualSL=",iVirtualSL," gBid=",gBid," iPosPrice=",iPosPrice," d=",(gBid-(iPosPrice+ipWorkVSL+ipMinVSL+idMin)));
}else{//if(gBid<=iPosPrice+ipWorkVSL+ipMinVSL+idMin)//WorkVSL + MinVSL не превышен а WorkVSL превышен
idMin=MathMax(idMin,((gBid-iPosPrice)-ipWorkVSL)*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMax(iVirtualSL,iPosPrice+ipMinVSL+idMin);//Устанавливаем VSL на MinVSL над ценой позиции
}}//if(gBid>iPosPrice+ipWorkVSL+ipMinVSL+idMin)
}else{//if(gBid<=iPosPrice+ipWorkVSL)//WorkVSL не превышен
idMin=MathMax(idMin,((gBid-iPosPrice)-ipWorkVSL)*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMax(iVirtualSL,iPosPrice+ipMinVSL+idMin);//Устанавливаем VSL на MinVSL над ценой позиции
}}//if(gAsk>iPositionPrice+iStartVSL)
}else{//(iPositionType==POSITION_TYPE_SELL)
{if(gAsk<iPosPrice-ipWorkVSL)//Степ превышен
{
{if(gAsk<iPosPrice-ipWorkVSL-ipMinVSL-idMin)//Степ + min превышен
{
iVirtualSL=MathMin(iVirtualSL,gAsk+ipWorkVSL-(iPosPrice-gAsk-ipWorkVSL-ipMinVSL-idMin)*kVSL);//VSL на степ выше бида
//Print("iVirtualSL=",iVirtualSL," gAsk=",gAsk," iPosPrice=",iPosPrice," d=",((iPosPrice+ipWorkVSL+ipMinVSL+idMin)-gAsk));
}else{//if(gBid>=iPositionPrice-iStepVSL-iMinVSL)//Степ + min не превышен а степ превышен
idMin=MathMax(idMin,((iPosPrice-gAsk)-ipWorkVSL)*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMin(iVirtualSL,iPosPrice-ipMinVSL-idMin);//VSL на MinVSL под ценой позиции
}}//if(iBid<iPositionPrice-iStepVSL-iMinVSL)
}else{//if(iAsk<=iPositionPrice+iStepVSL+iMinVSL)//Степ не превышен
idMin=MathMax(idMin,((iPosPrice-gAsk)-ipWorkVSL)*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMin(iVirtualSL,iPosPrice-ipMinVSL-idMin);//VSL на MinVSL под ценой позиции
}}//if(gBid<iPositionPrice-iStepVSL)
}}//if(iPositionType==POSITION_TYPE_BUY)
}}//if(iOldVSL<0.001)
}else{//if(iPositionPrice<=0)//Нет цены позиции или типа
iVirtualSL=0.0;//Сбросить VSL
}}//if(iPosPrice>0)
//-----
//{if(iType==OP_BUY)
//{
// {if(gBid>iPosPrice+iTrail_Start*_Point*dDig4Mult)
// {
// {if(iVirtualSL>0)
// {
// iVirtualSL=MathMax3(gBid-iTrail_Step*_Point*dDig4Mult,iPosPrice+_Point,iVirtualSL);
// }else{
// iVirtualSL=MathMax(gBid-iTrail_Step*_Point*dDig4Mult,iPosPrice+_Point);
// }}//if(iVirtualSL>0)
// }else{
// {if(gBid<iPosPrice+_Point)
// {
// iVirtualSL=0;
// }}//if(gBid<iPositionPrice+_Point)
// }}//if(gBid>iPositionPrice+iTrail_Start*_Point*dDig4Mult)
//}}//if(PositionIsBuy)
//{if(iType==OP_SELL)
//{
// {if(gAsk<iPosPrice-iTrail_Start*_Point*dDig4Mult)
// {
// {if(iVirtualSL>0)
// {
// iVirtualSL=MathMin3(gAsk+iTrail_Step*_Point*dDig4Mult,iPosPrice-_Point,iVirtualSL);
// }else{
// iVirtualSL=MathMin(gAsk+iTrail_Step*_Point*dDig4Mult,iPosPrice-_Point);
// }}
// }else{
// {if(gAsk>iPosPrice-_Point)
// {
// iVirtualSL=0;
// }}//
// }}//if(gBid>iPositionPrice+iTrail_Start*_Point*dDig4Mult)
//}}//if(PositionIsSell)
//Print("TrailingVSL1 OUT>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
return;
}//TrailingVSL1()
*/
//
/*
//======================================================================================================
// TrailingVSL2() - Трейлинг виртуальных ордеров v2.0 (for LN v2.022)
// Вход:
// iType - тип позиции
// iMagic - магик для идентификации позиции (сетки)
// iVirtualSL - старое значение виртуального SL для позиции
// iTrail_Start - начальное значение отступа для трейлинга
// iTrail_Step - рабочее значение отступа для трейлинга
// iPosPrice - цена позиции
// idMin - старый уровень добавки к VSL
// ----
// kVSL - коэфф (0..1) увеличения шага при росте отклонения от цены
// VSLTrailMult - коэфф для VSL промежуточного диапазона
// Выход:
// iVirtualSL - новое значение виртуального SL для позиции
// idMin - новый уровень добавки к VSL
//------------------------------------------------------------------------------------------------------
// Техническое описание процедуры трейлинга
// 1. Первоначальная установка уровня VSL (на примере BUY)
// Если Бид превысил цену более чем на рабочее значение дистанции трейлинга,
// То
// устанавливаем добавку VSL как (Положительная разница между (Бид) и (Цена + Раб знач дистанции трейлинга)) умноженное на коэфф VSLTrailMult
// устанавливаем уровень VSL как (Цена + Минимальная дистанция трейлинга + Добавка VSL)
// Иначе
// сбрасываем уровень VSL (и добавку VSL)
// 2. Переустановка уровня VSL (на примере BUY)
//
//======================================================================================================
void TrailingVSL2( int iType,
int iMagic,
double &iVirtualSL,
int iTrail_Start,
int iTrail_Step,
double iPosPrice,
double &idMin,
int iVSLMode){
{if(iType==OP_ALL)
{
iVirtualSL=0.0;
//Print("TrailingVSL2 exit>>> iType==OP_ALL");
return;
}}//if(iType==OP_ALL)
//-----
//Print("TrailingVSL2 done>>> ...");
{if(iVSLMode==0)
{
{if((iPosPrice>0)&&((iType==OP_BUY)||(iType==OP_SELL)))//Есть цена позиции и тип позиции OP_BUY или OP_SELL
{
double ipWorkVSL=iTrail_Step*_Point;//Пересчет из пунктов в валюту
double ipMinVSL=iTrail_Start*_Point;
//double ipWorkVSL=VSLTrailWrk*_Point;//Пересчет из пунктов в валюту
//double ipMinVSL=VSLTrailMin*_Point;
//*****
//Print("TrailingVSL2 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
{if(iVirtualSL<0.001)//VSL не был установлен
{
//Print("TrailingVSL2 NOVSL>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
idMin=0.0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;
{if(iType==OP_BUY)
{
{if(gBid>iPosPrice+ipWorkVSL)//gBid превысил цену более чем на WorkVSL
{
idMin=MathMax(idMin,(gBid-(iPosPrice+ipWorkVSL))*VSLTrailMult);
//Print("TrailingVSL2 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=iPosPrice+ipMinVSL+idMin;//Устанавливаем VSL на MinVSL над ценой позиции
}else{//(gBid<=iPosPrice+ipWorkVSL)//WorkVSL не превышен
idMin=0.0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;//Сбросить VSL хотя он и так =0
}}//if(gBid>iPosPrice+ipWorkVSL)
}else{//(iType==OP_SELL)
{if(gAsk<iPosPrice-ipWorkVSL)//gAsk ниже цены более чем на WorkVSL
{
idMin=MathMax(idMin,((iPosPrice+ipWorkVSL)-gAsk)*VSLTrailMult);
//Print("TrailingVSL2 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=iPosPrice-ipMinVSL-idMin;//VSL на MinVSL под ценой позиции
}else{//if(gBid>=iPositionPrice-WorkVSL)//WorkVSL не превышен
idMin=0.0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;//Сбросить VSL хотя он и так =0
}}//if(gAsk<iPosPrice-ipWorkVSL)
}}//if(iType==OP_BUY)
}else{//if(iOldVSL>0.0)//VSL был устанвлен
//Print("TrailingVSL2 VSL IS>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
{if(iType==OP_BUY)
{
{if(gBid>iPosPrice+ipWorkVSL)//gBid превысил цену более чем на WorkVSL
{
{if(gBid>iPosPrice+ipWorkVSL+ipMinVSL+idMin)//WorkVSL + MinVSL превышен
{
iVirtualSL=MathMax(iVirtualSL,gBid-ipWorkVSL+((gBid-(iPosPrice+ipWorkVSL+ipMinVSL+idMin))*kVSL));//VSL на StartVSL ниже аска
//Print("iVirtualSL=",iVirtualSL," gBid=",gBid," iPosPrice=",iPosPrice," d=",(gBid-(iPosPrice+ipWorkVSL+ipMinVSL+idMin)));
}else{//if(gBid<=iPosPrice+ipWorkVSL+ipMinVSL+idMin)//WorkVSL + MinVSL не превышен а WorkVSL превышен
idMin=MathMax(idMin,(gBid-(iPosPrice+ipWorkVSL))*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMax(iVirtualSL,iPosPrice+ipMinVSL+idMin);//Устанавливаем VSL на MinVSL над ценой позиции
}}//if(gBid>iPosPrice+ipWorkVSL+ipMinVSL+idMin)
}else{//if(gBid<=iPosPrice+ipWorkVSL)//WorkVSL не превышен
idMin=MathMax(idMin,(gBid-(iPosPrice+ipWorkVSL))*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMax(iVirtualSL,iPosPrice+ipMinVSL+idMin);//Устанавливаем VSL на MinVSL над ценой позиции
}}//if(gAsk>iPositionPrice+iStartVSL)
}else{//(iPositionType==POSITION_TYPE_SELL)
{if(gAsk<iPosPrice-ipWorkVSL)//Степ превышен
{
{if(gAsk<iPosPrice-ipWorkVSL-ipMinVSL-idMin)//Степ + min превышен
{
iVirtualSL=MathMin(iVirtualSL,gAsk+ipWorkVSL-(((iPosPrice+ipWorkVSL+ipMinVSL+idMin)-gAsk)*kVSL));//VSL на степ выше бида
//Print("iVirtualSL=",iVirtualSL," gAsk=",gAsk," iPosPrice=",iPosPrice," d=",((iPosPrice+ipWorkVSL+ipMinVSL+idMin)-gAsk));
}else{//if(gBid>=iPositionPrice-iStepVSL-iMinVSL)//Степ + min не превышен а степ превышен
idMin=MathMax(idMin,((iPosPrice+ipWorkVSL)-gAsk)*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMin(iVirtualSL,iPosPrice-ipMinVSL-idMin);//VSL на MinVSL под ценой позиции
}}//if(iBid<iPositionPrice-iStepVSL-iMinVSL)
}else{//if(iAsk<=iPositionPrice+iStepVSL+iMinVSL)//Степ не превышен
idMin=MathMax(idMin,((iPosPrice+ipWorkVSL)-gAsk)*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMin(iVirtualSL,iPosPrice-ipMinVSL-idMin);//VSL на MinVSL под ценой позиции
}}//if(gBid<iPositionPrice-iStepVSL)
}}//if(iPositionType==POSITION_TYPE_BUY)
}}//if(iOldVSL<0.001)
}else{//if(iPositionPrice<=0)//Нет цены позиции или типа
iVirtualSL=0.0;//Сбросить VSL
}}//if(iPosPrice>0)
}}//if(VSLMode==0)
//------
double iCommiss=0.0;//Временно
{if(iVSLMode==1)
{
{if((iPosPrice>0)&&((iType==OP_BUY)||(iType==OP_SELL)))//Есть цена позиции и тип позиции OP_BUY или OP_SELL
{
double ipWorkVSL=iTrail_Step*_Point;//Пересчет из пунктов в валюту
double ipMinVSL=iTrail_Start*_Point;
//double ipWorkVSL=VSLTrailWrk*_Point;//Пересчет из пунктов в валюту
//double ipMinVSL=VSLTrailMin*_Point;
//*****
//Print("TrailingVSL2 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
{if(iVirtualSL<0.001)//VSL не был установлен
{
//Print("TrailingVSL2 NOVSL>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
idMin=0.0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;
{if(iType==OP_BUY)
{
{if((gBid-iPosPrice)>(ipMinVSL+iCommiss))//Дельта (gBid-Цена) превысила начальный порог (МинОтступ+Комиссия)
{
idMin=MathMax(idMin,(gBid-(iPosPrice+ipWorkVSL))*VSLTrailMult);
//Print("TrailingVSL2 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=iPosPrice+ipMinVSL+idMin;//Устанавливаем VSL на MinVSL над ценой позиции
}else{//(gBid<=iPosPrice+ipWorkVSL)//WorkVSL не превышен
idMin=0.0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;//Сбросить VSL хотя он и так =0
}}//if(gBid>iPosPrice+ipWorkVSL)
}else{//(iType==OP_SELL)
{if(gAsk<iPosPrice-ipWorkVSL)//gAsk ниже цены более чем на WorkVSL
{
idMin=MathMax(idMin,((iPosPrice+ipWorkVSL)-gAsk)*VSLTrailMult);
//Print("TrailingVSL2 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=iPosPrice-ipMinVSL-idMin;//VSL на MinVSL под ценой позиции
}else{//if(gBid>=iPositionPrice-WorkVSL)//WorkVSL не превышен
idMin=0.0;//Сбросить idMin хотя он и так =0
iVirtualSL=0.0;//Сбросить VSL хотя он и так =0
}}//if(gAsk<iPosPrice-ipWorkVSL)
}}//if(iType==OP_BUY)
}else{//if(iOldVSL>0.0)//VSL был устанвлен
//Print("TrailingVSL2 VSL IS>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
{if(iType==OP_BUY)
{
{if(gBid>iPosPrice+ipWorkVSL)//gBid превысил цену более чем на WorkVSL
{
{if(gBid>iPosPrice+ipWorkVSL+ipMinVSL+idMin)//WorkVSL + MinVSL превышен
{
iVirtualSL=MathMax(iVirtualSL,gBid-ipWorkVSL+((gBid-(iPosPrice+ipWorkVSL+ipMinVSL+idMin))*kVSL));//VSL на StartVSL ниже аска
//Print("iVirtualSL=",iVirtualSL," gBid=",gBid," iPosPrice=",iPosPrice," d=",(gBid-(iPosPrice+ipWorkVSL+ipMinVSL+idMin)));
}else{//if(gBid<=iPosPrice+ipWorkVSL+ipMinVSL+idMin)//WorkVSL + MinVSL не превышен а WorkVSL превышен
idMin=MathMax(idMin,(gBid-(iPosPrice+ipWorkVSL))*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMax(iVirtualSL,iPosPrice+ipMinVSL+idMin);//Устанавливаем VSL на MinVSL над ценой позиции
}}//if(gBid>iPosPrice+ipWorkVSL+ipMinVSL+idMin)
}else{//if(gBid<=iPosPrice+ipWorkVSL)//WorkVSL не превышен
idMin=MathMax(idMin,(gBid-(iPosPrice+ipWorkVSL))*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMax(iVirtualSL,iPosPrice+ipMinVSL+idMin);//Устанавливаем VSL на MinVSL над ценой позиции
}}//if(gAsk>iPositionPrice+iStartVSL)
}else{//(iPositionType==POSITION_TYPE_SELL)
{if(gAsk<iPosPrice-ipWorkVSL)//Степ превышен
{
{if(gAsk<iPosPrice-ipWorkVSL-ipMinVSL-idMin)//Степ + min превышен
{
iVirtualSL=MathMin(iVirtualSL,gAsk+ipWorkVSL-(((iPosPrice+ipWorkVSL+ipMinVSL+idMin)-gAsk)*kVSL));//VSL на степ выше бида
//Print("iVirtualSL=",iVirtualSL," gAsk=",gAsk," iPosPrice=",iPosPrice," d=",((iPosPrice+ipWorkVSL+ipMinVSL+idMin)-gAsk));
}else{//if(gBid>=iPositionPrice-iStepVSL-iMinVSL)//Степ + min не превышен а степ превышен
idMin=MathMax(idMin,((iPosPrice+ipWorkVSL)-gAsk)*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMin(iVirtualSL,iPosPrice-ipMinVSL-idMin);//VSL на MinVSL под ценой позиции
}}//if(iBid<iPositionPrice-iStepVSL-iMinVSL)
}else{//if(iAsk<=iPositionPrice+iStepVSL+iMinVSL)//Степ не превышен
idMin=MathMax(idMin,((iPosPrice+ipWorkVSL)-gAsk)*VSLTrailMult);
//Print("TrailingVSL1 INTO>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
iVirtualSL=MathMin(iVirtualSL,iPosPrice-ipMinVSL-idMin);//VSL на MinVSL под ценой позиции
}}//if(gBid<iPositionPrice-iStepVSL)
}}//if(iPositionType==POSITION_TYPE_BUY)
}}//if(iOldVSL<0.001)
}else{//if(iPositionPrice<=0)//Нет цены позиции или типа
iVirtualSL=0.0;//Сбросить VSL
}}//if(iPosPrice>0)
}}//if(VSLMode==1)
//-----
//{if(iType==OP_BUY)
//{
// {if(gBid>iPosPrice+iTrail_Start*_Point*dDig4Mult)
// {
// {if(iVirtualSL>0)
// {
// iVirtualSL=MathMax3(gBid-iTrail_Step*_Point*dDig4Mult,iPosPrice+_Point,iVirtualSL);
// }else{
// iVirtualSL=MathMax(gBid-iTrail_Step*_Point*dDig4Mult,iPosPrice+_Point);
// }}//if(iVirtualSL>0)
// }else{
// {if(gBid<iPosPrice+_Point)
// {
// iVirtualSL=0;
// }}//if(gBid<iPositionPrice+_Point)
// }}//if(gBid>iPositionPrice+iTrail_Start*_Point*dDig4Mult)
//}}//if(PositionIsBuy)
//{if(iType==OP_SELL)
//{
// {if(gAsk<iPosPrice-iTrail_Start*_Point*dDig4Mult)
// {
// {if(iVirtualSL>0)
// {
// iVirtualSL=MathMin3(gAsk+iTrail_Step*_Point*dDig4Mult,iPosPrice-_Point,iVirtualSL);
// }else{
// iVirtualSL=MathMin(gAsk+iTrail_Step*_Point*dDig4Mult,iPosPrice-_Point);
// }}
// }else{
// {if(gAsk>iPosPrice-_Point)
// {
// iVirtualSL=0;
// }}//
// }}//if(gBid>iPositionPrice+iTrail_Start*_Point*dDig4Mult)
//}}//if(PositionIsSell)
//Print("TrailingVSL2 OUT>>> VirtualSL=",iVirtualSL," iType=",TypeToString(iType)," iPosPrice=",iPosPrice," idMin=",idMin);
return;
}//TrailingVSL2()
*/
//
////======================================================================================================
//// TrailingSL()
////======================================================================================================
//void TrailingSL(int iType, int iMagic, int iTrail_Start, int iTrail_Step, double iPosPrice){
//double OldStopLoss;
//double NewStopLoss;
////-----
// {if (iTrail_Step!=0)
// {
// if(PositionsTotal()>0)
// {for(int n=PositionsTotal()-1;n>=0;n--)
// {
// Ord_Inf=PositionSelect(n,SELECT_BY_POS,MODE_TRADES);
// {if(!Ord_Inf){continue;}}
// {if((PositionGetString(POSITION_SYMBOL)!=TheSymbol)||(PositionGetInteger(POSITION_MAGIC)!=iMagic)){continue;}}
// OldStopLoss=PositionGetDouble(POSITION_SL);
// {if(((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_BUY)&&((iType==OP_ALL)||(iType==OP_BUY)))
// {
// {if((gBid>iPosPrice+iTrail_Start*_Point*dDig4Mult)//Если прибыль больше старта трала
// &&(gBid>iPosPrice+SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point))//И больше стоплевела
// {
// //Установим если не было (подвинем если был) стоплосс на максимальное из
// //1. iPositionPrice+_Point
// //2. gBid-iTrail_Step
// NewStopLoss=fNormalizeDouble(MathMax(gBid-iTrail_Step*_Point*dDig4Mult,iPosPrice+_Point));
// {if(NewStopLoss>gBid-SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point)
// {//Больше стоплевела - нельзя ставить можно только на стоплевел
// NewStopLoss=fNormalizeDouble(gBid-SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point);
// }}//
// {if(((NewStopLoss>OldStopLoss)||(OldStopLoss==0))&&(NewStopLoss>iPosPrice))
// {//Лучше прежнего или первый раз, ну и конечно выше средней цены
// Ord_Inf=OrderModify(PositionGetInteger(POSITION_TICKET),PositionGetDouble(POSITION_PRICE_OPEN),NewStopLoss,PositionGetDouble(POSITION_TP),0,Aqua);
// }}//
// }}//if
// }}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_BUY)
// {if(((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)&&((iType==OP_ALL)||(iType==OP_SELL)))
// {
// {if((gAsk<iPosPrice-iTrail_Start*_Point*dDig4Mult)//Если прибыль Меньше старта трала
// &&(gAsk<iPosPrice-SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point))//И Меньше стоплевела
// {
// NewStopLoss=fNormalizeDouble(MathMin(gAsk+iTrail_Step*_Point*dDig4Mult,iPosPrice-_Point));
// {if(NewStopLoss<gAsk+SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point)
// {//Меньше стоплевела - нельзя ставить можно только на стоплевел
// NewStopLoss=fNormalizeDouble(gAsk+SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point);
// }}//
// {if(((NewStopLoss<OldStopLoss)||(OldStopLoss==0))&&(NewStopLoss<iPosPrice))
// {//Лучше прежнего или первый раз, ну и конечно ниже средней цены
// Ord_Inf=OrderModify(PositionGetInteger(POSITION_TICKET),PositionGetDouble(POSITION_PRICE_OPEN),NewStopLoss,PositionGetDouble(POSITION_TP),0,Red);
// }}//
// }}//if ((OldStopLoss==0.0)||((OldStopLoss!=0.0)&&(NewStopLoss<OldStopLoss)))
// }}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)
// Sleep(100);
// }}//for (int n=PositionsTotal()-1;n>=0;n--)
// }}//if (iTrailStep!=0)
//}//TrailingSL()
//
//======================================================================================================
// TrailingSL1() v4.105
// Описание:
// Устанавливаем стопы чуть позднее виртуальных (на 1-3 пункта SL2VSLSlip)
// Вход:
// iType
// iMagic
// iVirtualSL
//======================================================================================================
void TrailingSL1( int iType, //Тип позиции
int iMagic, //Магик позиции
double &iVirtualSL, //Уровень виртуального стоплосса
double &iSL, //Уровень стоплосс для позиции после установки
int iSL2VSLSlip, //Растояние в пипсах между SL(хуже) и VSL(лучше)
double iPosPrice) //Цена позиции
{
int
m=iMagic-Grid[0].Magic;
double OldStopLoss;
double NewStopLoss;
//-----
{if (iVirtualSL>=0)//Виртуальный уже установлен
{
if(PositionsTotal()>0)//Есть сделки
{for(int i=PositionsTotal()-1;i>=0;i--)//Перебираем сделки
{
ulong Pos_Tick=PositionGetTicket(i);//Выбираем позицию по номеру в списке
{if(Pos_Tick<=0){continue;}}//Неудачно - следующий
{if(!PositionSelectByTicket(Pos_Tick)){continue;}};//Выбираем позицию по тикету? Неудачно - следующий
{if(PositionGetString(POSITION_SYMBOL)!=TheSymbol){continue;}}//Не наш символ - к следующему
{if((PositionGetInteger(POSITION_MAGIC)!=iMagic)){continue;}}//Не наш магик - к следующему
{if(PositionGetDouble(POSITION_VOLUME)<0.01){continue;}}//Нулевой объём - к следующему
OldStopLoss=PositionGetDouble(POSITION_SL);//Запомним текущий стоплосс
{if((PositionGetInteger(POSITION_TYPE)==OP_BUY)&&((iType==OP_ALL)||(iType==OP_BUY)))//Отбор по типу ордера
{
{if(gBid>iVirtualSL-iSL2VSLSlip*_Point+SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point)////И больше стоплевела от iVirtualSL-iSL2VSLSlip
{
//Установим если не было (подвинем если был) стоплосс на iVirtualSL-iSL2VSLSlip
NewStopLoss=fNormalizeDouble(iVirtualSL-iSL2VSLSlip*_Point);
{if(NewStopLoss>gBid-SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point)
{//Больше стоплевела - нельзя ставить можно только на стоплевел
NewStopLoss=fNormalizeDouble(gBid-SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point);
}}//
{if(((NewStopLoss>OldStopLoss)||(OldStopLoss==0))&&(NewStopLoss>iPosPrice))
{//Лучше прежнего или первый раз, ну и конечно выше средней цены
Ord_Inf=PositionModifySL(Pos_Tick,NewStopLoss,PositionGetDouble(POSITION_TP));
{if(Ord_Inf)
{
Grid[m].StopLossLevel=NewStopLoss;
iSL=NewStopLoss;
}}//if(Ord_Inf)
}}//
}}//if
}}//if(PositionGetInteger(POSITION_TYPE)==OP_BUY)
{if((PositionGetInteger(POSITION_TYPE)==OP_SELL)&&((iType==OP_ALL)||(iType==OP_SELL)))
{
{if(gAsk<iVirtualSL+iSL2VSLSlip*_Point-SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point)//
{
NewStopLoss=fNormalizeDouble(iVirtualSL+iSL2VSLSlip*_Point);
{if(NewStopLoss<gAsk+SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point)
{//Меньше стоплевела - нельзя ставить можно только на стоплевел
NewStopLoss=fNormalizeDouble(gAsk+SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point);
}}//
{if(((NewStopLoss<OldStopLoss)||(OldStopLoss==0))&&(NewStopLoss<iPosPrice))
{//Лучше прежнего или первый раз, ну и конечно ниже средней цены
Ord_Inf=PositionModifySL(Pos_Tick,NewStopLoss,PositionGetDouble(POSITION_TP));
{if(Ord_Inf)
{
Grid[m].StopLossLevel=NewStopLoss;
iSL=NewStopLoss;
}}//if(Ord_Inf)
}}//
}}//if ((OldStopLoss==0.0)||((OldStopLoss!=0.0)&&(NewStopLoss<OldStopLoss)))
}}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)
//Sleep(10);
}}//for (int n=PositionsTotal()-1;n>=0;n--)
}}//if (iTrailStep!=0)
}//TrailingSL1()
//
//======================================================================================================
// CloseGrid() - Закрывает несколько позиций (сетку) по инструменту, типу и магику, с возможностью закрытия только убыточных
//======================================================================================================
int CloseGrid( string iSymbol,
OP_TYPE iType,
bool iLossOnly,
int iMagic){
int
m=iMagic-Grid[0].Magic;
int
nClosed=0;
//-----
{if((iLossOnly)&&(CalcPositionProfitSum1(TheSymbol,iType,iMagic,1)>0.0)&&(Grid[m].VirtualSL>0.0))
{
return(nClosed);
}}//if((iLossOnly)&&(CalcPositionProfitSum()>0.0))
if(PositionsTotal()>0)
{for (int i=PositionsTotal()-1;i>=0;i--)
{
ulong Pos_Tick=PositionGetTicket(i);//Выбираем позицию по номеру в списке
{if(Pos_Tick<=0){continue;}}//Неудачно - следующий
{if(!PositionSelectByTicket(Pos_Tick)){continue;}}//Выбираем позицию по тикету? Неудачно - следующий
{if(PositionGetString(POSITION_SYMBOL)!=iSymbol){continue;}}//Отбор по инструменту
{if(PositionGetInteger(POSITION_MAGIC)!=iMagic){continue;}}//Отбор по магику
{if(PositionGetDouble(POSITION_VOLUME)==0.0){continue;}}//Отбор непустых
ENUM_POSITION_TYPE OrdType=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
//{if((OrdType!=POSITION_TYPE_SELL)&&(OrdType!=POSITION_TYPE_BUY)){continue;}}
{if((OrdType==POSITION_TYPE_BUY)&&((iType==OP_BUY)||(iType==OP_ALL)))
{
//Ord_Inf=mPositionClose2(iSymbol,PositionGetInteger(POSITION_IDENTIFIER),SlipFixOrd,RepFixOrd,"CloseGrid(BUY)");
Ord_Inf=mPositionClose2(iSymbol,Pos_Tick,SlipFixOrd,RepFixOrd,"CloseGrid(BUY)");
nClosed++;
continue;
}}//if((OrdType==POSITION_TYPE_SELL)&&((iType==OP_SELL)||(iType==OP_ALL)))
{if((OrdType==POSITION_TYPE_SELL)&&((iType==OP_SELL)||(iType==OP_ALL)))
{
//Ord_Inf=mPositionClose2(iSymbol,PositionGetInteger(POSITION_IDENTIFIER),SlipFixOrd,RepFixOrd,"CloseGrid(SELL)");
Ord_Inf=mPositionClose2(iSymbol,Pos_Tick,SlipFixOrd,RepFixOrd,"CloseGrid(SELL)");
nClosed++;
}}//if((OrdType==POSITION_TYPE_SELL)&&((iType==OP_SELL)||(iType==OP_ALL)))
Sleep(CloseDelay);
}}//for (int j=PositionsTotal()-1;j>=0;j--)
{if(nClosed>0)
{
Grid[m].CloseOn=true;
Grid[m].Active=false;
Grid[m].VirtualSL=0.0;
Grid[m].Type=OP_ALL;
Grid[m].Ticket=0;
}}//if(nClosed>0)
return(nClosed);
}//CloseGrid
//
//======================================================================================================
// CloseGridesAll()
// Описание:
// Закрывает ордера заданного типа и заданного диапазона магиков, возможно только убыточные
//======================================================================================================
int CloseGridesAll( string iSymbol,
OP_TYPE iType,
bool iLossOnly,
int iMagic,
int inGrides){
int
m=0;
long
OrderMagicN=iMagic;
int
nClosed=0;
//-----
{if((iLossOnly)&&(CalcPositionProfitSum1(TheSymbol,iType,iMagic,inGrides)>0.0))
//{if((iLossOnly)&&(CalcPositionProfitSum1(iType,iMagic,inGrides)>0.0)&&(Grid[m].VirtualSL>0.0))
{
return(nClosed);
}}//if((iLossOnly)&&(CalcPositionProfitSum()>0.0))
if(PositionsTotal()>0)
{for (int i=PositionsTotal()-1;i>=0;i--)
{
ulong Pos_Tick=PositionGetTicket(i);//Выбираем позицию по номеру в списке
{if(Pos_Tick<=0){continue;}}//Неудачно - следующий
{if(!PositionSelectByTicket(Pos_Tick)){continue;}}//Выбираем позицию по тикету? Неудачно - следующий
{if(PositionGetString(POSITION_SYMBOL)!=TheSymbol){continue;}}//Отбор по символу
OrderMagicN=PositionGetInteger(POSITION_MAGIC);
m=(int)(OrderMagicN-Grid[0].Magic);
{if(((OrderMagicN<iMagic)||(OrderMagicN>=iMagic+inGrides))&&(iMagic!=MAGIC_ALL)){continue;}}//Отбор по магику
{if(PositionGetDouble(POSITION_VOLUME)==0.0){continue;}}//Отбор непустых
ENUM_POSITION_TYPE OrdType=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
//{if((OrdType!=POSITION_TYPE_SELL)&&(OrdType!=POSITION_TYPE_BUY)){continue;}}
Ord_Int=-1;
{if((OrdType==POSITION_TYPE_BUY)&&((iType==OP_BUY)||(iType==OP_ALL)))
{
//Print("Grid[0].Magic=",Grid[0].Magic," PositionGetInteger(POSITION_MAGIC)=",PositionGetInteger(POSITION_MAGIC));
Ord_Int=mPositionClose2(iSymbol,PositionGetInteger(POSITION_TICKET),SlipFixOrd,RepFixOrd,"CloseGridesAll(BUY)");
//Print("ClosePositionAll in for, VirtualSL Close TRY OP_BUY Ord_Int=",Ord_Int);
{if((Ord_Int==ERR_NO_MQLERROR)||(Ord_Int==ERR_SUCCESS))
{
Grid[m].VirtualSL=0.0;
Grid[m].Type=OP_ALL;
Grid[m].Active=false;
nClosed++;
continue;
}}//if(Ord_Inf)
}}//if((OrdType==POSITION_TYPE_BUY)&&((iType==OP_BUY)||(iType==OP_ALL)))
{if((OrdType==POSITION_TYPE_SELL)&&((iType==OP_SELL)||(iType==OP_ALL)))
{
Ord_Int=mPositionClose2(iSymbol,PositionGetInteger(POSITION_TICKET),SlipFixOrd,RepFixOrd,"CloseGridesAll(SELL)");
//Print("ClosePositionAll in for, VirtualSL Close TRY OP_SELL Ord_Int=",Ord_Int);
{if((Ord_Int==ERR_NO_MQLERROR)||(Ord_Int==ERR_SUCCESS))
{
Grid[m].VirtualSL=0.0;
Grid[m].Type=OP_ALL;
Grid[m].Active=false;
nClosed++;
//continue;
}}//if(Ord_Inf)
}}//if((OrdType==POSITION_TYPE_SELL)&&((iType==OP_SELL)||(iType==OP_ALL)))
Sleep(CloseDelay);
}}//for (int j=PositionsTotal()-1;j>=0;j--)
return(nClosed);
}//CloseGridesAll
//
////======================================================================================================
//// B4BCloseMA();//v69.159 008 - Закрывает все ордера встречно-оптимально
////======================================================================================================
//bool B4BCloseMA(int iMagic,int inGrides){
// if (!B4BCloseMOn) {return(false);}
//bool
// B4BRes=false,
// BePair=true;
//double
// AddCom=0.0,
// closeLot=0,
// closeProfit=0,
// lossLotBUY=0,
// lossLotSELL=0,
// lossBUY=0,
// lossSELL=0,
// profitLotBUY=0,
// profitLotSELL=0,
// profitBUY=0,
// profitSELL=0,
// profitDBUY=99999999.0,
// profitDSELL=99999999.0;
//int
// Ord_Tick=-1,
// nMLossBUY=-1,
// nMLossSELL=-1,
// nMProfitBUY=-1,
// nMProfitSELL=-1;
//// if (AccountFreeMargin()>B4BCloseLim*MathMax(AccountInfoDouble(ACCOUNT_EQUITY),AccountInfoDouble(ACCOUNT_BALANCE))) {return(true);}
//// if (AccountFreeMargin()>B4BCloseLim*AccountInfoDouble(ACCOUNT_BALANCE)) {return(true);}//Порог от Equity для инициации закрытия
// while (BePair==true)//Надо - ибо не один
// {
// closeLot=0;
// closeProfit=0;
// lossLotBUY=0;
// lossLotSELL=0;
// profitLotBUY=0;
// profitLotSELL=0;
// lossBUY=0;
// lossSELL=0;
// profitBUY=0;
// profitSELL=0;
// profitDBUY=99999999.0;
// profitDSELL=99999999.0;
// nMLossBUY=-1;
// nMLossSELL=-1;
// nMProfitBUY=-1;
// nMProfitSELL=-1;
// //Закрываем максимальный убыток на оптимальную прибыль
// //Ищем ордер с максимальным убытком на лот
// {//Перебор ордеров от последнего к первому
// for(int y=PositionsTotal()-1;y>=0;y--)
// {
// Ord_inf=PositionSelect(y,SELECT_BY_POS,MODE_TRADES);
// if (!Ord_inf) {continue;}
// if (PositionGetString(POSITION_SYMBOL)!=_Symbol) {continue;}
// {if((PositionGetInteger(POSITION_MAGIC)<iMagic)||(PositionGetInteger(POSITION_MAGIC)>=iMagic+inGrides)){continue;}} //Отбор по магику
// Ord_Tick=PositionGetInteger(POSITION_TICKET);
// Ord_inf=PositionSelect(Ord_Tick,SELECT_BY_TICKET,MODE_TRADES);
// if (!Ord_inf) {continue;}
// {//Если ордер убыточный
// if (PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME)<-0.0001)
// {
// {//Для ордера на покупку
// if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_BUY)
// {
// {//Если убыток больше (его значение меньше) ранее найденного по BUY
// if (PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME)<lossBUY)
// {
// nMLossBUY=Ord_Tick;
// lossBUY=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME);
// lossLotBUY=PositionGetDouble(POSITION_VOLUME);
// }}//if (PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)<lossBUY)
// }}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_BUY)
// {//Для ордера на продажу
// if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)
// {
// {//Если убыток больше (его значение меньше) ранее найденного по SELL
// if (PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME)<lossSELL)
// {
// nMLossSELL=Ord_Tick;
// lossSELL=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME);
// lossLotSELL=PositionGetDouble(POSITION_VOLUME);
// }}//if (PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)<lossSELL)
// }}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)
// }}//if (PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)<-0.0001)
// }}//for(int y=PositionsTotal()-1;y>=0;y--)
// {//Если решения по LOSS не найдено
// if ((nMLossBUY<0)&&(nMLossSELL<0))
// {
// //B4BRes=false;
//if (PrnB4BM) Print("************* B4BCloseM 1>>"," LOSSES NOT FOUND!!!"," lossB=",lossBUY," lossS=",lossSELL,
// " Fr=",AccountFreeMargin()," Eq=",AccountInfoDouble(ACCOUNT_EQUITY));//," MinEq=",MinEq);
// //continue;
// return(B4BRes);
// }}//if ((nMLossBUY<0)&&(nMLossSELL<0))
//if (PrnB4BM) Print("************* B4BCloseM 2>>"," LOSSES FOUND!!!"," lossB=",lossBUY," lossS=",lossSELL,
// " Fr=",AccountFreeMargin()," Eq=",AccountInfoDouble(ACCOUNT_EQUITY));//," MinEq=",MinEq);
// //Ищем ордер с оптимальной прибылью на лот
// //тут имена переменных унаследованы и особого смысла не имеют
// {//Перебор ордеров от конца - к началу
// for (int y=PositionsTotal()-1;y>=0;y--)
// {//перебор всех ордеров
// Ord_inf=PositionSelect(y,SELECT_BY_POS,MODE_TRADES);
// if (!Ord_inf) {continue;}
// if (PositionGetString(POSITION_SYMBOL)!=_Symbol) {continue;}
// {if((PositionGetInteger(POSITION_MAGIC)<iMagic)||(PositionGetInteger(POSITION_MAGIC)>=iMagic+inGrides)){continue;}} //Отбор по магику
// Ord_Tick=PositionGetInteger(POSITION_TICKET);
// Ord_inf=PositionSelect(Ord_Tick,SELECT_BY_TICKET,MODE_TRADES);
// if (!Ord_inf) {continue;}
// {//Если ордер прибыльный
// if (PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME)>0.0001)
// {
// {//Для ордера на покупку - если убыток от ордера на продажу обнаружен
// if (((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_BUY)&&(lossLotSELL>0)&&(PositionGetDouble(POSITION_VOLUME)>0))
// {
// //Вычисляем возмоный профит по BUY
// double profitDBUYtmp=(PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME))/PositionGetDouble(POSITION_VOLUME)+lossSELL/lossLotSELL;
// {//Если было найдено - в убыток, а теперь в прибыль - то запомним
// if ((profitDBUY<0)&&(profitDBUYtmp>0))
// {
// nMProfitBUY=Ord_Tick;
// profitBUY=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME);
// profitLotBUY=PositionGetDouble(POSITION_VOLUME);
// profitDBUY=profitDBUYtmp;
// }else{
// {//Если было найдено - в убыток, и теперь в убыток - то оценим
// if ((profitDBUY<0)&&(profitDBUYtmp<0))
// {
// {//Если значения ближе - запомним
// if (MathAbs(profitDBUYtmp)<MathAbs(profitDBUY))
// {
// nMProfitBUY=Ord_Tick;
// profitBUY=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME);
// profitLotBUY=PositionGetDouble(POSITION_VOLUME);
// profitDBUY=profitDBUYtmp;
// }}//if (MathAbs(profitDBUYtmp)<MathAbs(profitDBUY))
// }else{
// {//Если было найдено - в прибыль, и теперь в прибыль - то оценим
// if ((profitDBUY>0)&&(profitDBUYtmp>0))
// {
// {//Если значения ближе - запомним
// if (MathAbs(profitDBUYtmp)<MathAbs(profitDBUY))
// {
// nMProfitBUY=Ord_Tick;
// profitBUY=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME);
// profitLotBUY=PositionGetDouble(POSITION_VOLUME);
// profitDBUY=profitDBUYtmp;
// }}//if (MathAbs(profitDBUYtmp)<MathAbs(profitDBUY))
// }}//if ((profitDBUY>0)&&(profitDBUYtmp>0))
// //Если было найдено - в прибыль, а теперь в убыток - то ничего делать не надо
// }}//if ((profitDBUY<0)&&(profitDBUYtmp<0))
// }}
// }}//if (((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_BUY)&&(lossLotSELL>0)&&(PositionGetDouble(POSITION_VOLUME)>0))
// {//Для ордера на продажу - если убыток от ордера на покупку обнаружен
// if (((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)&&(lossLotBUY>0)&&(PositionGetDouble(POSITION_VOLUME)>0))
// {
// //Вычисляем возмоный профит по SELL
// double profitDSELLtmp=(PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME))/PositionGetDouble(POSITION_VOLUME)+lossBUY/lossLotBUY;
// {//Если было найдено - в убыток, а теперь в прибыль - то запомним
// if ((profitDSELL<0)&&(profitDSELLtmp>0))
// {
// nMProfitSELL=Ord_Tick;
// profitSELL=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME);
// profitLotSELL=PositionGetDouble(POSITION_VOLUME);
// profitDSELL=profitDSELLtmp;
// }else{
// {//Если было найдено - в убыток, и теперь в убыток - то оценим
// if ((profitDSELL<0)&&(profitDSELLtmp<0))
// {
// {//Если значения ближе - запомним
// if (MathAbs(profitDSELLtmp)<MathAbs(profitDSELL))
// {
// nMProfitSELL=Ord_Tick;
// profitSELL=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME);
// profitLotSELL=PositionGetDouble(POSITION_VOLUME);
// profitDSELL=profitDSELLtmp;
// }}//if (MathAbs(profitDSELLtmp)<MathAbs(profitDSELL))
// }else{
// {//Если было найдено - в прибыль, и теперь в прибыль - то оценим
// if ((profitDSELL>0)&&(profitDSELLtmp>0))
// {
// {//Если значения ближе - запомним
// if (MathAbs(profitDSELLtmp)<MathAbs(profitDSELL))
// {
// nMProfitSELL=Ord_Tick;
// profitSELL=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)-10*AddCom*PositionGetDouble(POSITION_VOLUME);
// profitLotSELL=PositionGetDouble(POSITION_VOLUME);
// profitDSELL=profitDSELLtmp;
// }}//if (MathAbs(profitDSELLtmp)<MathAbs(profitDSELLtmp))
// }}//if ((profitDSELL>0)&&(profitDSELLtmp>0))
// }}//if ((profitDSELL<0)&&(profitDSELLtmp>0))
// }}
// }}//if (((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)&&(lossLotBUY>0)&&(PositionGetDouble(POSITION_VOLUME)>0))
// }}//if (PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_COMISSION)+PositionGetDouble(POSITION_SWAP)>0.0001)
// }}//for (int y=PositionsTotal()-1;y>=0;y--)
// {//Если решения по Profit не найдено
// if ((nMProfitBUY<0)&&(nMProfitSELL<0))
// {
// //B4BRes=false;
//if (PrnB4BM) Print("************* B4BCloseM 3>>"," PROFIT NOT FOUND!!!"," profitB=",profitBUY," profitS=",profitSELL,
// " Fr=",AccountFreeMargin()," Eq=",AccountInfoDouble(ACCOUNT_EQUITY));//," MinEq=",MinEq);
// //continue;
// return(B4BRes);
// }}//if ((nMProfitBUY<0)&&(nMProfitSELL<0))
//if (PrnB4BM) Print("************* B4BCloseM 4>>"," PROFIT FOUND!!!"," profitB=",profitBUY," profitS=",profitSELL,
// " Fr=",AccountFreeMargin()," Eq=",AccountInfoDouble(ACCOUNT_EQUITY));//," MinEq=",MinEq);
// double lim=100;
// bool pairFound=false;
//
// for (lim=1000;lim>100;lim-=10)
// {
// if ((profitBUY>0.0001)&&(lossSELL<-0.0001)&&(profitBUY>=-lim*lossSELL))//&&(tsmiTrendBidNorm[9]<0))//прибыльный BUY - убыточный SELL - и прибыль падает
// {
// closeLot=MathMin(profitLotBUY,lossLotSELL);
// closeProfit=closeLot*(profitBUY/profitLotBUY+lossSELL/lossLotSELL);
// pairFound=true;
// if (Prn1) Print(" profitLotBUY=",profitLotBUY," lossLotSELL=",lossLotSELL);//," ltSprad=",ltSprad);
// }
// if ((profitSELL>0.0001)&&(lossBUY<-0.0001)&&(profitSELL>=-lim*lossBUY))//&&(tsmiTrendAskNorm[9]>0))//прибыльный SELL - убыточный BUY - и прибыль падает
// {
// closeLot=MathMin(profitLotSELL,lossLotBUY);
// closeProfit=closeLot*(profitSELL/profitLotSELL+lossBUY/lossLotBUY);
// pairFound=true;
// if (Prn1) Print(" profitLotSELL=",profitLotSELL," lossLotBUY=",lossLotBUY);//," ltSprad=",ltSprad);
// }
// if (pairFound){break;}
// }//end for
//
// if (!pairFound)
// for (lim=100;lim>10;lim-=1)
// {
// if ((profitBUY>0.0001)&&(lossSELL<-0.0001)&&(profitBUY>=-lim*lossSELL))//&&(tsmiTrendBidNorm[9]<0))//прибыльный BUY - убыточный SELL - и прибыль падает
// {
// closeLot=MathMin(profitLotBUY,lossLotSELL);
// closeProfit=closeLot*(profitBUY/profitLotBUY+lossSELL/lossLotSELL);
// pairFound=true;
// if (Prn1) Print(" profitLotBUY=",profitLotBUY," lossLotSELL=",lossLotSELL);//," ltSprad=",ltSprad);
// }
// if ((profitSELL>0.0001)&&(lossBUY<-0.0001)&&(profitSELL>=-lim*lossBUY))//&&(tsmiTrendAskNorm[9]>0))//прибыльный SELL - убыточный BUY - и прибыль падает
// {
// closeLot=MathMin(profitLotSELL,lossLotBUY);
// closeProfit=closeLot*(profitSELL/profitLotSELL+lossBUY/lossLotBUY);
// pairFound=true;
// if (Prn1) Print(" profitLotSELL=",profitLotSELL," lossLotBUY=",lossLotBUY);//," ltSprad=",ltSprad);
// }
// if (pairFound){break;}
// }//end for
//
// if (!pairFound)
// for (lim=10.0;lim>=B4BMLowLim;lim-=0.001)
// {
// if ((profitBUY>0.0001)&&(lossSELL<-0.0001)&&(profitBUY>=-lim*lossSELL))//&&(tsmiTrendBidNorm[9]<0))//прибыльный BUY - убыточный SELL - и прибыль падает
// {
// closeLot=MathMin(profitLotBUY,lossLotSELL);
// closeProfit=closeLot*(profitBUY/profitLotBUY+lossSELL/lossLotSELL);
// pairFound=true;
// if (Prn1) Print(" profitLotBUY=",profitLotBUY," lossLotSELL=",lossLotSELL);//," ltSprad=",ltSprad);
// }
// if ((profitSELL>0.0001)&&(lossBUY<-0.0001)&&(profitSELL>=-lim*lossBUY))//&&(tsmiTrendAskNorm[9]>0))//прибыльный SELL - убыточный BUY - и прибыль падает
// {
// closeLot=MathMin(profitLotSELL,lossLotBUY);
// closeProfit=closeLot*(profitSELL/profitLotSELL+lossBUY/lossLotBUY);
// pairFound=true;
// if (Prn1) Print(" profitLotSELL=",profitLotSELL," lossLotBUY=",lossLotBUY);//," ltSprad=",ltSprad);
// }
// if (pairFound){break;}
// }//end for
//
// if (pairFound)
// {
//if (PrnB4BM) Print("************* B4BCloseM 5>>"," PAIR FOUND!!!",
// " profitLotB=",profitLotBUY," lossLotS=",lossLotSELL," profitLotS=",profitLotSELL," lossLotB=",lossLotBUY,
// " Fr=",AccountFreeMargin()," Eq=",AccountInfoDouble(ACCOUNT_EQUITY));//," MinEq=",MinEq);
// }else{
// //B4BRes=false;
//if (PrnB4BM) Print("************* B4BCloseM 6>>"," PAIR NOT FOUND!!!",
// " profitLotB=",profitLotBUY," lossLotS=",lossLotSELL," profitLotS=",profitLotSELL," lossLotB=",lossLotBUY,
// " Fr=",AccountFreeMargin()," Eq=",AccountInfoDouble(ACCOUNT_EQUITY));//," MinEq=",MinEq);
// //continue;
// //return(B4BRes);
// }
// //Если пары есть - закрываем, пар нет - снимаем флаг продолжения
// if (true
// //&&(false
// // ||((profitBUY>0.01)&&(lossSELL<-0.01)&&(profitBUY>=-lim*lossSELL))
// // ||((profitSELL>0.01)&&(lossBUY<-0.01)&&(profitSELL>=-lim*lossBUY)))
// //&&(closeProfit>0.01*closeLot*ltSprad/Point)
// &&(pairFound)
// )
// {
// if (Prn1) Print("**************** Close B4B *********************");
// if (Prn1) Print(" profitBUY=",profitBUY," lossSELL=",lossSELL," profitSELL=",profitSELL," lossBUY=",lossBUY);
// //if (closeProfit>4*closeLot*ltSprad/Point)
// {//Если пары есть - закрываем
// //Закрываем прибыльный BUY на убыточный SELL
// if ((profitBUY>0.0001)&&(lossSELL<-0.0001)&&(profitBUY>=-lim*lossSELL))//прибыльный BUY - убыточный SELL
//// if ((profitBUY>0.0001)&&(lossSELL<-0.0001)&&(profitBUY>=-lim*lossSELL)&&(tsmiTrendAskNorm[9]>0))//прибыльный BUY - убыточный SELL - и убыток растет
//// if ((profitBUY>0.0001)&&(lossSELL<-0.0001)&&(profitBUY>=-lim*lossSELL)&&(tsmiTrendBidNorm[9]<0))//прибыльный BUY - убыточный SELL - и прибыль падает
// {
// Ord_inf=PositionSelect(nMProfitBUY,SELECT_BY_TICKET,MODE_TRADES);
// Ord_inf=OrderCloseBy(PositionGetInteger(POSITION_TICKET),nMLossSELL,clrForestGreen);
// if (Ord_inf)
// {
// B4BCloseOneN++;
// B4BRes=true;
// //if (Prn1)
//if (PrnB4BM) Print("************* B4BCloseM 7>>"," PAIR FOUND AND CLOSED!!!"," B4BRes=",B4BRes,
// " profitB=",profitBUY," lossS=",lossSELL," Ord_inf=",Ord_inf," B4BCloMN=",B4BCloseMN,
// " Fr=",AccountFreeMargin()," Eq=",AccountInfoDouble(ACCOUNT_EQUITY));//," MinEq=",MinEq);
// }
// BePair=false;//расчет окончен, всё что смогли - закрыли - 1 пару.
// }//if
// //Если все быстрые тренды по убытку BUY убыточные - убыток увеличивается
// //if ((TrendMB[0])&&(TrendMB[0]))//&&(!TrendMB[1])&&(TrendMB[2])&&(TrendMB[3]))//&&(!TrendCB[2]))
// //Закрываем прибыльный SELL на убыточный BUY
// if ((profitSELL>0.0001)&&(lossBUY<-0.0001)&&(profitSELL>=-lim*lossBUY))//прибыльный SELL - убыточный BUY
//// if ((profitSELL>0.0001)&&(lossBUY<-0.0001)&&(profitSELL>=-lim*lossBUY)&&(tsmiTrendBidNorm[9]<0))//прибыльный SELL - убыточный BUY - и убыток растет
//// if ((profitSELL>0.0001)&&(lossBUY<-0.0001)&&(profitSELL>=-lim*lossBUY)&&(tsmiTrendAskNorm[9]>0))//прибыльный SELL - убыточный BUY - и прибыль падает
// {
// Ord_inf=PositionSelect(nMProfitSELL,SELECT_BY_TICKET,MODE_TRADES);
// Ord_inf=OrderCloseBy(PositionGetInteger(POSITION_TICKET),nMLossBUY,clrForestGreen);
// if (Ord_inf)
// {
// B4BCloseOneN++;
// B4BRes=true;
// //if (Prn1)
//if (PrnB4BM) Print("************* B4BCloseM 8>>"," PAIR FOUND AND CLOSED!!!"," B4BRes=",B4BRes,
// " profitS=",profitSELL," lossB=",lossBUY," Ord_inf=",Ord_inf," B4BCloMN=",B4BCloseMN,
// " Fr=",AccountFreeMargin()," Eq=",AccountInfoDouble(ACCOUNT_EQUITY));//," MinEq=",MinEq);
// }
// //BePair=false;//расчет окончен, всё что смогли - закрыли - 1 пару.
// }//if
// //тогда Bepair=true и будет следующий расчет
// }
// }else{
// //Print("**************** BePair=false *********************");
// //Если нет пар - снимаем флаг продолжения
// BePair=false;//расчет окончен, всё что смогли - закрыли
// }
// }//end while - совсем While
//if ((PrnB4BM)&&(B4BRes!=true)) Print("************* B4BCloseM 9>>"," PAIR NOT FOUND!!!"," B4BRes=",B4BRes,
// " profitS=",profitSELL," lossB=",lossBUY," profitB=",profitBUY," lossS=",lossSELL," Ord_inf=",Ord_inf," B4BCloMN=",B4BCloseMN,
// " Fr=",AccountFreeMargin()," Eq=",AccountInfoDouble(ACCOUNT_EQUITY));//," MinEq=",MinEq);
// return(B4BRes);
//}//B4BCloseMA()
//
//======================================================================================================
// fOrderSend()
//
// Выход:
//
//======================================================================================================
//fOrderSend() - переписать добавить цикл с увеличением слипа
int fOrderSend( OP_TYPE OrdType,
double Ord_Vol,
int OrdSlippage,
int OrdStopLoss,
int OrdTakeProfit,
string OrdComment,
long OrdMagic,
int OrdExpir,
color Ord_Color,
ulong &rDeal){
//Print("fOrderSend>>");
//{if(!IsTradeTime2()){return(0);}},
{if(nOrdersOpen>=MaxOpenOrders){return(-5);}}//Превышено число ордеров
int OrdInfo=-1;//Ошибка открытия ордера
//int err=0;
int j=0;
int nRetry=5;
//-----
rDeal=0;
{switch (OrdType)
{
case OP_BUY:
{for (j=0;j<=nRetry-1;j++)
{
//RefreshRates();
{if(LongEnable)
{
OrdInfo=(int)PositionOrderSend(TheSymbol,(ENUM_ORDER_TYPE)OP_BUY,Ord_Vol,gAsk,OrdSlippage,PriceAddPoints(gBid,-OrdStopLoss),PriceAddPoints(gAsk,+OrdTakeProfit),OrdComment,OrdMagic,OrdExpir,rDeal);
//Print("rDeal>>",rDeal);
}}//if(LongEnable)
//err=GetLastError();
//{if (err == 0 /* NO_ERROR */ ){break;}}//for
//{if (!(( err == 4 /* SERVER_BUSY */
// || err == 137 /* BROKER_BUSY */
// || err == 134 /* NO MONEY */
// || err == 146 /* TRADE_CONTEXT_BUSY */
// || err == 136 /* OFF_QUOTES */ ))){break;}}//for
{if (
// (OrdInfo == 10008) /* TRADE_RETCODE_PLACED Ордер размещен */
//||
(OrdInfo == 10009) /* TRADE_RETCODE_DONE Заявка выполнена */
||
(OrdInfo == 10010) /* TRADE_RETCODE_DONE_PARTIAL Заявка выполнена частично */
)
{
break;//for
}else{
OrdInfo=-OrdInfo;
}}
Sleep(10);
}}//for (j=0;j<nRetry;j++)
break;//switch (OrdType)
case OP_SELL:
{for (j=0;j<=nRetry-1;j++)
{
//RefreshRates();
{if(ShortEnable)
{
OrdInfo=(int)PositionOrderSend(TheSymbol,(ENUM_ORDER_TYPE)OP_SELL,Ord_Vol,gBid,OrdSlippage,PriceAddPoints(gAsk,+OrdStopLoss),PriceAddPoints(gBid,-OrdTakeProfit),OrdComment,OrdMagic,OrdExpir,rDeal);
}}//if(ShortEnable)
//err=GetLastError();
//{if (err == 0 /* NO_ERROR */ ){break;}}//for
//{if (!(( err == 4 /* SERVER_BUSY */
// || err == 137 /* BROKER_BUSY */
// || err == 134 /* NO MONEY */
// || err == 146 /* TRADE_CONTEXT_BUSY */
// || err == 136 /* OFF_QUOTES */ ))){break;}}//for
{if (
// (OrdInfo == 10008) /* TRADE_RETCODE_PLACED Ордер размещен */
//||
(OrdInfo == 10009) /* TRADE_RETCODE_DONE Заявка выполнена */
||
(OrdInfo == 10010) /* TRADE_RETCODE_DONE_PARTIAL Заявка выполнена частично */
)
{
break;//for
}else{
OrdInfo=-OrdInfo;
}}
Sleep(10);
}}//for (j=0;j<nRetry;j++)
}}//switch (OrdType)
return(OrdInfo);
}//fOrderSend
//
//======================================================================================================
// fCloseBuySell() -
//======================================================================================================
int fCloseBuySell( string iSymbol,
bool bCloseBuy,
bool bCloseSell,
int iMagic,
double &iVirtualSL){
int
iResult=0;
ulong
Pos_Tick;
//-----
if(PositionsTotal()>0)
{for(int i=PositionsTotal()-1;i>=0;i--)
{
Pos_Tick=PositionGetTicket(i);
{if(Pos_Tick<=0){continue;}}//Неудачно - следующий
{if(!PositionSelectByTicket(Pos_Tick)){continue;}}//Выбираем позицию по тикету? Неудачно - следующий
{if(PositionGetString(POSITION_SYMBOL)!=iSymbol){continue;}}//Отбор по инструменту
{if(PositionGetInteger(POSITION_MAGIC)!=iMagic){continue;}}//Отбор по магику
//fCloseBuySell() переписать - добавить цикл с увеличением слипа
{if((PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)&&(bCloseBuy))
{
Ord_Int=-1;
//RefreshRates();
{if(true)//(!IsTradeContextBusy())
{
Ord_Int=mPositionClose2(iSymbol,Pos_Tick,SlipFixOrd,RepFixOrd,"fCloseBuySell(OP_BUY)");
{if((Ord_Int!=ERR_SUCCESS)&&(Ord_Int!=ERR_NO_MQLERROR))
// {if((Ord_inf!=ERR_SUCCESS)&&(Ord_inf!=ERR_NO_MQLERROR))
//{if((Ord_inf!=ERR_SUCCESS))
//{if(!OrderClose(PositionGetInteger(POSITION_TICKET),PositionGetDouble(POSITION_VOLUME),fNormalizeDouble(gBid),5,CLR_NONE))
{
Print("Error Closing BUY Trade "+string(PositionGetInteger(POSITION_TICKET)));
iResult=-1;
}}//if(!OrderClose(PositionGetInteger(POSITION_TICKET),PositionGetDouble(POSITION_VOLUME),fNormalizeDouble(gBid),5,CLR_NONE))
}else{
//if(tStopTimeBuy == iTime(NULL, 0, 0)) return (-2);
//tStopTimeBuy=iTime(NULL,0,0);
Print("Need Closing BUY Trade "+string(PositionGetInteger(POSITION_TICKET))+". Trade Context Busy");
return(-2);
}}//if(!IsTradeContextBusy())
}}//if(((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_BUY)&&(bCloseBuy))
{if((PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)&&(bCloseSell))
{
//RefreshRates();
{if(true)//(!IsTradeContextBusy())
{
Ord_Int=mPositionClose2(iSymbol,Pos_Tick,SlipFixOrd,RepFixOrd,"fCloseBuySell(OP_SELL)");
{if((Ord_Int==ERR_SUCCESS)||(Ord_Int==ERR_NO_MQLERROR)){continue;}}
//{if(OrderClose(PositionGetInteger(POSITION_TICKET),PositionGetDouble(POSITION_VOLUME),fNormalizeDouble(gAsk),5,CLR_NONE)){continue;}}
Print("Error Closing SELL Trade : "+string(PositionGetInteger(POSITION_TICKET)));
iResult=-1;
continue;
}}//if(!IsTradeContextBusy())
//if(tStopTimeSell == iTime(NULL, 0, 0)) return (-2);
////tStopTimeSell=iTime(NULL,0,0);
Print("Need to close SELL trade : "+string(PositionGetInteger(POSITION_TICKET))+". Trade Context Busy");
return(-2);
}}//if(((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)&&(bCloseSell))
}}//for(int n=PositionsTotal()-1;n>=0;n--)
iVirtualSL=0;
return(iResult);
}//fCloseBuySell
//
//======================================================================================================
// NormalizeVSL()
//======================================================================================================
void NormalizeVSL( string iSymbol,
OP_TYPE iType,
int iMagic,
double &iVirtualSL,
double iPosPrice)
{
//-----
double Comis=(PositionGetDouble(POSITION_VOLUME)*CalcAddCommPrice(iSymbol,AccSrv)+CalcGridSwap(iSymbol,iMagic))
/SymbolTradeTickValue;
{if(iType==OP_ALL)
{
iVirtualSL=0.0;
}}//if(iType==OP_ALL)
{if(iType==OP_BUY)
{
{if(iVirtualSL>0.0)
{
{if(iVirtualSL<iPosPrice)
{
{if(gBid>iPosPrice+MathMax(Comis,SymbolInfoInteger(iSymbol,SYMBOL_TRADE_STOPS_LEVEL))*_Point)
{
iVirtualSL=iPosPrice+MathMax(Comis,SymbolInfoInteger(iSymbol,SYMBOL_TRADE_STOPS_LEVEL))*_Point;
}else{
{if(gBid<=iPosPrice+_Point)
{
//iVirtualSL=iPosPrice+_Point;
iVirtualSL=0.0;
}}//if(gBid<=iPosPrice+_Point)
}}//if(gBid>iPosPrice+_Point)
}}//if(iVirtualSL<iPosPrice)
}}//if(iVirtualSL>0.0)
}}//if(iType==OP_BUY)
{if(iType==OP_SELL)
{
{if(iVirtualSL>0.0)
{
{if(iVirtualSL>iPosPrice)
{
{if(gAsk<iPosPrice-MathMax(Comis,SymbolInfoInteger(iSymbol,SYMBOL_TRADE_STOPS_LEVEL))*_Point)
{
iVirtualSL=iPosPrice-MathMax(Comis,SymbolInfoInteger(iSymbol,SYMBOL_TRADE_STOPS_LEVEL))*_Point;
}else{
{if(gAsk>=iPosPrice-_Point)
{
//iVirtualSL=iPosPrice+_Point;
iVirtualSL=0.0;
}}//if(gAsk>=iPosPrice-_Point)
}}//if(gAsk<iPosPrice-_Point)
}}//if(iVirtualSL>iPosPrice)
}}//if(iVirtualSL>0.0)
}}//if(iType==OP_SELL)
}//NormalizeVSL()
//
//======================================================================================================
// NormalizeSL()
//======================================================================================================
void NormalizeSL( string iSymbol,
OP_TYPE iType,
int iMagic,
double iPosPrice){
double
NewStopLoss=0;
//Комиссия + своп в пунктах
double Comis=(PositionGetDouble(POSITION_VOLUME)*CalcAddCommPrice(iSymbol,AccSrv)+CalcGridSwap(iSymbol,iMagic))
/SymbolTradeTickValue;
//-----
{if(PositionsTotal()>0)
{
{for (int i=PositionsTotal()-1;i>=0;i--)
{
ulong Pos_Tick=PositionGetTicket(i);
{if(Pos_Tick<=0){continue;}}//Неудачно - следующий
{if(!PositionSelectByTicket(Pos_Tick)){continue;}}//Выбираем позицию по тикету? Неудачно - следующий
{if(PositionGetString(POSITION_SYMBOL)!=iSymbol){continue;}}//Отбор по инструменту
{if(PositionGetInteger(POSITION_MAGIC)!=iMagic){continue;}}//Отбор по магику
double OrdStopLoss=PositionGetDouble(POSITION_SL);
{if(OrdStopLoss==0){continue;}}
{if((PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)&&((iType==OP_ALL)||(iType==OP_BUY)))
{
{if(OrdStopLoss<iPosPrice)
{
{if(gBid>iPosPrice+MathMax(Comis,SymbolInfoInteger(iSymbol,SYMBOL_TRADE_STOPS_LEVEL))*_Point)
{
NewStopLoss=NormalizeDouble(iPosPrice+MathMax(Comis,SymbolInfoInteger(iSymbol,SYMBOL_TRADE_STOPS_LEVEL))*_Point,_Digits);
}else{
NewStopLoss=0;
}}//if(gBid>=PosPrice+SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point)
Ord_Inf=PositionModifySL(Pos_Tick,NewStopLoss,0.0);
}}//if(OrdStopLoss<=PosPrice)
}}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_BUY)
{if((PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)&&((iType==OP_ALL)||(iType==OP_SELL)))
{
{if(OrdStopLoss>iPosPrice)
{
{if(gAsk<iPosPrice-MathMax(Comis,SymbolInfoInteger(iSymbol,SYMBOL_TRADE_STOPS_LEVEL))*_Point)
{
NewStopLoss=NormalizeDouble(iPosPrice-MathMax(Comis,SymbolInfoInteger(iSymbol,SYMBOL_TRADE_STOPS_LEVEL))*_Point,_Digits);
}else{
NewStopLoss=0;
}}//if(gBid>=PosPrice+SymbolInfoInteger(TheSymbol,SYMBOL_TRADE_STOPS_LEVEL)*_Point)
Ord_Inf=PositionModifySL(Pos_Tick,NewStopLoss,0.0);
}}//if(NewStopLoss>=PosPrice)
}}//if ((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)
Sleep(10);
}}//for (int n=PositionsTotal()-1;n>=0;n--)
}}//if
}//NormalizeSL()
//
//======================================================================================================
// ReadEventsToDay() - читаем из файла массив событий текущего дня, устанавливаем
// iLastReadDayBegin на начало текущего дня.
// Вход:
// iSymbol - фининструмент
// VolatLimit - минимальный уровень события
// iInvesting - использовать индексы от Investing.com
// iOffsetTime - смещение времени (для телетрейд -3600 (UTC+2), остальные скачиваются UTC+3)
// Выход:
// iLastReadDayBegin - время начала последнего прочитанного дня (устанавливается на начало дня прочтения новостей)
// iEvents - массив событий дня
// iNEvents - количество событий дня
//======================================================================================================
bool ReadEventsToDay( string iSymbol,
string iFileName,
int VolatLimit,
bool iInvesting,
datetime iOffsetTime,
datetime &iLastReadDayBegin,
News &iEvents[],
int &iNEvents,
bool iFileCommon)
{
string
StringBuff,
iCurrencyN,iEventN,iCountryN,
Symbol_1=StringSubstr(iSymbol,0,3),
Symbol_2=StringSubstr(iSymbol,3,3);
datetime
iTimeN;
int
iVolatilityN;
bool
Done=true;
//-----
datetime ThisDayBegin=DateTimeDayBegin(Time_Current);//не UTC
datetime NextDayBegin=ThisDayBegin+24*60*60;//не UTC
//-----
ResetLastError();
int InFileHandle=INVALID_HANDLE;
{if(iFileCommon)
{
InFileHandle=FileOpen(iFileName,FILE_READ|FILE_TXT|FILE_SHARE_READ|FILE_COMMON,';');
}else{
InFileHandle=FileOpen(iFileName,FILE_READ|FILE_TXT|FILE_SHARE_READ,';');
}}//if(iFileCommon)
//Print("ReadEventsToDay >>InFileHandle=",InFileHandle);
{if((InFileHandle==INVALID_HANDLE)||(FileSize(InFileHandle)==0))
{
Print("ReadEventsToDay Error Open File >> "+iFileName);
iLastReadDayBegin=0;
Done=false;
return(false);
}else{
//Очистка списка событий
{for(int j=0;j<100;j++)
{
Events[j].TimeN=0;
Events[j].CurrencyN="";
Events[j].VolatilityN=0;
Events[j].EventN="";
Events[j].CountryN="";
Events[j].MaxVolBeN=false;
Events[j].CompositeStringN="";
}}//for(int j=0;j<100;j++)
//Цикл чтения строк из файла
int i=0;
{while(!FileIsEnding(InFileHandle))
{
StringBuff=FileReadString(InFileHandle);
//Print("StringBuff=",StringBuff);
//StringParse(StringBuff,iEvents[i].TimeN,iEvents[i].CurrencyN,iEvents[i].VolatilityN);
StringParse(StringBuff,iTimeN,iCurrencyN,iVolatilityN,iEventN,iCountryN);
//Print("ThisDayBeginU=",ThisDayBegin," NextDayBegin=",NextDayBegin," iTimeN=",iTimeN," iCurrencyN=",iCurrencyN," iVolatilityN=",iVolatilityN);
iTimeN=iTimeN+iOffsetTime;
{if( (true)
&&((iInvesting)||(StringFind(iEventN,"Investing.com")<0))//Выкусываем индексы от Investing.com к чертям собачьим
&&(iTimeN>=ThisDayBegin)&&(iTimeN<NextDayBegin)//не UTC
&&(
(
(
(iCurrencyN==Symbol_1)//Валюта новости есть в инструменте как валюта котирования
||
(iCurrencyN==Symbol_2)//Валюта новости есть в инструменте как базовая валюта
)
&&
(iVolatilityN>=VolatLimit)
)
||
((iCurrencyN=="USD")&&(iVolatilityN>=2))//... или это доллар с максимальной волатильностью
||
((iCurrencyN=="EUR")&&(iVolatilityN>=2))//... или это евро с максимальной волатильностью
||
((iCurrencyN=="JPY")&&(iVolatilityN>=2))//... или это йена с максимальной волатильностью
||
((iCurrencyN=="GBP")&&(iVolatilityN>=3))//... или это фунт с максимальной волатильностью
||
((iCurrencyN=="CHF")&&(iVolatilityN>=3))//... или это франк с максимальной волатильностью
||
((iCurrencyN=="AUD")&&(iVolatilityN>=3))//... или это оззи с максимальной волатильностью
||
((iCurrencyN=="NSD")&&(iVolatilityN>=3))//... или это киви с максимальной волатильностью
||
((iCurrencyN=="CAD")&&(iVolatilityN>=3))//... или это кабель с максимальной волатильностью
)
)
{
//Print("************ iTimeN=",iTimeN,"ThisDayBegin=",ThisDayBegin," NextDayBegin=",NextDayBegin," iCurrencyN=",iCurrencyN," iVolatilityN=",iVolatilityN);
//Print("StringBuff=",StringBuff);
iEvents[i].TimeN=iTimeN;
iEvents[i].CurrencyN=iCurrencyN;
iEvents[i].VolatilityN=iVolatilityN;
iEvents[i].EventN=iEventN;
iEvents[i].CountryN=iCountryN;
i++;
}}//if((iTimeN>=ThisDayBegin)&&(iTimeN<NextDayBegin))
}}//while(!FileIsEnding(InFileHandle))
FileClose(InFileHandle);
{if(i>=1){Print("ReadEventsToDay Close File >> "+iFileName+" read="+IntegerToString(i)," InFileHandle=",InFileHandle);}}
//ExpertRemove();
{if(i>=1)//Найдены записи текущего дня
{
iLastReadDayBegin=ThisDayBegin;
iNEvents=i;
Done=true;
}else{//Записи текущего дня не найдены
iLastReadDayBegin=NextDayBegin;
iNEvents=0;
Done=false;
return(false);
}}//if(i>=1)
}}//if ((InFileHandle!=INVALID_HANDLE)&&(FileSize(InFileHandle)!=0))
//Заполнение признака максимальной волатильности при очередном времени и сводной строки
{if(Done)
{
datetime TimeOldN=0;
int MaxVolN=0;
string CompositeString="";
int MaxTimeRecord=-1;//Номер записи с максимальной волатильностью внутри времени, и флаг обнаружения максимальной записи (>=0)
{for(int j=0;j<iNEvents;j++)//
{
{if(Events[j].TimeN>TimeOldN)//Наступило новое время
{
//----- Обработка завершения предыдущего времени (Не забыть проделать то же на последнем активном элементе iNEvents-1 массива новостей)
{if(MaxTimeRecord>=0)//Если максимальная волатильность была обнаружена
{
Events[MaxTimeRecord].MaxVolBeN=true;//Помечаем первый элемент с максимальной волатильностью в закрытом времени
Events[MaxTimeRecord].CompositeStringN=CompositeString;//Заносим в элемент накопленную строку
CompositeString="";
}}//if(MaxTimeRecord>=0)
//----- Начальные процедуры нового времени
CompositeString=Events[j].EventN;//начальное значение накопительной строки
MaxVolN=Events[j].VolatilityN;//новое значение для максимума волатильности
MaxTimeRecord=j;//Первую запись считаем максимальной по волатильности
//Запомним время для сравнения
TimeOldN=Events[j].TimeN;
//----- Обработка завершения времени на последнем активном элементе iNEvents-1 массива новостей
{if(j==(iNEvents-1))//Последний элемент
{
Events[MaxTimeRecord].MaxVolBeN=true;//Помечаем первый элемент с максимальной волатильностью в закрытом времени
Events[MaxTimeRecord].CompositeStringN=CompositeString;//Заносим в элемент накопленную строку
CompositeString="";
}}//if(j==iNEvents)
}else{//Время не изменилось
//----- Обработка по значению волатильности
{if(Events[j].VolatilityN>MaxVolN)//Новый максимум
{
CompositeString=Events[j].EventN;//начальное значение накопительной строки
MaxVolN=Events[j].VolatilityN;//Значение максимума для волатильности
MaxTimeRecord=j;//запомним позицию первого элемента с максимумом
}else{//Не новый максимум по волатильности
{if(Events[j].VolatilityN==MaxVolN)//Событие с волатильностью по максимуму
{
CompositeString=CompositeString+"* "+Events[j].EventN;//Наращивание накопительной строки
}}//if(Events[j].VolatilityN=MaxVolN)
}}//if(Events[j].VolatilityN>MaxVolN)
//----- Обработка завершения времени на последнем активном элементе iNEvents-1 массива новостей
{if(j==(iNEvents-1))//Последний элемент
{
Events[MaxTimeRecord].MaxVolBeN=true;//Помечаем первый элемент с максимальной волатильностью в закрытом времени
Events[MaxTimeRecord].CompositeStringN=CompositeString;//Заносим в элемент накопленную строку
}}//if(j==iNEvents)
}}//{if(Events[j].TimeN>TimeOldN)
}}//for(int j=0;j<100;j++)
//{for(int j=0;j<iNEvents;j++)//
//{
// {if(Events[j].MaxVolBeN)
// {
// Events[j].CompositeStringN=TimeToString(Events[j].TimeN)+" "+VolatilityName[Events[j].VolatilityN]+" "+Events[j].CompositeStringN;
// //Print("CompositeStringN=",Events[j].CompositeStringN);
// }}//if(Events[j].MaxVolBeN)
//}}//for(int j=0;j<iNEvents;j++)
}else{
//Очистка списка событий
{for(int j=0;j<100;j++)
{
Events[j].TimeN=0;
Events[j].CurrencyN="";
Events[j].VolatilityN=0;
Events[j].EventN="";
Events[j].CountryN="";
Events[j].MaxVolBeN=false;
Events[j].CompositeStringN="";
}}//for(int j=0;j<100;j++)
}}//if(Done)
return(true);
}//ReadEventsToDay()
//
//======================================================================================================
// ReadEventsWeeks() - читаем из файла массив событий текущей недели, устанавливаем
// iLastReadDayBegin на начало текущего дня.
// Вход:
// iSymbol - фининструмент
// VolatLimit - минимальный уровень события
// iInvesting - использовать индексы от Investing.com
// iTimeCurrent - Текущее серверное время по последнему тику
// iOffsetTime - смещение времени (для телетрейд -3600 (UTC+2(+3)), остальные скачиваются UTC+3(+4))
// Выход:
// iLastReadDayBegin - время начала последней прочитанной недели (устанавливается на начало дня прочтения новостей)
// iEvents - массив событий недели
// iNEvents - количество событий недели
//======================================================================================================
bool ReadEventsWeeks( string iSymbol,
string iFileName,
int iVolatLimit,
bool iInvesting,
datetime iTimeCurrent, //Текущее серверное время по последнему тику
datetime iOffsetTime,
datetime &iLastReadWeekBegin,
News &iEvents[],
int &iNEvents,
bool iFileCommon)
{
string
StringBuff,
iCurrencyN,iEventN,iCountryN,
Symbol_1=StringSubstr(iSymbol,0,3),
Symbol_2=StringSubstr(iSymbol,3,3);
//{if(())Тут добавить обработку биржевых инструментов и разных фьючерсов
//{
//}}//
datetime
iTimeN;
int
iVolatilityN;
bool
Done=true;
//----- Рассчет границ недели - учесть оффсет? вроде не надо
datetime ThisWeekBegin=DateTimeWeekBegin(iTimeCurrent); //начало текущей недели в текущем серверном времени (UTC+2(+3))
datetime NextWeekBegin=ThisWeekBegin+8*24*60*60; //начало следующей недели в текущем серверном времени (UTC+2(+3))
//Print("ThisWeekBegin=",ThisWeekBegin," NextWeekBegin=",NextWeekBegin);
//-----
ResetLastError();
int InFileHandle=INVALID_HANDLE;
//Получение хендла файла новостей с учётом места расположения файла
{if(iFileCommon)
{
InFileHandle=FileOpen(iFileName,FILE_READ|FILE_TXT|FILE_ANSI|FILE_COMMON,';');
}else{
InFileHandle=FileOpen(iFileName,FILE_READ|FILE_TXT|FILE_ANSI,';');
}}//if(iFileCommon)
//Print("ReadEventsWeeks >>InFileHandle=",InFileHandle);
{if((InFileHandle==INVALID_HANDLE)||(FileSize(InFileHandle)==0))
{
Print("ReadEventsWeeks Error Open File >> "+iFileName);
iLastReadWeekBegin=0;
Done=false;
return(false);
}else{
//Очистка списка событий
{for(int j=0;j<100;j++)
{
Events[j].TimeN=0;
Events[j].CurrencyN="";
Events[j].VolatilityN=0;
Events[j].EventN="";
Events[j].CountryN="";
Events[j].MaxVolBeN=false;
Events[j].CompositeStringN="";
}}//for(int j=0;j<100;j++)
//Цикл чтения строк из файла
int i=0;
{while((!FileIsEnding(InFileHandle))&&(i<EventsListSize))//Пока не конец файла и массив не переполнен
{
StringBuff=FileReadString(InFileHandle);//Считываем строку
//Print("StringBuff=",StringBuff);
//StringParse(StringBuff,iEvents[i].TimeN,iEvents[i].CurrencyN,iEvents[i].VolatilityN);
StringParse(StringBuff,iTimeN,iCurrencyN,iVolatilityN,iEventN,iCountryN);//Синтаксический разбор строки на значения
//Print("ThisWeekBegin=",ThisWeekBegin," NextWeekBegin=",NextWeekBegin,
// " iTimeN=",iTimeN," iCurrencyN=",iCurrencyN," iVolatilityN=",iVolatilityN," iEventN=",iEventN);
//Корректировка по смещению. В файле всегда (UTC+2), что обычно совпадает зимой с серверным временем (на телетрейд-корректировка -3600 сек)
//летом серверное обычно (UTC+3). Например новость по (UTC+2) выходит в [2017.06.15 12:00] что хранится в файле.
//на сервере (UTC+3) в это время [2017.06.15 13:00] и если использовать время из файла, то выстрелим раньше на час.
//Поэтому ко времени новости в файле добавляем смещение (+1) летом северное полушарие.
iTimeN=iTimeN+iOffsetTime;
{if(
((iInvesting)||(StringFind(iEventN,"Investing.com")<0))//Выкусываем индексы от Investing.com к чертям собачьим
&&(iTimeN>=ThisWeekBegin)&&(iTimeN<NextWeekBegin)//Тут уже по скорректированному (серверному) времени
&&(
(
(
(iCurrencyN==Symbol_1)//Валюта новости есть в инструменте как валюта котирования
||
(iCurrencyN==Symbol_2)//Валюта новости есть в инструменте как базовая валюта
//тут можно добавить для биржи и всякого прочего
)
&&
(iVolatilityN>=iVolatLimit)
)
||
//Новости по доллару, евро и йене как очень сильно влияющие используем всегда от важности 2
((iCurrencyN=="USD")&&(iVolatilityN>=MathMax(2,exVolatLimit)))//... или это доллар с максимальной волатильностью
||
((iCurrencyN=="EUR")&&(iVolatilityN>=MathMax(2,exVolatLimit)))//... или это евро с максимальной волатильностью
||
((iCurrencyN=="JPY")&&(iVolatilityN>=MathMax(2,exVolatLimit)))//... или это йена с максимальной волатильностью
||
//Новости по фунту, франку, оззи, киви, каблю как сильно влияющие используем всегда от важности 3
((iCurrencyN=="GBP")&&(iVolatilityN>=3))//... или это фунт с максимальной волатильностью
||
((iCurrencyN=="CHF")&&(iVolatilityN>=3))//... или это франк с максимальной волатильностью
||
((iCurrencyN=="AUD")&&(iVolatilityN>=3))//... или это оззи с максимальной волатильностью
||
((iCurrencyN=="NSD")&&(iVolatilityN>=3))//... или это киви с максимальной волатильностью
||
((iCurrencyN=="CAD")&&(iVolatilityN>=3))//... или это кабель с максимальной волатильностью
)
)
{
//Print("*** iTimeN=",iTimeN,"ThisWeekBegin=",ThisWeekBegin," NextWeekBegin=",NextWeekBegin,
// " iCurrencyN=",iCurrencyN," iVolatilityN=",iVolatilityN," iEventN=",iEventN);
//Print("StringBuff=",StringBuff);
//Заносим разобранную строку в массив событий
iEvents[i].TimeN=iTimeN;
iEvents[i].CurrencyN=iCurrencyN;
iEvents[i].VolatilityN=iVolatilityN;
iEvents[i].EventN=iEventN;
iEvents[i].CountryN=iCountryN;
i++;
}}//if((iTimeN>=ThisDayBegin)&&(iTimeN<NextDayBegin))
}}//while(!FileIsEnding(InFileHandle))
FileClose(InFileHandle);
{if(i>=EventsListSize){Print("ReadEventsWeeks ERROR >> Размер массива событий ",EventsListSize," недостаточен.");}}
//ExpertRemove();
{if(i>=1)//Найдены записи текущей недели
{
iLastReadWeekBegin=ThisWeekBegin;
iNEvents=i;//Количество найденных событий
Print("ReadEventsWeeks Close File >> ",iFileName," FileHandle=",InFileHandle," Записи текущей недели =",iNEvents);
Done=true;
}else{//Записи текущей недели не найдены
Print("ReadEventsWeeks ERROR >> Записи текущей недели не найдены.");
iLastReadWeekBegin=NextWeekBegin;
iNEvents=0;//Обнулим количество найденных событий
Done=false;
return(false);
}}//if(i>=1)
}}//if((InFileHandle!=INVALID_HANDLE)&&(FileSize(InFileHandle)!=0))
ZeroMemory(InFileHandle);
//Заполнение признака максимальной волатильности при очередном времени и сводной строки
{if(Done)
{
datetime TimeOldN=0;
int MaxVolN=0;
string CompositeString="";//Сводная строка
int MaxTimeRecord=-1;//Номер записи с максимальной волатильностью внутри времени, и флаг обнаружения максимальной записи (>=0)
{for(int j=0;j<iNEvents;j++)//Перебираем всё количество найденных событий
{
{if(Events[j].TimeN>TimeOldN)//Наступило новое время
{
//----- Обработка завершения предыдущего времени (Не забыть проделать то же на последнем активном элементе iNEvents-1 массива новостей)
{if(MaxTimeRecord>=0)//Если максимальная волатильность была обнаружена
{
Events[MaxTimeRecord].MaxVolBeN=true;//Помечаем первый элемент с максимальной волатильностью в закрытом времени
Events[MaxTimeRecord].CompositeStringN=CompositeString;//Заносим в элемент накопленную сводную строку
CompositeString="";//Очищаем сводную строку
}}//if(MaxTimeRecord>=0)
//----- Начальные процедуры нового времени
CompositeString=Events[j].EventN;//начальное значение накопительной строки
MaxVolN=Events[j].VolatilityN;//новое значение для максимума волатильности
MaxTimeRecord=j;//Первую запись считаем максимальной по волатильности
//Запомним время для сравнения
TimeOldN=Events[j].TimeN;
//----- Обработка завершения времени на последнем активном элементе iNEvents-1 массива новостей
{if(j==(iNEvents-1))//Последний элемент
{
Events[MaxTimeRecord].MaxVolBeN=true;//Помечаем первый элемент с максимальной волатильностью в закрытом времени
Events[MaxTimeRecord].CompositeStringN=CompositeString;//Заносим в элемент накопленную сводную строку
CompositeString="";//Очищаем сводную строку
}}//if(j==iNEvents)
}else{//Время не изменилось
//----- Обработка по значению волатильности
{if(Events[j].VolatilityN>MaxVolN)//Новый максимум
{
CompositeString=Events[j].EventN;//начальное значение накопительной строки
MaxVolN=Events[j].VolatilityN;//Значение максимума для волатильности
MaxTimeRecord=j;//запомним позицию первого элемента с максимумом
}else{//Не новый максимум по волатильности
{if(Events[j].VolatilityN==MaxVolN)//Событие с волатильностью по максимуму
{
CompositeString=CompositeString+"* "+Events[j].EventN;//Наращивание накопительной строки
}}//if(Events[j].VolatilityN=MaxVolN)
}}//if(Events[j].VolatilityN>MaxVolN)
//----- Обработка завершения времени на последнем активном элементе iNEvents-1 массива новостей
{if(j==(iNEvents-1))//Последний элемент
{
Events[MaxTimeRecord].MaxVolBeN=true;//Помечаем первый элемент с максимальной волатильностью в закрытом времени
Events[MaxTimeRecord].CompositeStringN=CompositeString;//Заносим в элемент накопленную строку
}}//if(j==iNEvents)
}}//{if(Events[j].TimeN>TimeOldN)
}}//for(int j=0;j<EventsListSize;j++)
//Контрольный вывод
{for(int j=0;j<iNEvents;j++)//
{
{if(Events[j].MaxVolBeN)
{
Events[j].CompositeStringN=TimeToString(Events[j].TimeN)+" "+VolatilityName[Events[j].VolatilityN]+" "+Events[j].CompositeStringN;
//Print("CompositeStringN=",Events[j].CompositeStringN);
}}//if(Events[j].MaxVolBeN)
}}//for(int j=0;j<iNEvents;j++)
}else{
//Очистка списка событий
{for(int j=0;j<EventsListSize;j++)
{
Events[j].TimeN=0;
Events[j].CurrencyN="";
Events[j].VolatilityN=0;
Events[j].EventN="";
Events[j].CountryN="";
Events[j].MaxVolBeN=false;
Events[j].CompositeStringN="";
}}//for(int j=0;j<EventsListSize;j++)
}}//if(Done)
return(true);
}//ReadEventsToDay()
//
//======================================================================================================
// mPositionClose2();//v66.112-v71.163.003 - закрытие ордера
// OrTic - тикет ордера
// OrSli - допустимое проскальзывание
// mRet - допустимое количество попыток закрытия
// comm - наименование инициатора закрытия для протокола
//======================================================================================================
int mPositionClose2( string iSymbol,
ulong OrTic,
int OrSli,
int mRet,
string comm){
bool
mRes=true;
int
mErr=-1; //за пределом кодов ошибок
ResetLastError();
{if(!PositionSelectByTicket(OrTic)) //Если невозможно выбрать позицию - сваливаем с кодом ошибки
{
mErr=GetLastError();
return(mErr);
}}//if (!Ord_inf)
{if(!CloseEnable)
{
{if(PrnClose){Print("#",OrTic,">> CLOSE DISABLE ERROR IN MORDERCLOSE> "," OrderSymbol()=",PositionGetString(POSITION_SYMBOL)," TheSymbol=",iSymbol);}}
return(1995);
}else{
{if(PrnClose){Print("#",OrTic,">> CLOSE ENABLE NO ERROR IN MORDERCLOSE> "," OrderSymbol()=",PositionGetString(POSITION_SYMBOL)," TheSymbol=",iSymbol);}}
}}//if(!CloseEnable)
{if(PositionGetString(POSITION_SYMBOL)!=iSymbol)
{
if(PrnClose) Print("#",OrTic,">> SYMBOL ERROR IN MORDERCLOSE> "," PositionGetString(POSITION_SYMBOL)=",PositionGetString(POSITION_SYMBOL)," iSymbol=",iSymbol);
return(1999);
}else{
if(PrnClose) Print("#",OrTic,">> SYMBOL NO ERROR IN MORDERCLOSE> "," PositionGetString(POSITION_SYMBOL)=",PositionGetString(POSITION_SYMBOL)," iSymbol=",iSymbol);
}}//if(PositionGetString(POSITION_SYMBOL)!=iSymbol)
//========== Неприкасаемые ордера не закрываем!!!
//if (((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_SELL)&&(MathAbs(PositionGetDouble(POSITION_SL)-_Point)<0.5*_Point)) {return(mErr);}
//if (((OP_TYPE)PositionGetInteger(POSITION_TYPE)==OP_BUY)&&(MathAbs(PositionGetDouble(POSITION_SL)-_Point)<0.5*_Point)) {return(mErr);}
//=================================================
////if(PrnClose) Print("#",OrTic," 1 >> CLOSE from:",comm,
//// " Type=",(((OP_TYPE)PositionGetInteger(POSITION_TYPE)==0)?("BUY"):("SELL")),
//// " Lots=",PositionGetDouble(POSITION_VOLUME),
//// " Vol=",OrVol,
//// " Prc=",OrPrc,
//// " Prof=",DoubleToString(CalcOrdersProfit(AllType,PositionGetInteger(POSITION_TICKET),CheckMagicOn),2),
//// " Spr=",DoubleToString(ltSprad,_Digits));
////if(PrnClose) Print("#",OrTic," 2 >> OrdTotal=",PositionsTotal(),
//// " OrdOpTim=",OrderOpenTime(),"/",TimeToString(OrderOpenTime()),
//// //" OrdExpir=",OrderExpiration()-1600000000,"/",TimeToString(OrderExpiration()),
//// " TimCurr=",IntegerToString(TimeCurrent()),"/",TimeCurrent());
{while (
(mErr!=ERR_NO_MQLERROR)&&(mErr!=ERR_SUCCESS)
&&(mRet>0)
)
{
//{if(IsTradeContextBusy()){break;}}//Торговый поток занят - ожидание
if(PrnClose) Print("mPositionClose2 in while, from [",comm,"] Close TRY >>"," mErr=",mErr," mRet=",mRet," OrTic=",OrTic," OrSli=",OrSli);
ResetLastError();
{if (!PositionSelectByTicket(OrTic))
{
mErr=GetLastError();
//Print("mPositionClose2 SELECT ERROR IN WHILE> ","ERR:"+IntegerToString(mErr));
break;
}else{
mErr=GetLastError();
//Print("mPositionClose2 SELECT NO ERROR IN WHILE> ","ERR:"+IntegerToString(mErr));
}}//if (!Ord_inf)
ResetLastError();
////{if ((!MQLInfoInteger(MQL_TESTER))&&((-CalcOrdersProfit(AllType,PositionGetInteger(POSITION_TICKET),CheckMagicOn))>=CloseLossQLimit))//Если закрываем большой убыток
////{
//// {if (MessageBox("Close "+DoubleToString(CalcOrdersProfit(AllType,PositionGetInteger(POSITION_TICKET),CheckMagicOn),2)+"$ ?","*** BIG LOSS ORDER CLOSE ***",MB_YESNO+MB_ICONSTOP)==IDYES)
//// {
//// mRes=OrderClose(OrTic,NormalizeDouble(OrVol,f_N_Sign(SymbolInfoInteger(TheSymbol,SUMBOL_VOLUME_STEP))),NormalizeDouble(OrPrc,_Digits),OrSli,OrCol);//_Digits
//// }else{
//// mRes=false;
//// }}//if (MessageBox("Close
////}else{//тестирование или небольшой убыток
mRes=PositionCloseOne(OrTic,OrSli);//
////}}//if ((!MQLInfoInteger(MQL_TESTER))&&(CalcOrdersProfit
mErr=GetLastError();
{if (mRes)
{
//mErr=ERR_NO_MQLERROR;
if(PrnClose) Print("mPositionClose2 CLOSE NO ERROR IN WHILE> ","ERR:"+IntegerToString(mErr));
break;
}else{
if(PrnClose) Print("mPositionClose2 CLOSE ERROR IN WHILE> ","ERR:"+IntegerToString(mErr));
}}//if (mRes)
OrSli++;
mRet--;
}}//while ((mErr!=ERR_NO_MQLERROR)&&(mRet>=0)))
if (PrnClose) Print("mPositionClose2 CLOSE END> ",((mRes)?("NO_ERROR:"+IntegerToString(mErr)):("ERROR:"+IntegerToString(mErr))));
return(mErr);
}//mPositionClose2()
//
//======================================================================================================
// CalendarRequest() - Download CBOE page source code in a text variable
// Вх:
// iReqTimeOut - таймаут запроса к сайту
// iInFailName - файл для сохранения результата запроса
// Вых: - bool результат операции
// iOutString - строка с результатом запроса
//======================================================================================================
int CalendarRequest( int iReqTimeOut,
string iInFailName,
string &iOutString){
string
cookie=NULL,headers;
char
post[],
result[];
int
ErrCode,
res;
int
RetResult=0;
//--- to work with the server, you must add the URL "https://www.google.com/finance"
//--- the list of allowed URL (Main menu-> Tools-> Settings tab "Advisors"):
////string google_url=
//// "http://ec.forexprostools.com/?"columns=exc_currency,exc_importance&importance=1,2,3&calType=week&timeZone=15&lang=1";
iOutString="";
string google_url=
"https://sslecal2.forexprostools.com/?"+//"http://ec.forexprostools.com/?"+//
"columns=exc_flags,exc_currency,exc_importance,exc_actual,exc_forecast,exc_previous"+
//"&category=_employment,_economicActivity,_inflation,_credit,_centralBanks,_confidenceIndex,_balance,_Bonds"+
"&importance=1,2,3"+
//"&features=timezone"+
//"&features=datepicker,timezone"+
"&countries=4,5,6,9,10,11,12,14,17,22,23,24,25,26,27,29,32,33,34,35,36,37,38,39,41,42,43,45,46,48,54,56,72,110"+
"&calType=week"+//week
//"&timeZone=7"+//17 - GMT+3 Иерусалим
"&lang=1";
/*
!!!ВНИМАНИЕ!!! Скачивается всегда в UTC+0
<iframe src="http://ec.forexprostools.com?
columns=exc_flags,exc_currency,exc_importance,exc_actual,exc_forecast,exc_previous&amp;
category=_employment,_economicActivity,_inflation,_credit,_centralBanks,_confidenceIndex,_balance,_Bonds&amp;
importance=1,2,3&amp;
features=datepicker,timezone&amp;
countries=4,5,6,9,10,11,12,14,17,22,23,24,25,26,27,29,32,33,34,35,36,37,38,39,41,42,43,45,46,48,54,56,72,110&amp;
countries=25,32,6,37,72,22,17,39,14,10,35,43,56,36,110,11,26,12,4,5&amp;
Список стран
(4-GBP|5-USD|6-CAD|7-MXN|9-SEK|10-ITL|11-KRW|12-CHF|14-INR|17-GER|21-NET|22-FRN|23-ILS|24-DKK|25-AUD|26-SPA|27-CLP|29-ARS|32-BRL|33-IRE|34-BEL|35-JPY|36-SGD|37-CNY|38-POR|39-HKD)
(41-THB|42-MYR|43-NZD|45-PHP|46-TWD|48-IDR|51-GRE|53-PLN|54-AUS|55-CZK|56-RUB|72-EUR|110-ZAR)
-->
<!-- Вид календаря (week/day - неделя/день) -->
<!-- Временная зона лето северное полушарие
(7 - GMT-5 Central Time USA)(8 - GMT-4 Eastern Time USA)
(14 - GMT+0 Азорские о-ва)(55 - GMT)(15 - GMT+1 Лондон)(16 - GMT+2 Амстердам)(17 - GMT+3 Иерусалим)(18 - GMT+3 Москва) -->
<!-- Язык (1-English|7-Russian) -->
calType=week&amp;
timeZone=18&amp;
lang=1"
width="610"
height="9999"
frameborder="0"
allowtransparency="true"
marginwidth="0"
marginheight="0">
</iframe>
*/
//---
ResetLastError();
//--- download html-pages
int timeout=iReqTimeOut; //--- timeout less than 1,000 (1 sec.) is insufficient at a low speed of the Internet
Print("WebRequest>>",google_url);
res=WebRequest("GET",google_url,cookie,NULL,timeout,post,0,result,headers);//Страница идет в result
//--- error checking
{if(res==-1)//Ошибка запроса
{
ErrCode=GetLastError();
Print("WebRequest error [",google_url,"] err.code =",ErrCode);
{if(ErrCode==4060)//ERR_FUNCTION_NOT_CONFIRMED Функция не разрешена
{
//"Необходимо добавить адрес '"+google_url+"' в список разрешенных URL во вкладке 'Советники'","Ошибка",
MessageBox("You must add the address ' "+google_url+"' in the list of allowed URL tab 'Advisors' "," Error ",MB_ICONINFORMATION);
}}//if(ErrCode==4060)
RetResult=10000+ErrCode;//Ошибка запроса к сайту
}else{//Запрос выполнен
//--- successful download
PrintFormat("File successfully downloaded, the file size in bytes =%d.",ArraySize(result));
//--- save the data in the file
ResetLastError();
int filehandle=FileOpen(iInFailName,FILE_WRITE|FILE_BIN|FILE_TXT|FILE_ANSI|FILE_COMMON|FILE_SHARE_WRITE);
//--- проверка ошибки
{if(filehandle==INVALID_HANDLE)//Ошибка
{
ErrCode=GetLastError();
Print("Error in FileOpen Write [",iInFailName,"] Error code =",ErrCode);
RetResult=30000+ErrCode;//Ошибка записи в файл
FileClose(filehandle);
}else{//Нет ошибки
//--- save the contents of the array result [] in file
FileWriteArray(filehandle,result,0,ArraySize(result));
//--- close file
FileClose(filehandle);
//--- load the contents of the result file
ResetLastError();
int filehandle2=FileOpen(iInFailName,FILE_READ|FILE_BIN|FILE_TXT|FILE_ANSI|FILE_COMMON|FILE_SHARE_READ);
{if(filehandle2==INVALID_HANDLE)//Ошибка
{
ErrCode=GetLastError();
Print("Error in FileOpen Read [",iInFailName,"] Error code =",ErrCode);
RetResult=20000+ErrCode;//Ошибка чтения из файла
FileClose(filehandle2);
}else{//Нет ошибки
iOutString=FileReadString(filehandle2,ArraySize(result));
FileClose(filehandle2);
}}//if(filehandle2!=INVALID_HANDLE)
}}//if(filehandle!=INVALID_HANDLE)
}}//if(res==-1)
return(RetResult);
}//CalendarRequest()
//
//////======================================================================================================
////// StringConverter() - Script program start function
//////======================================================================================================
////bool StringConverter(int iMode,string iInpStr,string &iOutStr,datetime iOffSetTime){
////int
//// n;
////bool
//// iResult=true;
//// iOutStr="";
//// {if((StringFind(iInpStr,",",0)<0)&&(iMode<=3))
//// {
//// iResult=false;
//// return(iResult);
//// }}//if(StringFind(iInpStr,",",0)<0)
//////-----
////string iDateTim="";
////string iDate=gDat;
////string iYear=gYear;
////string iMou=gMoun;
////string iDay=gDay;
////string iTim=gTim;
////string iEvent="";
////string iCountry="";
////string iCouN="";
////string iCur="";
////string iVolatility="";
////string iForecast="";
////string iImpact="";
////string iImpN="";
////string iActual="";
////string iPrevious="";
////int nCountry=0;
////int nnCountry=0;
//////----- Календарь fxstreet
//// {if(iMode==1)
//// {
//// //Стандартный формат
//// //12/11/2015 15:00:00,Reuters/Michigan Consumer Sentiment Index,United States,1,91.800,91.300,92.000
//// //Ограничивающие кавычки в событии
//// //12/15/2015 09:30:00,"PPI Core Output (YoY) n.s.a ",United Kingdom,2,,0.300,0.100
//// //Запятая в событии - не обработано
//// //01/02/2015 11:30:00,"FX Reserves, USD",India,1,319.710,320.000,
//// //01/09/2015 07:45:00,"Exports, EUR",France,1,37.171,36.900,
//// //01/27/2015 14:00:00,"Trade Balance s/a, $",Mexico,1,-0.011,-1.060,
//// //Нестандартное название страны
//// //12/15/2015 08:30:00,Retail Sales (YoY),"Netherlands, The",1,,4.300,
//// iMou=StringSubstr(iInpStr,0,2);
//// iDay=StringSubstr(iInpStr,3,2);
//// iYear=StringSubstr(iInpStr,6,4);
//// iInpStr=StringSubstr(iInpStr,11);
//// iTim=StringSubstr(iInpStr,0,8);
//// iTim=StringSubstr(iTim,0,5);//Удаляем секунды
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+1);
//// //Нормализуем Ограничивающие кавычки и запятая в событии
//// {if(StringFind(iInpStr,"\"",0)==0)
//// {//С кавычками
//// iEvent=StringSubstr(iInpStr,1,StringFind(iInpStr,"\""+",",1));
//// n=StringReplace(iEvent," "+"\"","");//Убираем "пробел+кавычки"
//// n=StringReplace(iEvent,"\"","");//Убираем "кавычки"
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"\""+",",0)+2);
//// }else{//Без кавычек
//// iEvent=StringSubstr(iInpStr,0,StringFind(iInpStr,",",0));
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+1);
//// }}//if(StringFind(iInpStr,"\"",0)=0)
//// //Нормализуем при необходимости Нестандартное название страны
//// {if(StringFind(iInpStr,"\"",0)==0)
//// {
//// //Убираем первые кавычки
//// iInpStr=StringSubstr(iInpStr,1);
//// //Вырезаем от запятой до вторых кавычек
//// n=StringReplace(
//// iInpStr,
//// StringSubstr(iInpStr,StringFind(iInpStr,",",0),StringFind(iInpStr,"\"",0)-StringFind(iInpStr,",",0)+1),
//// "");
//// }}//if(StringFind(iInpStr,"\"",0)=0)
//// iCountry=StringSubstr(iInpStr,0,StringFind(iInpStr,",",0));
//// iCouN=StringSubstr(iCountryS,StringFind(iCountryS,iCountry,3)-3,3);
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+1);
//// iVolatility=StringSubstr(iInpStr,0,StringFind(iInpStr,",",0));
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+1);
//// iActual=((StringFind(iInpStr,",",0)>0)?(StringSubstr(iInpStr,0,StringFind(iInpStr,",",0))):(""));
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+1);
//// iPrevious=((StringFind(iInpStr,",",0)>0)?(StringSubstr(iInpStr,0,StringFind(iInpStr,",",0))):(""));
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+1);
//// iForecast=iInpStr;
//// iOutStr=iYear+"."+iMou+"."+iDay+" "+iTim+";"+iEvent+";"+iCountry+";"+iCouN+";"+iVolatility+";"+iPrevious+";"+iForecast+";"+iActual+";";
//// return(true);
//// }}//if(iMode==1)
//////----- Календарь myfxbook
//// {if(iMode==2)
//// {
//// //"2015, September 01, 11:30","(United Kingdom) Consumer Credit",Medium,Ј1.23B,Ј1.2B,Ј1.17B,GBP
//// iYear=StringSubstr(iInpStr,1,4);
//// iInpStr=StringSubstr(iInpStr,7);
//// iMou=StringSubstr(iInpStr,0,StringFind(iInpStr," ",3));
//// iMou=StringSubstr(iMounthN,StringFind(iMounthN,iMou,2)-2,2);
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr," ",1)+1);
//// iDay=StringSubstr(iInpStr,0,2);
//// iInpStr=StringSubstr(iInpStr,4);
//// iTim=StringSubstr(iInpStr,0,5);
//// iInpStr=StringSubstr(iInpStr,9);
//// iDateTim=TimeToString(StringToTime(iYear+"."+iMou+"."+iDay+" "+iTim),TIME_DATE|TIME_MINUTES);
//// iCountry=StringSubstr(iInpStr,0,StringFind(iInpStr,")",0));
//// iCouN=StringSubstr(iCountryS,StringFind(iCountryS,iCountry,3)-3,3);
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,") ",0)+2);
//// iEvent=StringSubstr(iInpStr,0,StringFind(iInpStr,"\",",0));
//// n=StringReplace(iEvent,";",".");
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"\",",0)+2);
//// iImpact=StringSubstr(iInpStr,0,StringFind(iInpStr,",",0));
//// iImpN=StringSubstr(iImpactLN,StringFind(iImpactLN,iImpact,1)-1,1);
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+1);
//// iPrevious=((StringFind(iInpStr,",",0)>0)?(StringSubstr(iInpStr,0,StringFind(iInpStr,",",0))):(""));
//// StringNormal(iPrevious);
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+1);
//// iForecast=((StringFind(iInpStr,",",0)>0)?(StringSubstr(iInpStr,0,StringFind(iInpStr,",",0))):(""));
//// StringNormal(iForecast);
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+1);
//// iActual=((StringFind(iInpStr,",",0)>0)?(StringSubstr(iInpStr,0,StringFind(iInpStr,",",0))):(""));
//// StringNormal(iActual);
//// iOutStr=iDateTim+";"+iEvent+";"+iCountry+";"+iCouN+";"+iImpN+";"+iPrevious+";"+iForecast+";"+iActual+";";
//// return(true);
//// }}//if(iMode==2)
//////----- Календарь allnews
//// {if(iMode==3)
//// {
//// //"2007/02/06","07:00","EUR","M","German Factory Orders m/m","-0.2%","0.5%","0.8%","1.5%","03558"
//// //"2007/01/30","06:18","EUR","L","Italian 10-y Bond Auction","4.29|1.3","","4.17|1.5","","43355" string iDay=StringSubstr(iInpStr,0,2);
//// //Date, Time, Currency, News description, Impact, Actual, Forecast, Previous, Revised from, FF event ID
//// //Print(iInpStr);
//// iYear=StringSubstr(iInpStr,1,4);
//// iMou=StringSubstr(iInpStr,6,2);
//// iDay=StringSubstr(iInpStr,9,2);
//// iInpStr=StringSubstr(iInpStr,14);
//// iTim=StringSubstr(iInpStr,0,5);
//// iInpStr=StringSubstr(iInpStr,8);
//// iCouN=StringSubstr(iInpStr,0,3);
//// iInpStr=StringSubstr(iInpStr,6);
//// iImpact=StringSubstr(iInpStr,0,1);
//// iImpN=StringSubstr(iImpactN,StringFind(iImpactN,iImpact,1)-1,1);
//// iInpStr=StringSubstr(iInpStr,4);
//// iEvent=StringSubstr(iInpStr,0,StringFind(iInpStr,"\""+",",0));
//// iCountry=StringSubstr(iEvent,0,StringFind(iEvent," ",0));
//// nCountry=StringFind(iCountryT,iCountry,0);
//// nnCountry=nCountry+StringLen(iCountry);
//// iCountry=((nCountry>=0)
//// ?(StringSubstr(iCountryT,nnCountry,StringFind(iCountryT,"#",nnCountry)-nnCountry))
//// :(StringSubstr(iCountryS,
//// StringFind(iCountryS,iCouN,0)+3,
//// StringFind(iCountryS,"#",StringFind(iCountryS,iCouN,0)+3)-StringFind(iCountryS,iCouN,0)-3)));
//// //iEvent=((nCountry>=0)?(StringSubstr(iEvent,StringFind(iEvent," ",0)+1,StringLen(iCountry)-StringFind(iEvent," ",0)-1)):(iEvent));
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+2);
//// iActual=((StringFind(iInpStr,"\"",0)>0)?(StringSubstr(iInpStr,0,StringFind(iInpStr,"\"",0))):(""));
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+2);
//// iPrevious=((StringFind(iInpStr,"\"",0)>0)?(StringSubstr(iInpStr,0,StringFind(iInpStr,"\"",0))):(""));
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,",",0)+2);
//// iForecast=((StringFind(iInpStr,"\"",0)>0)?(StringSubstr(iInpStr,0,StringFind(iInpStr,"\"",0))):(""));
//// iOutStr=iYear+"."+iMou+"."+iDay+" "+iTim+";"+iEvent+";"+iCountry+";"+iCouN+";"+iImpN+";"+iPrevious+";"+iForecast+";"+iActual+";";
//// return(true);
//// }}//if(iMode==3)
//////----- Календарь investing html
//// {if(iMode==4)
//// {
//// //<tr><td colspan="9" class="theDay" id="theDay1458864000">Friday, March 25, 2016</td></tr>
//// //<tr id="eventRowId_3"><td class="first left">All Day</td><td class="flagCur left"><span title="Australia" class="ceFlags Australia float_lang_base_1" data-img_key="Australia"></span></td><td class="left textNum sentiment"><span class="bold">Holiday</span></td><td colspan="6" class="left event">Australia - Good Friday</td></tr>
//// //<tr id="eventInfo325877" class="noHover displayNone"><td id="eventInfoTd325877" colspan="8" class="eventInfo"><div class="displayNone" id="eventDivWrapper325877"></div></td></tr>
//// //<tr id="eventRowId_325877" class="js-event-item" event_attr_id="1623" data-event-datetime="2016/03/24 18:00:00"><td class="first left time js-time" title="Event data was released 548h 57m ago">18:00</td><td class="left flagCur noWrap"><span title="France" class="ceFlags France" data-img_key="France"></span>EUR</td><td class="left textNum sentiment noWrap" title="Moderate Volatility Expected" data-img_key="bull2"><i class="grayFullBullishIcon"></i><i class="grayFullBullishIcon"></i><i class="grayEmptyBullishIcon"></i></td><td class="left event" title="Click to view more info on France Jobseekers Total"><a href="http://www.investing.com/economic-calendar/france-jobseekers-total-1623" target="_blank">France Jobseekers Total (Feb)</a></td><td class="bold act redFont event-325877-actual" title="Worse Than Expected" id="eventActual_325877">3,591.0K</td><td class="fore event-325877-forecast " id="eventForecast_325877">3,555.3K</td><td class="prev blackFont event-325877-previous" id="eventPrevious_325877">3,552.6K</td><td class="diamond" id="eventRevisedFrom_325877"></td></tr>
////
////
//// //<tr id="eventRowId_9"><td class="first left">All Day</td><td class="flagCur left"><span title="United States" class="ceFlags United_States float_lang_base_1" data-img_key="United_States">&nbsp;</span></td><td class="left textNum sentiment"><span class="bold">Holiday</span></td><td colspan="6" class="left event">United States - New Year's Day</td></tr>
//// //<tr id="eventRowId_9"><td class="first left">All Day</td><td class="flagCur left"><span title="United Kingdom" class="ceFlags United_Kingdom float_lang_base_1" data-img_key="United_Kingdom">&nbsp;</span></td> <td class="left textNum sentiment"><span class="bold">Holiday</span></td><td colspan="6" class="left event">United Kingdom - New Year's Day</td></tr>
//// //<tr id="eventRowId_320509" class="js-event-item" event_attr_id="594" data-event-datetime="2016/01/01 02:00:00"><td class="first left time js-time" title="Event data was released 2556h 43m ago">02:00</td><td class="left flagCur noWrap"><span title="China" class="ceFlags China" data-img_key="China">&nbsp;</span> CNY</td><td class="left textNum sentiment noWrap" title="High Volatility Expected" data-img_key="bull3"><i class="grayFullBullishIcon"></i><i class="grayFullBullishIcon"></i><i class="grayFullBullishIcon"></i></td><td class="left event" title="Click to view more info on Manufacturing PMI"><a href="http://www.investing.com/economic-calendar/chinese-manufacturing-pmi-594" target="_blank"> Manufacturing PMI (Dec)</a></td><td class="bold act blackFont event-320509-actual" title="In Line with Expectation" id="eventActual_320509">49.7</td><td class="fore event-320509-forecast " id="eventForecast_320509">49.7</td><td class="prev blackFont event-320509-previous" id="eventPrevious_320509">49.6</td><td class="diamond" id="eventRevisedFrom_320509">&nbsp;</td></tr>
//// //<tr id="eventRowId_320070" event_attr_id="1292" event_timestamp="2015-12-21 22:00:00"><td class="first left time">01:00</td><td class="left flagCur noWrap"><span title="Colombia" class="ceFlags Colombia" data-img_key="Colombia">&nbsp;</span> COP</td> <td class="left textNum sentiment noWrap" title="Low Volatility Expected" data-img_key="bull1"><i class="grayFullBullishIcon"></i><i class="grayEmptyBullishIcon"></i><i class="grayEmptyBullishIcon"></i></td> <td class="left event" title="Click to view more info on Imports"><a href="http://www.investing.com/economic-calendar/colombian-imports-1292" target="_blank"> Imports (YoY) (Oct)</a> </td> <td class="bold act blackFont event-320070-actual" title="" id="eventActual_320070">&nbsp;</td> <td class="fore event-320070-forecast " id="eventForecast_320070">&nbsp;</td> <td class="prev blackFont event-320070-previous" id="eventPrevious_320070">-22.30%</td> <td class="diamond" id="eventRevisedFrom_320070">&nbsp;</td> </tr> <tr id="eventInfo320070" class="noHover displayNone"> <td id="eventInfoTd320070" colspan="8" class="eventInfo"> <div class="displayNone" id="eventDivWrapper320070"></div> </td> </tr>
//// //<tr id="eventRowId_165"> <td class="first left">All Day</td> <td class="flagCur left"><span title="Bahrain" class="ceFlags Bahrain float_lang_base_1" data-img_key="Bahrain">&nbsp;</span></td> <td class="left textNum sentiment"><span class="bold">Holiday</span></td> <td colspan="6" class="left event">Bahrain - Prophet's Birthday</td> </tr>
////
//// //Строка даты нового дня - заносим дату в глобал, для установки дат недатированных событий
////
//// //Print("iInpStr=",iInpStr);
////
//// string iTheDay="";
//// int posDay=StringFind(iInpStr,"<td colspan=\"8\" class=\"theDay\" id=\"theDay");
//// //int posDay=StringFind(iInpStr,"<td colspan=\"9\" class=\"theDay\" id=\"theDay");
//// {if((posDay>=0)&&(TagContent(iInpStr,"id=\"theDay","/td>",iTheDay)))
//// {
//// iResult=TagContent(iTheDay,", ","<",iTheDay);
//// gMoun=StringSubstr(iTheDay,0,StringFind(iTheDay," "));
//// gMoun=StringSubstr(iMounthN,StringFind(iMounthN,gMoun,2)-2,2);
//// iResult=TagContent(iTheDay," ",",",gDay);
//// gYear=StringSubstr(iTheDay,StringFind(iTheDay,", ")+2);
//// iTheDay=gYear+"."+gMoun+"."+gDay+" 00:00:00";
//// TimeToStruct(StringToTime(iTheDay),gDateTime);
//// iResult=TagDelete(iInpStr,"<tr>","</tr>");
//// //Print("iTheDay=",iTheDay);
//// return(false);
//// }}//if(TagContent(InpStrBuff,"id=\"theDay","/td>",iTheDay))
////
//// int dFormat=0;
//// dFormat=(TagContent(iInpStr,"event_timestamp=\"","\">",iDate))
//// ?(1)
//// :(
//// (TagContent(iInpStr,"data-event-datetime=\"","\">",iDate))
//// ?(2)
//// :(0)
//// );
//// {if((dFormat==1)||(dFormat==2)) //если один из распознаваемых форматов
//// //{if(TagContent(iInpStr,"event_timestamp=\"","\">",iDate)) //если есть дата тэг в формате сгенерированной страницы ноябрь 2016
//// //{if(TagContent(iInpStr,"data-event-datetime=\"","\">",iDate)) //если есть дата тэг в формате апреля 2016
//// //{if(TagContent(iInpStr,"event_timestamp=\"","\">",iDate)) //если есть дата тэг в формате ранее апреля 2016
//// {
//// //----- Date Time
//// if(dFormat==2)StringReplace(iDate,"/",".");//в формате апреля 2016
//// if(dFormat==1)StringReplace(iDate,"-",".");//в формате ранее апреля 2016
//// iDateTim=TimeToString(StringToTime(iDate)+iOffSetTime,TIME_DATE|TIME_MINUTES);
//// TimeToStruct(StringToTime(iDate)+iOffSetTime,gDateTime);
//// iResult=TagDelete(iInpStr,"<tr id=\"eventRowId_","\">");
//// //<td class="first left time js-time" title="Event data was released 548h 57m ago">18:00</td><td class="left flagCur noWrap"><span title="France" class="ceFlags France" data-img_key="France"></span>EUR</td><td class="left textNum sentiment noWrap" title="Moderate Volatility Expected" data-img_key="bull2"><i class="grayFullBullishIcon"></i><i class="g
//// iResult=TagDelete(iInpStr,"<td class=","</td>");
//// //<td class="left flagCur noWrap"><span title="France" class="ceFlags France" data-img_key="France"></span>EUR</td><td class="left textNum sentiment noWrap" title="Moderate Volatility Expected" data-img_key="bull2"><i class="grayFullBullishIcon"></i><i class="g
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"<td"));
//// //<td class="left flagCur noWrap"><span title="France" class="ceFlags France" data-img_key="France"></span>EUR</td><td class="left textNum sentiment noWrap" title="Moderate Volatility Expected" data-img_key="bull2"><i class="grayFullBullishIcon"></i><i class="g
//// //----- Country
//// iResult=TagContent(iInpStr,"<span title=\"","\" class=\"",iCountry);
//// //----- Currency
//// iResult=TagContent(iInpStr,"</span>","</td>",iCouN);
//// iResult=TagDelete(iInpStr,"<td class=","</td>");
//// //<td class="left textNum sentiment noWrap" title="Moderate Volatility Expected" data-img_key="bull2"><i class="grayFullBullishIcon"></i><i class="g
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"<td"));
//// //----- Impact
//// iResult=TagContent(iInpStr,"title=\"","\">",iVolatility);
//// //iResult=TagContent(iInpStr,"noWrap\" title=\"","\" data-img_key",iVolatility);
//// //----- Impact N
//// iImpN=StringSubstr(iImpactMN,StringFind(iImpactMN,iVolatility,1)-1,1);
//// iResult=TagDelete(iInpStr,"<td class=","</td>");
//// //<td class="left event" title="Click to view more info on France Jobseekers Total"><a href="http://www.investing.com/economic-calendar/france-jobseekers-total-1623" target="_blank">France Jobseekers Total (Feb)</a></td><td class="bold act redFont event-325877-actual" title="Worse Than Expected" id="eventActual_325877">3,591.0K</td><td class="fore event-325877-forecast " id="eventForecast_325877">3,555.3K</td><td class="prev blackFont event-325877-previous" id="eventPrevious_325877">3,552.6K</td><td class="diamond" id="eventRevisedFrom_325877"></td></tr>
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"<td"));
//// //----- Тип события
//// iResult=TagDelete(iInpStr,"<span","</span>"); //Удаляем тип события
//// //----- Event
//// iResult=TagContent(iInpStr,"event\">","</td",iEvent);
//// //iResult=TagContent(iInpStr,"target=\"_blank\">","</a>",iEvent);
//// iResult=TagDelete(iInpStr,"<td class=","</td>"); //Удаляем событие
//// //<td class="bold act redFont event-325877-actual" title="Worse Than Expected" id="eventActual_325877">3,591.0K</td><td class="fore event-325877-forecast " id="eventForecast_325877">3,555.3K</td><td class="prev blackFont event-325877-previous" id="eventPrevious_325877">3,552.6K</td><td class="diamond" id="eventRevisedFrom_325877"></td></tr>
//// n=StringReplace(iEvent,"&amp;","");
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"<td"));
//// //----- Actual
//// iResult=TagContent(iInpStr,"id=\"eventActual_","/td>",iActual);
//// iResult=TagContent(iActual,"\">","<",iActual);
//// n=StringReplace(iActual,"&nbsp;","");
//// iResult=TagDelete(iInpStr,"<td class=","</td>"); //Удаляем тег с актуалом
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"<td"));
//// //----- Forecast
//// iResult=TagContent(iInpStr,"id=\"eventForecast_","/td>",iForecast);
//// iResult=TagContent(iForecast,"\">","<",iForecast);
//// n=StringReplace(iForecast,"&nbsp;","");
//// iResult=TagDelete(iInpStr,"<td class=","</td>"); //Удаляем тег с прогнозом
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"<td"));
//// //----- Previous &amp;
//// iResult=TagContent(iInpStr,"id=\"eventPrevious_","/td>",iPrevious);
//// iResult=TagContent(iPrevious,"\">","<",iPrevious);
//// n=StringReplace(iPrevious,"&nbsp;","");
//// }else{//Если даты нет но возможно "All Day"
//// {if(TagContent(iInpStr,"<td class=\"first left\">","</td>",iDate)&&(iDate=="All Day")) //если есть дата тэг
//// {
//// //----- Date Time
//// iDateTim=TimeToString(StructToTime(gDateTime),TIME_DATE|TIME_MINUTES);
//// iResult=TagDelete(iInpStr,"<tr id=\"eventRowId_","</td>");
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"<td"));
//// //----- Country
//// iResult=TagContent(iInpStr,"<span title=\"","\" class=\"",iCountry);
//// //----- Currency
//// iCouN=StringSubstr(iCountryS,StringFind(iCountryS,iCountry,3)-3,3);
//// iResult=TagDelete(iInpStr,"<td class=","</td>");
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"<td"));
//// //----- Impact
//// iResult=TagContent(iInpStr,"<span class=","</td>",iVolatility);
//// iResult=TagContent(iVolatility,"\">","</span>",iVolatility);
//// //----- Impact N
//// iImpN=StringSubstr(iImpactMN,StringFind(iImpactMN,iVolatility,1)-1,1);
//// iResult=TagDelete(iInpStr,"<td class=","</td>");
//// iInpStr=StringSubstr(iInpStr,StringFind(iInpStr,"<td"));
//// //----- Event
//// iResult=TagContent(iInpStr,"class=\"","td>",iEvent);
//// iResult=TagContent(iInpStr,"\">","</",iEvent);
//// //----- Previous
//// iPrevious="";
//// //----- Forecast
//// iForecast="";
//// //----- Actual
//// iActual="";
//// //Print("4. iDate=",iDate," iDateTim=",iDateTim," iStr=",iInpStr);
//// }else{//Если даты нет и нет "All Day"
//// iOutStr="";
//// return(false);
//// }}//if(TagContent(iInpStr,"<span class=\"date\">","</td>",iMouDay))
//// }}//if(TagContent(iInpStr,"<span class=\"date\">","</td>",iMouDay))
//// iOutStr=iDateTim+";"+iEvent+";"+iCountry+";"+iCouN+";"+iImpN+";"+iPrevious+";"+iForecast+";"+iActual+";";//
//// //Print("iOutStr=",iOutStr);
//// //Print("3. iRes=",iResult," iPrevious=",iPrevious," iStr=",iInpStr);
//// return(true);
//// }}//if(iMode==4)
//////----- Календарь forexfactory html
//// {if(iMode==5)
//// {
//// //----- Date
//// {if(TagContent(iInpStr,"<td class=\"date\">","</td>",iMou)) //если есть дата тэг
//// {
//// iResult=TagDelete(iMou,"<span class=\"date\">","<span>"); //Удаляем день недели
//// iResult=TagDelete(iMou,"</span>","</span>"); //Удаляем </span></span>
//// iDay=StringSubstr(iMou,4); //Вынимаем "14" или "1"
//// iMou=StringSubstr(iMou,0,3); //Вынимаем "Dec"
//// iDay=((StringLen(iDay)>=2)?(StringSubstr(iDay,0,2)):("0"+iDay)); //День дополняем нулем
//// iMou=StringSubstr(iMounthN,StringFind(iMounthN,iMou,2)-2,2); //Месяц переводим в число
//// gDay=iDay;
//// gMoun=iMou;
//// }else{//Если даты нет
//// iDay=gDay;
//// iMou=gMoun;
//// }}//if(TagContent(iInpStr,"<span class=\"date\">","</td>",iMouDay))
//// iResult=TagDelete(iInpStr,"<td class=\"date\">","</td>"); //Удаляем дату
//// //----- Time
//// {if(TagContent(iInpStr,"<td class=\"time\">","</td>",iTim)) //Если есть время тэг
//// {
//// {if((iTim=="Tentative")||(iTim=="All Day"))
//// {
//// iTim="00:00";
//// }else{
//// {if((StringLen(iTim)>5)&&(StringFind(iTim,":",1)>=1)) //Если есть дополнительный тег и время в нем
//// {//<span class="upnext">
//// iResult=TagContent(iTim,"<span class=\"upnext\">","</span>",iTim); //Вынимаем "0:00" или "00:00"
//// }}//if(StringLen(iTim)>5)
//// iTim=((StringLen(iTim)>=5)?(StringSubstr(iTim,0,5)):("0"+iTim));
//// gTim=iTim;
//// }}//
//// }else{//Если даты нет
//// iTim=gTim;
//// }}//if(TagContent(iInpStr,"<span class=\"time\">","</td>",iTim))
//// iResult=TagDelete(iInpStr,"<td class=\"time\">","</td>"); //Удаляем время
//// //----- Currency
//// iResult=TagContent(iInpStr,"<td class=\"currency\">","</td>",iCouN);
//// {if(!iResult)
//// {
//// iOutStr="";
//// return(false);
//// }}//if(!iResult)
//// iResult=TagDelete(iInpStr,"<td class=\"currency\">","</td>");
//// //----- Impact
//// iResult=TagContent(iInpStr,"<td class=\"impact\">","</td>",iImpact);
//// iResult=TagContent(iImpact,"<span title=\"","\" class=\"",iImpact);
//// {if(!iResult)
//// {
//// iOutStr="";
//// return(false);
//// }}//if(!iResult)
//// iResult=TagDelete(iInpStr,"<td class=\"impact\">","</td>");
//// //----- Impact N
//// iImpN=StringSubstr(iImpactNN,StringFind(iImpactNN,iImpact,1)-1,1);
//// //----- Event &amp;
//// iEvent="";
//// iResult=TagContent(iInpStr,"<td class=\"event\"><span>","</span></td>",iEvent);
//// n=StringReplace(iEvent,"&amp;","&");
//// {if(!iResult)
//// {
//// iOutStr="";
//// return(false);
//// }}//if(!iResult)
//// iResult=TagDelete(iInpStr,"<td class=\"event\">","</td>");
//// iResult=TagDelete(iInpStr,"<td class=\"detail\">","</td>");
//// iCountry=StringSubstr(iEvent,0,StringFind(iEvent," ",0));
//// nCountry=StringFind(iCountryT,iCountry,0);
//// nnCountry=nCountry+StringLen(iCountry);
//// iCountry=((nCountry>=0)
//// ?(StringSubstr(iCountryT,nnCountry,StringFind(iCountryT,"#",nnCountry)-nnCountry))
//// :(StringSubstr(iCountryS,
//// StringFind(iCountryS,iCouN,0)+3,
//// StringFind(iCountryS,"#",StringFind(iCountryS,iCouN,0)+3)-StringFind(iCountryS,iCouN,0)-3)));
//// iEvent=((nCountry>=0)?(StringSubstr(iEvent,StringFind(iEvent," ",0)+1,StringLen(iCountry)-StringFind(iEvent," ",0)-1)):(iEvent));
//// StringTrimRight(iEvent);
//// //----- Actual
//// iResult=TagContent(iInpStr,"<td class=\"actual\">","</td>",iActual);
//// {if(StringFind(iActual,"<span class=",0)>=0)
//// {
//// string iClass="";
//// iResult=TagContent(iActual,"<span class=\"","\">",iClass);
//// iResult=TagContent(iActual,"<span class=\""+iClass+"\">","</span>",iActual);
//// StringNormal(iActual);
//// iResult=TagDelete(iInpStr,"<span class=\"","</span>");
//// }}//
//// iResult=TagDelete(iInpStr,"<td class=\"actual\">","</td>");
//// n=StringReplace(iActual,"&lt;","");
//// n=StringReplace(iActual,"\t","");//Тут всавлен спецсимвол табуляция
//// n=StringReplace(iActual," ","");
//// StringNormal(iActual);
//// //----- Forecast
//// iResult=TagContent(iInpStr,"<td class=\"forecast\">","</td>",iForecast);
//// iResult=TagDelete(iInpStr,"<td class=\"forecast\">","</td>");
//// n=StringReplace(iForecast,"&lt;","");
//// n=StringReplace(iForecast,"\t","");
//// n=StringReplace(iForecast," ","");
//// StringNormal(iForecast);
//// //----- Previous
//// iResult=TagContent(iInpStr,"<td class=\"previous\">","</td>",iPrevious);
//// {if(StringFind(iPrevious,"<span class=",0)>=0)
//// {
//// string iClass="";
//// iResult=TagContent(iPrevious,"<span class=\"","\">",iClass);
//// iResult=TagContent(iPrevious,"<span class=\""+iClass+"\">","</span>",iPrevious);
//// iResult=TagDelete(iInpStr,"<span class=\"","</span>");
//// }}//&lt;
//// n=StringReplace(iPrevious,"&lt;","");
//// n=StringReplace(iPrevious,"\t","");
//// n=StringReplace(iPrevious," ","");
//// StringNormal(iPrevious);
//// iOutStr=iYear+"."+iMou+"."+iDay+" "+iTim+";"+iEvent+";"+iCountry+";"+iCouN+";"+iImpN+";"+iPrevious+";"+iForecast+";"+iActual+";";//
//// return(true);
//// //Print("iOutStr=",iOutStr);
//// //Print("3. iRes=",iResult," iActual=***",iActual,"*** iStr=",iInpStr);
//// }}//if(iMode==5)
//////----- Календарь DailyFX html
//// {if(iMode==6)
//// {
//////id="date1_0" style="width: 0%;">December 14, 2015 00:30</td>
//////<td style="width: 6%;" class="text-center calendar-td"><div class="flag-20-nzd"></div></td>
//////<td style="width: 48%;" id="title1_0" class="calendar-td"><div class="visible-xs f16">00:30<br></div>NZD Performance Services Index (NOV)</td>
//////<td style="width: 12%;" class="calendar-td">
//////<span id="importance1_0" class="label label-medium text-capitalize hidden-xs">medium</span>
//////<span id="importance1_0" class="label label-sm label-medium-sm text-capitalize hidden-lg hidden-md hidden-sm">m</span>
//////</td>
//////<td style="width: 8%;" class="-color hidden-xs text-center calendar-td">59.8</td>
//////<td style="width: 10%;" class="hidden-xs text-center calendar-td"></td>
//////<td style="width: 8%;" class="up-color hidden-xs text-center calendar-td">56.5</td>
//// //----- Date Time
//// {if(TagContent(iInpStr,";\"","/td>",iDateTim)) //если есть дата тэг
//// {
//// iResult=TagContent(iDateTim,">"," ",iMou);
//// iMou=StringSubstr(iMounthN,StringFind(iMounthN,iMou,2)-2,2); //Месяц переводим в число
//// iResult=TagDelete(iDateTim,">"," "); //Удаляем
//// iDay=StringSubstr(iDateTim,0,StringFind(iDateTim,",")); //Вынимаем день
//// iDay=((StringLen(iDay)>=2)?(StringSubstr(iDay,0,2)):("0"+iDay)); //День дополняем нулем
//// iDateTim=StringSubstr(iDateTim,StringFind(iDateTim,", ")+2); //Вырезаем от года и дальше
//// iYear=StringSubstr(iDateTim,0,4); //Вынимаем год
//// iResult=TagContent(iDateTim," ","<",iTim); //Вынимаем время
//// gYear=iYear;
//// gMoun=iMou;
//// gDay=iDay;
//// gTim=iTim;
//// }else{//Если даты нет ??А это возможно??
//// iYear=gYear;
//// iDay=gDay;
//// iMou=gMoun;
//// iTim=gTim;
//// }}//if(TagContent(iInpStr,"<span class=\"date\">","</td>",iMouDay))
//// iDate=iYear+"."+iMou+"."+iDay+" "+iTim;
//// iDateTim=TimeToString(StringToTime(iDate),TIME_DATE|TIME_MINUTES);
//// TimeToStruct(StringToTime(iDate),gDateTime);
//// iResult=TagDelete(iInpStr,"id=\"date","</td>"); //Удаляем дату
//// //----- Currency
//// iResult=TagContent(iInpStr,"<div class=\"flag-20-","\">",iCouN);
//// {if(!iResult)
//// {
//// iOutStr="";
//// return(false);
//// }}//if(!iResult)
//// StringToUpper(iCouN);
//// iResult=TagDelete(iInpStr,"<td style=","<br></");
//// //----- Country
//// iCountry=StringSubstr(iCountryS,
//// StringFind(iCountryS,iCouN,0)+3,
//// StringFind(iCountryS,"#",StringFind(iCountryS,iCouN,0)+3)-StringFind(iCountryS,iCouN,0)-3);
//// //----- Event
//// iResult=TagContent(iInpStr,"di","td><td style",iEvent);
//// {if(!iResult)
//// {
//// iOutStr="";
//// return(false);
//// }}//if(!iResult)
//// iResult=TagContent(iEvent,"v>"," ",iCur);
//// {if(StringFind(iCountryS,iCur)>=0)
//// {
//// iResult=TagDelete(iEvent,">"," ");
//// iResult=TagContent(iEvent,"v","</",iEvent);
//// }else{
//// iResult=TagContent(iEvent,"v>","</",iEvent);
//// }}//if(StringFind(iCountryS,iCur)>=0)
//// n=StringReplace(iEvent,"&#039;","\'");
//// iResult=TagDelete(iInpStr,"div>","<span id=\"imp");
//// //----- Impact
//// iResult=TagContent(iInpStr,"\">","</span>",iImpact);
//// {if(!iResult)
//// {
//// iOutStr="";
//// return(false);
//// }}//if(!iResult)
//// //----- Impact N
//// iImpN=StringSubstr(iImpactON,StringFind(iImpactON,iImpact,1)-1,1);
//// iResult=TagDelete(iInpStr,"ortance","</span></td>");
//// //----- Actual
//// iResult=TagContent(iInpStr,"td\">","</td>",iActual);
//// iResult=TagDelete(iInpStr,"<td style=","</td>");
//// //n=StringReplace(iActual,"&lt;","");
//// //n=StringReplace(iActual,"\t","");
//// //n=StringReplace(iActual," ","");
//// StringNormal(iActual);
//// //----- Forecast
//// iResult=TagContent(iInpStr,"td\">","</td>",iForecast);
//// iResult=TagDelete(iInpStr,"<td style=","</td>");
//// //n=StringReplace(iForecast,"&lt;","");
//// //n=StringReplace(iForecast,"\t","");
//// //n=StringReplace(iForecast," ","");
//// StringNormal(iForecast);
//// //----- Previous
//// iResult=TagContent(iInpStr,"td\">","</td>",iPrevious);
//// iResult=TagDelete(iInpStr,"<td style=","</td>");
//// //n=StringReplace(iPrevious,"&lt;","");
//// //n=StringReplace(iPrevious,"\t","");
//// //n=StringReplace(iPrevious," ","");
//// StringNormal(iPrevious);
//// iOutStr=iYear+"."+iMou+"."+iDay+" "+iTim+";"+iEvent+";"+iCountry+";"+iCouN+";"+iImpN+";"+iPrevious+";"+iForecast+";"+iActual+";";//
//// return(true);
//// //Print("iOutStr=",iOutStr);
//// //Print("3. iRes=",iResult," iActual=***",iActual,"*** iStr=",iInpStr);
//// }}//if(iMode==6)
//////-----
//// return(false);
////}//StringConverter()
//
//======================================================================================================
// StringNormal() - удаление из строки не цифровых символов
//======================================================================================================
void StringNormal(string &iInpStr){
string
Cifr="0123456789.-KMBT$|%";
StringTrimLeft(iInpStr);
StringTrimRight(iInpStr);
StringToUpper(iInpStr);
//Print(iInpStr);
{for(int i=StringLen(iInpStr)-1;i>=0;i--)
{
{if(StringFind(Cifr,StringSubstr(iInpStr,i,1),0)<0)
{
//Print(StringSubstr(iInpStr,i,1));
StringSetCharacter(iInpStr,i,'#');
}}//if(StringFind(Cifr,StringSubstr(iInpStr,i,1),0)<0)
}}//for(int i=StringLen(iInpStr)-1;i>=0;i--)
//Print(StringReplace(iInpStr,"#",""));
StringReplace(iInpStr,"#","");
return;
}//StringNormal()
//
//======================================================================================================
// NormalizeFile() - Удаление из файла повторов и косяков
//======================================================================================================
bool NormalizeFile( string iInFileName,
string iTmpFileName){
string
OutStr="";
uchar
LastChar=char(0),
InpChar=char(0);
int
n=0,
CharOperation=0;// 0/1/2/3 - без изменений/пропустить/заменить/конец строки
//-----
ResetLastError();
int InFileHandle = FileOpen(iInFileName,FILE_READ|FILE_BIN|FILE_COMMON,',');
{if ((InFileHandle!=INVALID_HANDLE)&&(FileSize(InFileHandle)!=0))
{
ResetLastError();
int OutFileHandle=FileOpen(iTmpFileName,FILE_WRITE|FILE_TXT|FILE_ANSI|FILE_COMMON,',');
{if(OutFileHandle!=INVALID_HANDLE)
{
bool NewString=true;
{while(!FileIsEnding(InFileHandle))
{
CharOperation=0;//Передать на выход по умолчанию
ResetLastError();
InpChar=(uchar)FileReadInteger(InFileHandle,1);
{if(CharToString(InpChar)==">")//Конец тега - конец строки
{
CharOperation=3;
}}//if(CharToString(InpChar)==">")
{if(CharToString(InpChar)==" ")//Пробел...
{
{if(CharToString(LastChar)==" ")//... после пробела
{
CharOperation=1;//Пропустить
}else{
CharOperation=0;//Передать на выход
}}//if(CharToString(LastChar)==" ")
}}//if(CharToString(InpChar)==" ")
LastChar=InpChar;
{switch(CharOperation)
{
case 1://Пропустить
//Просто ничего не делать
break;
case 2://Заменить
//Пока не известно, что можно сразу заменять
break;
case 3://Конец строки - запись строки в файл
ResetLastError();
OutStr=OutStr+CharToString(InpChar);
//Подчистка
n=StringReplace(OutStr,"\t","");//Удаляем табуляции
n=StringReplace(OutStr,"\n","");//удаляем возвраты каретки
n=StringReplace(OutStr,"\r","");//удаляем переводы строк
n=StringReplace(OutStr,"\0","");
n=StringReplace(OutStr,"&nbsp;","");//&nbsp;
n=StringReplace(OutStr,"&amp;","");//&amp;
n=StringReplace(OutStr,"&lt;","");//&lt;
n=StringReplace(OutStr,"&#039;","");//&#039;
n=StringReplace(OutStr," <","<");//удаляем пробел перед тегом
n=StringReplace(OutStr," "," ");//удаляем двойные пробелы
OutStr=((StringGetCharacter(OutStr,0)==StringGetCharacter(" ",0))?(StringSubstr(OutStr,1)):(OutStr));//удаляем пробел в начале строки
//OutStr=OutStr+"\n\r";//<ВК><ПС>
OutStr=OutStr+"\n";//<ВК>
//Print("OutStr=",OutStr);
if(FileWriteString(OutFileHandle,OutStr)==0)return(false);
OutStr="";
break;
default://0 - Передать без изменений на выход
OutStr=OutStr+CharToString(InpChar);
break;
}}//switch(CharOperation)
}}//while(!FileIsEnding(file_handle))
//Закрытие выходного файла
ResetLastError();
FileClose(OutFileHandle);
//Закрытие входного файла
ResetLastError();
FileClose(InFileHandle);
}else{
Print("NormalizeFile>> Операция FileOpen Write неудачна, ошибка ",GetLastError());
return(false);
}}//if(OutFileHandle!=INVALID_HANDLE)
}else{
Print("NormalizeFile>> Операция FileOpen Read неудачна, ошибка ",GetLastError());
return(false);
}}//if ((InFileHandle!=INVALID_HANDLE)&&(FileSize(InFileHandle)!=0))
//-----
return(true);
}//NormalizeFile()
//
//======================================================================================================
// iMAOnArrayMql4v2() - Расчет скользящего среднего как для mql4 программ от произвольного массива.
// Вход:
// Array[] - Массив с данными.
// total - Количество элементов для вычисления. 0 означает все элементы массива.
// ma_period - Период усреднения для вычисления индикатора.
// ma_shift - Сдвиг индикатора относительно ценового графика.
// ma_method - Метод усреднения. Может быть любым из значений перечисления ENUM_MA_METHOD.
// shift - Индекс получаемого значения из индикаторного буфера (сдвиг относительно текущего бара на указанное количество периодов назад).
// Выход:
// Значение технического индикатора Moving Average, рассчитанного на данных, хранящихся в массиве Array[].
//======================================================================================================
double iMAOnArrayMql4v2( double &Array[],
uint total,
uint iMAPeriod,
uint ma_shift,
ENUM_MA_METHOD ma_method,
uint Shift){
double buf[];
{if((total>0)&&(total<=iMAPeriod)){return(0);}}
{if(total==0){total=ArraySize(Array);}}//total равен размеру массива.
{if(ArrayResize(buf,total)<0){return(0);}}
{switch(ma_method)
{
case MODE_SMA :
{
double sum=0;
uint i,pos=total-1;//pos равен номеру последнего элемента массива
{for(i=1;i<iMAPeriod;i++,pos--)//Перебор на глубину периода МА
{
//{if((pos>1000)||(pos<2))
//{
// Print("total=",total," i=",i," pos=",pos);
//}}//if(pos>1000)
sum+=Array[pos];//Сумма всех элементов массива на периоде МА
}}//for(i=1;i<iMAPeriod;i++,pos--)
{while(pos>0)
{
sum+=Array[pos];
buf[pos]=sum/iMAPeriod;
sum-=Array[pos+iMAPeriod-1];
pos--;
}}//while(pos>0)
{if(pos==0)
{
sum+=Array[pos];
buf[pos]=sum/iMAPeriod;
sum-=Array[pos+iMAPeriod-1];
}}//if(pos==0)
return(buf[Shift+ma_shift]);
}//case MODE_SMA
case MODE_EMA :
{
double pr=2.0/(iMAPeriod+1);
uint pos=total-2;
{while(pos>0)
{
if(pos==total-2) buf[pos+1]=Array[pos+1];
buf[pos]=Array[pos]*pr+buf[pos+1]*(1-pr);
pos--;
}}//while(pos>=0)
{if(pos==0)
{
if(pos==total-2) buf[pos+1]=Array[pos+1];
buf[pos]=Array[pos]*pr+buf[pos+1]*(1-pr);
}}//if(pos==0)
return(buf[Shift+ma_shift]);
}//case MODE_EMA
case MODE_SMMA :
{
double sum=0;
uint i,k,pos;
pos=total-iMAPeriod;
{while(pos>0)
{
{if(pos==total-iMAPeriod)
{
{for(i=0,k=pos;i<iMAPeriod;i++,k++)
{
sum+=Array[k];
buf[k]=0;
}}//for(i=0,k=pos;i<iMAPeriod;i++,k++)
}else{
sum=buf[pos+1]*(iMAPeriod-1)+Array[pos];
}}//if(pos==total-iMAPeriod)
buf[pos]=sum/iMAPeriod;
pos--;
}}//while(pos>0)
{if(pos==0)
{
{if(pos==total-iMAPeriod)
{
{for(i=0,k=pos;i<iMAPeriod;i++,k++)
{
sum+=Array[k];
buf[k]=0;
}}//for(i=0,k=pos;i<iMAPeriod;i++,k++)
}else{
sum=buf[pos+1]*(iMAPeriod-1)+Array[pos];
}}//if(pos==total-iMAPeriod)
buf[pos]=sum/iMAPeriod;
}}//if(pos==0)
return(buf[Shift+ma_shift]);
}//case MODE_SMMA
case MODE_LWMA :
{
double sum=0.0,lsum=0.0;
double price;
uint i,weight=0,pos=total-1;
{for(i=1;i<=iMAPeriod;i++,pos--)
{
price=Array[pos];
sum+=price*i;
lsum+=price;
weight+=i;
}}//for(i=1;i<=iMAPeriod;i++,pos--)
pos++;
i=pos+iMAPeriod;
{while(pos>0)
{
buf[pos]=sum/weight;
if(pos==0) break;
pos--;
i--;
price=Array[pos];
sum=sum-lsum+price*iMAPeriod;
lsum-=Array[i];
lsum+=price;
}}//while(pos>0)
{if(pos==0)
{
buf[pos]=sum/weight;
if(pos==0) break;
pos--;
i--;
price=Array[pos];
sum=sum-lsum+price*iMAPeriod;
lsum-=Array[i];
lsum+=price;
}}//if(pos==0)
return(buf[Shift+ma_shift]);
}
default: {return(0);}
}}//switch(ma_method)
return(0);
}//iMAOnArrayMql4v2()
//
//======================================================================================================
// iBarShiftMql4() - Поиск бара по времени как для mql4.
// Функция возвращает индекс бара, в который попадает указанное время.
//======================================================================================================
int iBarShiftMql4( string symbol,
datetime time,
bool exact=false){
{if(time<0){return(-1);}}
datetime Arr[],time1;
CopyTime(symbol,PERIOD_M1,0,1,Arr);
time1=Arr[0];
{if(CopyTime(symbol,PERIOD_M1,time,time1,Arr)>0)
{
if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
if(time<time1) return(1);
else return(0);
}else{
return(-1);
}}//if(CopyTime(symbol,timeframe,time,time1,Arr)>0)
}//iBarShiftMql4()
//
//PositionModify(Pos_Tick,PositionGetDouble(POSITION_PRICE_OPEN),NewStopLoss,PositionGetDouble(POSITION_TP),0,Red)
//
//======================================================================================================
// PositionModifySL() - Изменение SL TP для позиции
// Вход:
// iPosTick - тикет позиции
// iPosNewSL - Новый SL
// iPosNewTP - Новый TP
//======================================================================================================
bool PositionModifySL( long iPosTick,
double iPosNewSL,
double iPosNewTP){
//bool
// iOrd_inf=false;
//Print("PositionModifySL>>");
//return(true);
{if(!PositionSelectByTicket(iPosTick)){return(false);}};//Выбираем позицию по тикету? Неудачно - следующий
{if(PositionGetDouble(POSITION_VOLUME)<MinLot)//Нулевой объём - к следующему
{
//Print("Return Vol=",PositionGetDouble(POSITION_VOLUME));
return(false);
}else{//Ненулевой объём - модификация
//Print("Request Vol=",PositionGetDouble(POSITION_VOLUME),
// " Type=",EnumToString((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)),
// " Price=",PositionGetDouble(POSITION_PRICE_OPEN),
// " PriceCurr=",PositionGetDouble(POSITION_PRICE_CURRENT),
// " Bid=",gBid,
// " Ask=",gAsk);
//--- Объявление запроса и результата
MqlTradeRequest Request={0};
MqlTradeResult Result={0};
//--- Обнуление значений запроса и результата
ZeroMemory(Request);
ZeroMemory(Result);
//--- установка параметров операции
Request.symbol=PositionGetString(POSITION_SYMBOL);// Символ (инструмент) позиции
Request.action=TRADE_ACTION_SLTP; // Тип торговой операции изменение SL TP
Request.position=iPosTick; // Тикет позиции
Request.sl=iPosNewSL; // Stop Loss позиции
Request.tp=iPosNewTP; // Take Profit позиции
//--- отправка запроса
return(OrderSendAsync(Request,Result)); //Отправляем асинхронно
//return(OrderSend(Request,Result));
}}//if(PositionGetDouble(POSITION_VOLUME)<0.01)
}//PositionModifySL()
//
//======================================================================================================
// PositionCloseBy() - Встречное закрытие позиций. Добавить цикличность до победы
// Вход:
// iPosTick - тикет позиции
// iPosTick - тикет встречной позиции
//======================================================================================================
bool PositionCloseBy( long iPosTick,
long iPosTick2){
bool
iOrd_inf=false;
//--- объявление запроса и результата
MqlTradeRequest Request={0};
MqlTradeResult Result={0};
//--- обнуление значений запроса и результата
ZeroMemory(Request);
ZeroMemory(Result);
//--- установка параметров операции
Request.action=TRADE_ACTION_CLOSE_BY; // тип торговой операции
Request.position=iPosTick; // тикет позиции
Request.position_by=iPosTick2; // тикет встречной позиции
//--- отправка запроса
iOrd_inf=OrderSendAsync(Request,Result);
return(iOrd_inf);
}//PositionCloseBy()
//
//======================================================================================================
// PositionOrderSend() - Отправка запроса на выставление ордера
// Вход:
// iSymbol - инструмент позиции
// iType - тип позиции
//======================================================================================================
uint PositionOrderSend( string iSymbol,
ENUM_ORDER_TYPE iType,
double iVol,
double iPrice,
ulong iSlip,
double iSL,
double iTP,
string iComment,
ulong iMagic,
datetime iExpir,
ulong &iDeal){
bool
iOrd_inf=false;
//--- обнуление значений запроса и результата
MqlTradeRequest Request={0};
MqlTradeResult Result={0};
//ZeroMemory(Request);
//ZeroMemory(Result);
//--- подготовим запрос
Request.action =TRADE_ACTION_DEAL;
Request.magic =iMagic;
Request.type =iType;
Request.symbol =iSymbol;
Request.volume =iVol;
Request.price =iPrice;
Request.sl =iSL;
Request.tp =iTP;
Request.deviation =iSlip;
Request.comment =iComment;
Request.expiration =iExpir;
//--- отправка запроса
//ResetLastError();
iOrd_inf=OrderSend(Request,Result);
//Print("ERR 20=",GetLastError());
iDeal=Result.deal;
return(Result.retcode);
}//PositionOrderSend()
//
//======================================================================================================
// PositionOrderSendAsync() - Встречное закрытие позиций. Добавить цикличность до победы
// Вход:
// iSymbol - инструмент позиции
// iType - тип позиции
//======================================================================================================
bool PositionOrderSendAsync( string iSymbol,
ENUM_ORDER_TYPE iType,
double iVol,
double iPrice,
ulong iSlip,
double iSL,
double iTP,
string iComment,
long iMagic,
datetime iExpir,
ulong &iDeal){
bool
iOrd_inf=false;
//--- обнуление значений запроса и результата
MqlTradeRequest Request={0};
MqlTradeResult Result={0};
ZeroMemory(Request);
ZeroMemory(Result);
//--- подготовим запрос
Request.action =TRADE_ACTION_DEAL;
Request.magic =iMagic;
Request.type =iType;
Request.symbol =iSymbol;
Request.volume =iVol;
Request.price =iPrice;
Request.sl =iSL;
Request.tp =iTP;
Request.deviation =iSlip;
Request.comment =iComment;
Request.expiration =iExpir;
//--- отправка запроса
iOrd_inf=OrderSendAsync(Request,Result);
iDeal=Result.deal;
return(iOrd_inf);
}//PositionOrderSendAsync()
//
//======================================================================================================
// PositionCloseOne() - Закрытие позиции. Добавить цикличность до победы
// Вход:
// iPosTick - тикет позиции
//======================================================================================================
bool PositionCloseOne( ulong iPosTick,
ulong iSlip ){
//Print("PositionCloseOne>>");
//----- Получим дополнительную информацию по позиции
//int q=0;
{if(!PositionSelectByTicket(iPosTick))
{
Print("Close select error iPosTick=",iPosTick);
return(false);
}}//if(!PositionSelectByTicket(iPosTick))
//Print(q,". Close select OK iPosTick=",iPosTick);//А эта выводится... или наоборот
ENUM_POSITION_TYPE Position_Type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // тип позиции
string Position_Symbol=PositionGetString(POSITION_SYMBOL); // символ
//double Position_Volume=PositionGetDouble(POSITION_VOLUME); // объем позиции
//double Position_Price=PositionGetDouble(POSITION_PRICE_OPEN); // цена позиции
//Print("Position>> Type=",EnumToString(Position_Type),
// " Volume=",DoubleToString(Position_Volume,2),
// " Price Open=",DoubleToString(Position_Price,5),
// " gBid=",gBid,
// " gAsk=",gAsk);
bool iOrd_inf=false;
//--- обнуление значений запроса и результата
MqlTradeRequest Request={0};
MqlTradeResult Result={0};
//ZeroMemory(Request);
//ZeroMemory(Result);
//--- подготовим запрос
Request.action =TRADE_ACTION_DEAL;
Request.position =iPosTick; // тикет позиции
Request.volume =PositionGetDouble(POSITION_VOLUME); // объем позиции
Request.deviation =iSlip;
Request.symbol =PositionGetString(POSITION_SYMBOL); // символ позиции
Request.magic =PositionGetInteger(POSITION_MAGIC);
// Request.type =iType;
Request.symbol =Position_Symbol;
// Request.price =iPrice;
// Request.sl =iSL;
// Request.tp =iTP;
// Request.comment =iComment;
// Request.expiration =iExpir;
// //--- установка параметров операции
// request.volume =volume; // объем позиции
// request.deviation=5; // допустимое отклонение от цены
// request.magic =EXPERT_MAGIC; // MagicNumber позиции
//--- установка цены и типа ордера в зависимости от типа позиции
{if(Position_Type==POSITION_TYPE_BUY)
{
//Request.price = SymbolInfoDouble(Position_Symbol,SYMBOL_ASK);
Request.price = SymbolInfoDouble(Position_Symbol,SYMBOL_BID);
Request.type = ORDER_TYPE_SELL;
//Request.price = Position_Price;
}else{
//Request.price = SymbolInfoDouble(Position_Symbol,SYMBOL_BID);
Request.price = SymbolInfoDouble(Position_Symbol,SYMBOL_ASK);
Request.type = ORDER_TYPE_BUY;
//Request.price = Position_Price;
}}//if(type==POSITION_TYPE_BUY)
//--- последняя проверка и отправка запроса
{if(PositionSelectByTicket(iPosTick))
{
iOrd_inf=OrderSend(Request,Result);
{if(PrnClose){Print("Close select OK iPosTick=",iPosTick);}}//Эта строка в тестере упорно не выводится...
}else{
Print("Close select error iPosTick=",iPosTick);
return(false);
}}//if(!PositionSelectByTicket(iPosTick))
return(iOrd_inf);
}//PositionCloseOne()
//
//======================================================================================================
// Load_History() - загрузка истории
// Вход:
// iSymbol - инструмент
// iPeriod - период
// iRequestFirstDate - дата до глубины которой запрашивается подкачка данных
// inBars - размер порции подкачки данных
// iFailCntMax - число попыток получения данных
// Выход:
// код завершения операции (отрицательные - ошибки и некорректности)
//======================================================================================================
int Load_History_( string iSymbol,
ENUM_TIMEFRAMES iPeriod,
datetime iRequestFirstDate,
int inBars,
int iFailCntMax){
datetime iTerminalFirstDate=0;
datetime iTimes[];
ArrayResize(iTimes,inBars);
//--- check symbol
{if((iSymbol==NULL)||(iSymbol==""))
{
iSymbol=Symbol();
}}//if((iSymbol==NULL)||(iSymbol==""))
//--- check period
{if(iPeriod==PERIOD_CURRENT)
{
iPeriod=Period();
}}//if(iPeriod==PERIOD_CURRENT)
//--- check if symbol is selected in the MarketWatch
{if(!SymbolInfoInteger(iSymbol,SYMBOL_SELECT))
{
//Неопознанный символ для данного рынка
{if(GetLastError()==ERR_MARKET_UNKNOWN_SYMBOL)
{
return(-1);
}}//if(GetLastError()==ERR_MARKET_UNKNOWN_SYMBOL)
//Попытка внести символ в окно "Обзор рынка"
{if(!SymbolSelect(iSymbol,true))
{
Print(__FUNCTION__,"(): Не удалось добавить символ ",iSymbol," в окно MarketWatch!!!");
return(-6);
}}//if(!SymbolSelect(iSymbol,true))
}}//(!SymbolInfoInteger(iSymbol,SYMBOL_SELECT))
//--- check if data is present
//Теперь необходимо получить начальную дату по уже имеющейся истории для указанной пары символ/период.
//Возможно, что значение входного параметра iRequestFirstDate, переданного функции Load_History()
//попадает в интервал уже доступной истории, и тогда никакого запроса к торговому серверу не потребуется.
//Для получения самой первой даты по символу-периоду на данный момент предназначена функция SeriesInfoInteger()
//с модификатором SERIES_FIRSTDATE.
SeriesInfoInteger(iSymbol,iPeriod,SERIES_FIRSTDATE,iTerminalFirstDate);//The very first date for the symbol-period for the current moment in terminal
{if((iTerminalFirstDate>0)&&(iTerminalFirstDate<=iRequestFirstDate))//Данные есть и перекрывают диапазон запроса
{
return(1);//Данные есть и перекрывают диапазон запроса, докачка не потребовалась
}}//if((iTerminalFirstDate>0)&&(iTerminalFirstDate<=iRequestFirstDate))
//--- don't ask for load of its own data if it is an indicator
//Следующая важная проверка — проверка типа программы, из которой вызывается функция.
//Напомним, что отправка запроса на обновление таймсерии с тем же периодом, что и у индикатора,
//вызывающего обновление, крайне нежелательна. Нежелательность запроса данных по тому же символу-периоду,
//что и у индикатора обусловлена тем, что обновление исторических данных производится в том же потоке,
//в котором работает индикатор. Поэтому велика вероятность клинча.
//Для проверки используем функцию MQL5InfoInteger() с модификатором MQL5_PROGRAM_TYPE.
{if(
(MQL5InfoInteger(MQL5_PROGRAM_TYPE)==PROGRAM_INDICATOR)
&& (Period()==iPeriod)
&& (Symbol()==iSymbol)
)
{
return(-4);
}}//if(
//--- second attempt
//Если мы успешно прошли все проверки, то сделаем последнюю попытку обойтись без обращения к торговому серверу.
//Сначала узнаем начальную дату iTerminalFirstDate, для которой доступны минутные данные в формате HCC.
//Запросим это значение функцией SeriesInfoInteger() с модификатором SERIES_TERMINAL_FIRSTDATE
//и опять сравним со значением параметра iRequestFirstDate.
{if(SeriesInfoInteger(iSymbol,iPeriod,SERIES_TERMINAL_FIRSTDATE,iTerminalFirstDate))//Если значение получено:Самая первая дата в истории независимо от периода (минутные???) в клиентском терминале и она не перекрывает диапазон запроса
{
//--- there is loaded data to build timeseries
{if(iTerminalFirstDate>0)//Данные есть
{
//--- force timeseries build
{if(CopyTime(iSymbol,iPeriod,iTerminalFirstDate+PeriodSeconds(iPeriod),1,iTimes)>0)//Пытаемся скопировать на 1 бар дальше, чем в клиентском терминале
{
//--- check date
{if(SeriesInfoInteger(iSymbol,iPeriod,SERIES_FIRSTDATE,iTerminalFirstDate))//Если значение получено
{
{if((iTerminalFirstDate>0)&&(iTerminalFirstDate<=iRequestFirstDate))//Данные есть и перекрывают диапазон запроса
{
return(2);//Данные есть и перекрывают диапазон запроса, потребовалась минимальная докачка в 1 бар
}}//if((iTerminalFirstDate>0)&&(iTerminalFirstDate<=iRequestFirstDate))
}}//if(SeriesInfoInteger(iSymbol,iPeriod,SERIES_FIRSTDATE,iTerminalFirstDate))
}}//if(CopyTime(iSymbol,iPeriod,iTerminalFirstDate+PeriodSeconds(iPeriod),1,iTimes)>0)
}}//if(iTerminalFirstDate>0)
}}//if(SeriesInfoInteger(iSymbol,PERIOD_M1,SERIES_TERMINAL_FIRSTDATE,iTerminalFirstDate))
//--- max bars in chart from terminal options
int iMaxBars=TerminalInfoInteger(TERMINAL_MAXBARS);//Максимальное количество баров на графике
//--- load symbol history info
datetime iFirstServerDate=0;
{while(
(!SeriesInfoInteger(iSymbol,PERIOD_M1,SERIES_SERVER_FIRSTDATE,iFirstServerDate))
&&
(!IsStopped())
)
{
Sleep(5);
}}//while(
//--- fix start date for loading
{if(iFirstServerDate>iRequestFirstDate)
{
iRequestFirstDate=iFirstServerDate;
}}//if(first_server_date>iRequestFirstDate)
{if((iTerminalFirstDate>0)&&(iTerminalFirstDate<iFirstServerDate))
{
Print(__FUNCTION__,"(): Warning: first server date ",iFirstServerDate," for ",iSymbol,
" does not match to first series date ",iTerminalFirstDate);
}}//if((iTerminalFirstDate>0)&&(iTerminalFirstDate<first_server_date))
//--- load data step by step
int iFailCnt=0;
{while(!IsStopped())
{
//--- 1.дождаться окончания процесса перестройки таймсерии
{while(
(!SeriesInfoInteger(iSymbol,iPeriod,SERIES_SYNCHRONIZED))//проверка синхронности данных
&&
(!IsStopped())
)
{//Если не синхронны и не подготовка к остановке
Sleep(5);//Маленько подождать...
}}//while(
//--- 2.запросим сколько баров мы теперь имеем
int iBars=Bars(iSymbol,iPeriod);//Общее количество всех баров в истории
{if(iBars>0)
{
//Если есть бары в истории
//--- баров больше, чем можно отобразить на графике, выходим
{if(iBars>=iMaxBars)//Количество баров в истории больше чем максимальное количество баров на графике
{
return(-2);
}}//if(iBars>=iMaxBars)
//--- 3. узнаем текущую начальную дату в таймсерии
{if(SeriesInfoInteger(iSymbol,iPeriod,SERIES_FIRSTDATE,iTerminalFirstDate))//Получаем в first_date самую первую дату по символу на сервере
{
//значение было помещено в переменную iTerminalFirstDate
{if((iTerminalFirstDate>0)&&(iTerminalFirstDate<=iRequestFirstDate))//Дата есть и меньше требуемой
{
return(0);
}}//if((iTerminalFirstDate>0)&&(iTerminalFirstDate<=iRequestFirstDate))
}else{
//значение НЕ было помещено в переменную iTerminalFirstDate, возвращает false.
//Чтобы получить дополнительную информацию об ошибке, необходимо вызвать функцию GetLastError().
Print("Exception 0007");
return(-7);
}}//if(SeriesInfoInteger(iSymbol,iPeriod,SERIES_FIRSTDATE,iTerminalFirstDate))
}else{
//данные для таймсерии с указанными параметрами при вызове функции Bars() еще не сформированы в терминале,
//или данные таймсерии в момент вызова функции не синхронизированы с торговым сервером
Print("Exception 0008");
return(-8);
}}//if(iBars>0)
//4. Запросим новую порцию истории в inBars баров у торгового сервера от последнего доступного бара под номером iBars
int iCopied=CopyTime(iSymbol,iPeriod,iBars,inBars,iTimes);//Запрос подкачки ещё inBars баров истории с бара iBars
{if(iCopied>0)
{
//--- check for data
{if(iTimes[0]<=iRequestFirstDate)//самое старое скопированное значение раньше даты начала, готово (массив не as_series!!!)
{
return(0);
}}//if(iTimes[0]<=iRequestFirstDate)
{if(iBars+iCopied>=iMaxBars)// баров стало больше, чем можно размещать на график, готово
{
return(-2);
}}//if(iBars+iCopied>=iMaxBars)
iFailCnt=0;
}else{
//--- no more than iFailCntMax failed attempts
iFailCnt++;
{if(iFailCnt>=iFailCntMax)
{
return(-5);
}}//if(fail_cnt>=iFailCntMax)
Sleep(10);
}}//if(iCopied>0)
}}//while(!IsStopped())
//----+ stopped
return(-3);
}//Load_History()
//
//======================================================================================================
// Load_History2() - загрузка истории в терминал
// Вход:
// iSymbol - инструмент
// iRequestFirstDate - дата до глубины которой запрашивается подкачка данных
// inBars - размер порции подкачки данных
// iFailCnt... - число попыток получения данных
// Выход:
// функция: код завершения операции (отрицательные - ошибки и некорректности)
// iFirstDate - гарантированное время начала данных
//======================================================================================================
int Load_History2( string iSymbol,
datetime iRequestFirstDate,
datetime &iFirstDate,
int &iBarsN,
int inBars=100,
bool iPrintDebug=false,
int iFailCntTerminalFirstDateMax=10,//для запроса данных терминала
int iFailCntServerFirstDateMax=10,//для запроса данных сервера
int iFailCntCopyRatesMax=10,//для попыток копирования данных
int iFailCntSyncMax=10)//для попыток синхронозации
{
iBarsN=0;//Обнуляем выходной параметр - количество баров на графике
iFirstDate=0;//Обнуляем выходной параметр - время начала данных
//----- Временный массив для подкачки данных
MqlRates iRates[];
ArraySetAsSeries(iRates,false);//Гарантированно не AsSeries
ArrayResize(iRates,inBars);
//----- Проверка символа на специальные значения
{if((iSymbol==NULL)||(iSymbol==""))
{
iSymbol=TheSymbol;
}}//if((iSymbol==NULL)||(iSymbol==""))
//----- Проверка символа на присутствие в Обзоре Рынка (MarketWatch)
{if(!SymbolInfoInteger(iSymbol,SYMBOL_SELECT))
{
//Неопознанный символ для данного рынка
{if(GetLastError()==ERR_MARKET_UNKNOWN_SYMBOL)
{
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-1) >> Неопознанный символ ",iSymbol," для данного рынка!");}}
return(-1);//Неопознанный символ для данного рынка
}}//if(GetLastError()==ERR_MARKET_UNKNOWN_SYMBOL)
//----- Попытка внести символ в окно "Обзор рынка" если его там не было
{if(!SymbolSelect(iSymbol,true))
{
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-6) >> Не удалось добавить символ ",iSymbol," в окно MarketWatch!");}}
return(-6);//Не удалось добавить символ в окно MarketWatch
}}//if(!SymbolSelect(iSymbol,true))
}}//(!SymbolInfoInteger(iSymbol,SYMBOL_SELECT))
//----- Проверка данных на наличие
//Теперь необходимо получить начальную дату по уже имеющейся истории для указанной пары символ/период.
//Возможно, что значение входного параметра iRequestFirstDate, переданного функции Load_History()
//попадает в интервал уже доступной истории, и тогда никакого запроса к торговому серверу не потребуется.
//Для получения самой первой даты по символу-периоду на данный момент предназначена функция SeriesInfoInteger()
//с модификатором SERIES_FIRSTDATE.
datetime iTerminalFirstDate=0;
int iFailCntTerminalFirstDate=iFailCntTerminalFirstDateMax;
/*A*/{while(iFailCntTerminalFirstDate>=1)//Продолжаем, пока счетчик попыток не обнулился
{
{if(IsStopped()){return(-101);}}
/*B*/ {if(//Самая первая дата в истории независимо от периода (минутные???) в клиентском терминале
(SeriesInfoInteger(iSymbol,PERIOD_M1,SERIES_TERMINAL_FIRSTDATE,iTerminalFirstDate))//Данные получены
&&
(iTerminalFirstDate>0)//Данные реальны
)
{//Данные терминала получены
iFailCntTerminalFirstDate=iFailCntTerminalFirstDateMax;//Устанавливаем счетчик попыток обращения к данным
/*C*/ {if(iTerminalFirstDate<=iRequestFirstDate)//Данные перекрывают диапазон запроса
{
iBarsN=Bars(iSymbol,PERIOD_M1);//Общее количество всех баров в истории терминала - на выход
iFirstDate=iTerminalFirstDate;//Время начала данных терминала - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Normal (1) >> Данные перекрывают диапазон запроса. B=",iBarsN," T=",iFirstDate);}}
return(1);//Выход с кодом возврата 1 из цикла /*A*/
/*C*/ }else{//Данные есть, но не перекрывают диапазон запроса - нужна докачка
//----- Загрузка информации об истории на сервере
datetime iFirstServerDate=0;
int iFailCntServerFirstDate=iFailCntServerFirstDateMax;//Число попыток обращения к информации сервера
/*D*/ {while(iFailCntServerFirstDate>=1)//Продолжаем, пока счетчик попыток не обнулился
{
{if(IsStopped()){return(-101);}}
//Анализ доступности информации сервера
/*E*/ {if(//Самая первая дата в истории независимо от периода (минутки?) на сервере
(SeriesInfoInteger(iSymbol,PERIOD_M1,SERIES_SERVER_FIRSTDATE,iFirstServerDate))//Данные получены
&&
(iFirstServerDate>0)//Данные реальны
)
{//Данные об истории с сервера получены
/*F*/ {if(iFirstServerDate<=iRequestFirstDate)//Истории на сервере достаточно
{
//Данных на сервере достаточно для обработки запроса
//Тут будем пытаться считать запрошенное количество данных
//--- load data step by step
int iFailCntCopyRates=iFailCntCopyRatesMax;//Устанавливаем счетчик попыток загрузки данных с сервера
/*G*/ {while(iFailCntCopyRates>=1)//Продолжаем, пока счетчик попыток не обнулился
{
{if(IsStopped()){return(-101);}}
//--- 1.дождаться окончания процесса перестройки таймсерии
int iFailCntSync=iFailCntSyncMax;//Устанавливаем счетчик попыток синхронизации данных
/*H*/ {while(iFailCntSync>=1)//Продолжаем попытки синхронизации, пока счетчик попыток не обнулился
{//Проверка синхронности данных
{if(IsStopped()){return(-101);}}
/*I*/ {if((bool)SeriesInfoInteger(iSymbol,PERIOD_M1,SERIES_SYNCHRONIZED))//Проверка синхронности данных
{//Если данные синхронны - выполняем загрузку
iFailCntSync=iFailCntSyncMax;//Устанавливаем счетчик попыток синхронизации данных
//--- 2.запросим сколько баров мы теперь имеем в истории терминала
int iBars=Bars(iSymbol,PERIOD_M1);//Общее количество всех баров в истории терминала
/*J*/ {if(iBars>0)
{
//Если есть бары в истории и синхронизировано и сформировано
//--- max bars in chart from terminal options
int iTerminalMaxBars=TerminalInfoInteger(TERMINAL_MAXBARS);//Максимальное количество баров на графике установленное в настройках
/*K*/ {if(iBars<iTerminalMaxBars)
{//Количество баров в истории терминала меньше чем максимальное количество баров на графике заданное в настройках
//Обработка докачки
//--- 3. узнаем текущую начальную дату в таймсерии (истории терминала???)
/*L*/ datetime iTerminalFirstDate2=0;
{if(SeriesInfoInteger(iSymbol,PERIOD_M1,SERIES_TERMINAL_FIRSTDATE,iTerminalFirstDate2))//Получаем в iTerminalFirstDate самую первую дату по символу в терминале
{
/*M*/ {if(
(iTerminalFirstDate2>0)//Дата есть
&&
(iTerminalFirstDate2<=iRequestFirstDate)//Дата меньше требуемой
)
{//Дата начала данных терминала меньше или равна запрошенной
iBarsN=iBars;//Общее количество всех баров в истории терминала - на выход
iFirstDate=iTerminalFirstDate2;//Время начала данных терминала - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Normal (2) >> Дата начала данных терминала меньше или равна запрошенной. B=",iBarsN," T=",iFirstDate);}}
return(2);//Дата начала данных терминала меньше или равна запрошенной
/*M*/ }else{//Дата начала данных терминала больше запрошенной
//Обработка докачки
//4. Запросим новую порцию истории в inBars баров у торгового сервера от последнего доступного бара под номером iBars дальше в прошлое
int iCopied=CopyRates(iSymbol,PERIOD_M1,iBars,inBars,iRates);//Запрос подкачки в терминал ещё inBars баров истории начиная с бара iBars и дальше в прошлое
/*N*/ {if(iCopied>0)
{//Данные скопированы
//Проверка условия завершения закачки
/*O*/ {if(iRates[0].time<=iRequestFirstDate)//самое старое скопированное значение раньше даты начала, готово (массив iRates не as_series!!!)
{//Дата начала данных терминала меньше или равна запрошенной
iBarsN=iBars+iCopied;//Общее количество всех баров в истории терминала - на выход
iFirstDate=iRates[0].time;//Время начала данных терминала - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Normal (3) >> Дата начала данных терминала меньше или равна запрошенной. B=",iBarsN," T=",iFirstDate);}}
return(3);//Дата начала данных терминала меньше или равна запрошенной
/*O*/ }else{//Дата терминала больше запрошенной
/*P*/ {if(iBars+iCopied>=iTerminalMaxBars)//После докачки баров стало больше, чем можно размещать на график, вернуть достигнутое время
{//Продолжение докачки невозможно - превышено максимальное количество баров
iBarsN=iBars+iCopied;//Общее количество всех баров в истории терминала - на выход
iFirstDate=iRates[0].time;//Время начала данных терминала - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-2) >> После докачки баров стало больше, чем можно размещать на график! B=",iBarsN," T=",iFirstDate);}}
return(-2);//После докачки баров стало больше, чем можно размещать на график
/*P*/ }else{//Продолжение возможно - максимальное количество баров не превышено
//Тут: данные были скопированы, но условие завершения докачки не соблюдено - продолжим докачку
iFailCntCopyRates=iFailCntCopyRatesMax;//Устанавливаем счетчик попыток докачки в исходное состояние
/*P*/ }}//if(iBars+iCopied>=iTerminalMaxBars)
/*O*/ }}//if(iTimes[0]<=iRequestFirstDate)
/*N*/ }else{//Данные НЕ скопированы
/*Q*/ {if(iFailCntCopyRates>1)
{//Количество попыток докачки НЕ исчерпано
iFailCntCopyRates--;//Декремент количества попыток докачки
Sleep(5);//Небольшая задержка
/*Q*/ }else{//Количество попыток докачки исчерпано
iBarsN=iBars;//Общее количество всех баров в истории терминала - на выход
iFirstDate=iTerminalFirstDate2;//Время начала данных терминала - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-5) >> Количество попыток докачки исчерпано! B=",iBarsN," T=",iFirstDate);}}
return(-5);//Количество попыток исчерпано
/*Q*/ }}//if(iFailCntCopyRates>1)
/*N*/ }}//if(iCopied>0)
/*M*/ }}//if((iTerminalFirstDate>0)&&(iTerminalFirstDate<=iRequestFirstDate))
/*L*/ }else{//Значение НЕ было помещено в переменную iTerminalFirstDate
/*R*/ {if(iFailCntCopyRates>1)
{//Количество попыток докачки НЕ исчерпано
iFailCntCopyRates--;//Декремент количества попыток докачки
Sleep(5);//Небольшая задержка
/*R*/ }else{//Количество попыток докачки исчерпано
iBarsN=iBars;//Общее количество всех баров в истории терминала - на выход
iFirstDate=iTerminalFirstDate;//Время начала данных терминала - на выход
//Чтобы получить дополнительную информацию об ошибке, необходимо вызвать функцию GetLastError().
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-7) >> Значение TerminalFirstDate НЕ получено! Количество попыток докачки исчерпано! B=",iBarsN," T=",iFirstDate);}}
return(-7);//Количество попыток исчерпано
/*R*/ }}//if(iFailCntCopyRates>1)
/*L*/ }}//if(SeriesInfoInteger(iSymbol,iPeriod,SERIES_FIRSTDATE,iTerminalFirstDate2))
/*K*/ }else{//Количество баров в истории больше чем максимально возможное количество баров на графике заданное в настройках
//Исправить невозможно - по любому выход
iBarsN=iBars;//Общее количество всех баров в истории терминала - на выход
iFirstDate=iTerminalFirstDate;//Время начала данных терминала - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-8) >> Количество баров в истории больше, чем можно размещать на график! B=",iBarsN," T=",iFirstDate);}}
return(-8);
/*K*/ }}//(iBars<iTerminalMaxBars)
/*J*/ }else{
//Данные для таймсерии с указанными параметрами при вызове функции Bars() еще не сформированы в терминале,
//или данные таймсерии в момент вызова функции не синхронизированы с торговым сервером
{if(iFailCntSync>1)
{//Счетчик попыток получения данных сервера НЕ исчерпан
iFailCntSync--;//Декремент счетчика попыток синхронизации
Sleep(5);//Небольшая задержка...
}else{//Счетчик попыток синхронизации исчерпан
iBarsN=iBars;//Общее количество всех баров в истории терминала - на выход
iFirstDate=iTerminalFirstDate;//Время начала данных терминала - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-9) >> Данные при вызове Bars() не сформированы за ",iFailCntSyncMax," попыток! B=",iBarsN," T=",iFirstDate);}}
return(-9);//iFailCntSync error
}}//if(iFailCntSync>1)
/*J*/ }}//if(iBars>0)
/*I*/ }else{//Если данные не синхронны
{if(iFailCntSync>1)
{//Счетчик попыток получения синхронизации НЕ исчерпан
iFailCntSync--;//Декремент счетчика попыток синхронизации
Sleep(10);//Небольшая задержка...
}else{//Счетчик попыток синхронизации исчерпан
iBarsN=Bars(iSymbol,PERIOD_M1);//Общее количество всех баров в истории терминала - на выход
iFirstDate=iTerminalFirstDate;//Время начала данных терминала - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-10) >> Данные НЕ синхронизированы за ",iFailCntSyncMax," попыток! B=",iBarsN," T=",iFirstDate);}}
return(-10);//iFailCntSync error
}}//if(iFailCntSync>1)
/*I*/ }}//if((bool)SeriesInfoInteger(iSymbol,PERIOD_M1,SERIES_SYNCHRONIZED))
/*H*/ }}//while( (iFailCntSync>=1)...
/*G*/ }}//while( (iFailCntCopyRates>=1)...
/*F*/ }else{//Данных на сервере НЕ достаточно
//Выходим с признаком ошибки и количеством скачанного
iBarsN=Bars(iSymbol,PERIOD_M1);//Общее количество всех баров в истории терминала - на выход
iFirstDate=iFirstServerDate;//Время начала данных сервера - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-11) >> Данных на сервере НЕ достаточно!");}}
return(-11);//Данных на сервере НЕ достаточно
/*F*/ }}//if(iFirstServerDate>iRequestFirstDate)
/*E*/ }else{//Данные об истории с сервера НЕ получены
{if(iFailCntServerFirstDate>1)
{//Счетчик попыток получения данных сервера НЕ исчерпан
iFailCntServerFirstDate--;//Декремент счетчика попыток получения данных сервера
Sleep(5);//Небольшая задержка...
}else{//Счетчик попыток получения данных сервера исчерпан
iBarsN=Bars(iSymbol,PERIOD_M1);//Общее количество всех баров в истории терминала - на выход
iFirstDate=iTerminalFirstDate;//Время начала данных терминала - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-12) >> Данные об истории сервера НЕ получены за ",iFailCntServerFirstDateMax," попыток! B=",iBarsN," T=",iFirstDate);}}
return(-12);//iFailCntServerFirstDate error
}}//if(iFailCntFirstServerDate>1)
/*E*/ }}//if( (SeriesInfoInteger(iSymbol,PERIOD_M1,SERIES_SERVER_FIRSTDATE,iFirstServerDate))
/*D*/ }}//while( (iFailCntServerFirstDate>=1) && (!IsStopped())
/*C*/ }}//if(iTerminalFirstDate<=iRequestFirstDate))
/*B*/ }else{//Данные терминала НЕ получены
{if(iFailCntTerminalFirstDate>1)
{//Счетчик попыток получения данных терминала НЕ исчерпан
iFailCntTerminalFirstDate--;//Декремент счетчика попыток получения данных терминала
Sleep(5);//Небольшая задержка...
}else{//Счетчик попыток получения данных терминала исчерпан
iBarsN=Bars(iSymbol,PERIOD_M1);//Общее количество всех баров в истории терминала - на выход
iFirstDate=iTerminalFirstDate;//Время начала данных терминала - на выход
{if(iPrintDebug){Print(__FUNCTION__,"() Error (-13) >> Данные терминала НЕ получены за ",iFailCntTerminalFirstDateMax," попыток !");}}
return(-13);//iFailCntTerminalFirstDate error
}}//if(iFailCntTerminalFirstDate<=0)
/*B*/ }}//if(iTerminalFirstDate>0)
/*A*/}}//while( (iFailCntTerminalFirstDate>=1) && (!IsStopped())
//Коды возврата
// -101 Завершение по IsStopped()
// -100 Завершение по исчерпанию счетчика TerminalFirstDate ???
return(-100);
}//Load_History2()
//