//+------------------------------------------------------------------+
//| Charlie.mq4 |
//| Copyright 2017, Silentspec. |
//| https://www.tradelikeapro.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Silentspec"
#property link "https://www.tradelikeapro.ru"
#property version "1.08"
#property strict
#include <WinUser32.mqh>
#import "user32.dll"
// Считывает описатель оpгана упpавления, содеpжащийся в указанном блоке диалога. Возвpащаемое значение: идентификатоp оpгана упpавления; 0 - если указанный оpган упpавления не существует.
int GetDlgItem(int hDlg, // Блок диалога, содеpжащий оpган упpавления.
int nIDDlgItem); // Идентификатоp оpгана упpавления.
// Возвращает идентификатор hierarchyid, представляющий n-го предка данного элемента.
int GetAncestor(int hWnd, // Идентификатоp окна.
int gaFlags); // Уровень окна от текущего окна (1, 2, 3...).
int SendMessageA(int hWnd, // Окно, пpинимающее сообщение или $FFFF для посылки всем всплывающим окнам в системе.
int Msg, // Тип сообщения.
int wParam, // Дополнительная инфоpмация о сообщении.
int& lParam[]); // Дополнительная инфоpмация о сообщении.
int PostMessageA (int hWnd, int Msg, int wParam, string lParam);
#import
extern bool UseTestTrade = false; //Тестовая торговля с кнопок
extern int MyMagic = 0;
extern string TestParams = "Параметры тестирования";
extern string EAName = "Charlie_108";
extern bool UseVirtualTrade = false; //Виртуальная торговля
extern bool UseRealTrade = true; //Реальная торговля
extern bool WeekendVTradeFile = false; //Закрывать файл виртуальной торговли на выходной
extern bool WriteTestInfo = false; //Создать файл тестирования
extern double Loss = 1.0;
extern double Profit = 0.85;
extern string MMParams = "Параметры манименеджмента";
enum MMVAR
{
MMVAR1=1, // Фикс лот
MMVAR2=2, // Риск в % от депозита
MMVAR3=3, // Ступенчатое повышение
};
input MMVAR MMVariant = 2;
extern string MM01 = " - фикс лот";
extern double Lot = 1;
extern string MM02 = " - риск в % от депо";
extern double Risk = 3;
extern string MM03 = " - ступенчатое повышение лота";
extern double StartDepo = 30;
extern double Step = 0.5;
extern double StepDelta = 10;
extern double MaxRisk = 30;
extern double MaxOrders = 10;
extern string ServiceParams = "Выбор брокера";
enum BROVAR
{
BROVAR1=1, // Grand
BROVAR2=2, // WForex Anerica
BROVAR3=3, // WForex Europe
BROVAR4=4, // GDMFX
BROVAR5=5, // Larson
BROVAR6=6, // MikiForex
BROVAR7=7, // NoaFX
BROVAR8=8, // StarfishFX
BROVAR9=9, // Clmforex
BROVAR10=10, // RinkostMarkets
BROVAR11=11, // GoMarkets
BROVAR12=12, // DirectFX
};
input BROVAR BrokerVariant = 1;
//+------------------------------------------------------------------+
extern string Settings03 = "====Расписание====";
extern int GMTOffset = 2;
extern bool CalculateDST = true;
enum DSTVAR
{
DSTVAR0=0, // Европа
DSTVAR1=1, // Америка
};
input DSTVAR DSTVariant = 1;
extern bool UseWeekEndRollover = true;
extern bool MondayTrade = true;
extern bool TuesdayTrade = true;
extern bool WednesdayTrade = true;
extern bool ThursdayTrade = true;
extern bool FridayTrade = true;
extern string Settings04 = "====Сервисные настройки====";
extern bool UseDebug = true;
extern int RetryAttempts = 30;
extern bool MailSend = true;
extern bool PushSend = true;
extern string Settings08 = "====Торговые настройки====";
extern int Expiration = 60;
extern int WPRPeriod = 4;
extern double WPREnterLevel = 20;
extern int KCPeriod = 60;
extern double KCPipDev = -10;
extern double KCDev = 0.6;
extern int WPR2Period = 4;
extern double WPR2EnterLevel = 18;
extern int KC2Period = 30;
extern double KC2PipDev = -5;
extern double KC2Dev = 1.2;
extern int RSIPer = 2;
extern double RSIEnterLevel = 30;
extern string Settings033 = "====Часы работы====";
extern bool Hour0 = true;
extern bool Hour1 = true;
extern bool Hour2 = true;
extern bool Hour3 = true;
extern bool Hour4 = true;
extern bool Hour5 = true;
extern bool Hour6 = true;
extern bool Hour7 = true;
extern bool Hour8 = true;
extern bool Hour9 = true;
extern bool Hour10 = true;
extern bool Hour11 = true;
extern bool Hour12 = true;
extern bool Hour13 = true;
extern bool Hour14 = true;
extern bool Hour15 = true;
extern bool Hour16 = true;
extern bool Hour17 = true;
extern bool Hour18 = true;
extern bool Hour19 = true;
extern bool Hour20 = true;
extern bool Hour21 = true;
extern bool Hour22 = true;
extern bool Hour23 = true;
int SleepTime = 3;
int SleepMaximum = 15;
datetime FirstOpenTime = 0;
double FirstOpenPrice=0;
string MyPrefix = "";
string MySuffix = "";
string Comm="";
datetime VOrderOpenTime = 0;
double VOrderOpenPrice = 0;
double VOrderOpenLots = 0;
string FileNameVT=_Symbol+"_"+EAName+"_VirtualTrades.csv";
int HandleVT=0;
bool VOrderBuy = false;
bool VOrderSell = false;
int Magic=0;
//+------------------------------------------------------------------+
void OrderCloseFuncTest(int expiration)
{
int ticket=0,n=0,i=0, err;
for(i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(SELECT_BY_POS,MODE_TRADES))
{
if(OrderSymbol() == _Symbol && OrderMagicNumber() == Magic && TimeCurrent() - OrderOpenTime() >= expiration*60)
{
if(OrderType() == OP_BUY)
{
RefreshRates();
ticket=OrderClose(OrderTicket(), OrderLots(), Bid, 1, Green);
err = GetLastError();
if(err>0) Print("Ошибка : ",0);
else if(UseDebug) Print("Ордер закрыт.");
}
if(OrderType() == OP_SELL)
{
RefreshRates();
ticket=OrderClose(OrderTicket(), OrderLots(), Ask, 1, Green);
err = GetLastError();
if(err>0) Print("Ошибка : ",0);
else if(UseDebug) Print("Ордер закрыт.");
}
}
}
}
return;
}
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(UseDebug) Print("Начинаем инициализацию. Ожидайте...");
Sleep(5000);
int err;
if (_Digits==3||_Digits==5)
{
KCPipDev*=10;
KC2PipDev*=10;
}
SetPrefSuff();
if(UseDebug) Print("Префиксы и суффиксы определены: Префикс = ", MyPrefix, ", Суффикс = " + MySuffix);
if(UseVirtualTrade)
{
HandleVT=FileOpen(FileNameVT, FILE_WRITE, ";");
err = GetLastError();
if(err>0) Print("Файл виртуальной торговли не создан. Ошибка: ",0);
}
if(MyMagic==0) Magic = makeMagicNumber(WindowExpertName() + Symbol() + IntegerToString(Period())); // Генерация мэджика
if(MyMagic!=0) Magic = MyMagic;
if(Magic == 0 && UseDebug) Print("Ошибка! Magic равен нулю! Функция makeMagicNumber почему то не сработала!");
if(UseDebug) Print("Массивы настроек заполнены. Начинаем работу.");
PrintAccParams();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
switch (_UninitReason)
{
case REASON_ACCOUNT:
Print(" Советник остановлен. Пара "+Symbol()+". Аккаунт сменен.");
break;
case REASON_CHARTCHANGE:
Print(" Советник остановлен Пара "+Symbol()+". Смена таймфрейма.");
break;
case REASON_CHARTCLOSE:
Print(" Советник остановлен. Пара "+Symbol()+". График закрыт.");
break;
case REASON_PARAMETERS:
Print(" Советник остановлен. Пара "+Symbol()+". Параметры советника изменены.");
break;
case REASON_RECOMPILE:
Print(" Советник остановлен. Пара "+Symbol()+". Перекомпиляция советника.");
break;
case REASON_REMOVE:
Print(" Советник остановлен. Пара "+Symbol()+". Советник был удален с графика.");
break;
case REASON_TEMPLATE:
Print(" Советник остановлен. Пара "+Symbol()+". Новый шаблон загружен на график.");
break;
default:
Print(" Советник остановлен. Пара "+Symbol());
}
if(UseVirtualTrade)
{
FileClose(HandleVT);
if(UseDebug) Print("Файл виртуальной торговли закрыт.");
}
//clearChart();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(IsNewBar(1,PERIOD_M1))
{
if(!CheckStatus())
{
Print("Критическая ошибка! Останавливаем советник.");
if(MailSend) SendMail("Критическая ошибка","Советник Charlie на паре "+_Symbol+" остановлен! Брокер:"+AccountInfoString(ACCOUNT_COMPANY));
if(PushSend) SendNotification("Советник Charlie на паре "+_Symbol+" остановлен! Брокер:"+AccountInfoString(ACCOUNT_COMPANY));
ExpertRemove();
}
if(UseVirtualTrade&&WeekendVTradeFile)
{
if(DayOfWeek()==5&&Hour()==23&&Minute()==45)
{
FileClose(HandleVT);
if(UseDebug) Print("Файл виртуальной торговли закрыт.");
}
if(DayOfWeek()==1&&Hour()==0&&Minute()==5)
{
int err=0;
HandleVT=FileOpen(FileNameVT, FILE_WRITE, ";");
err = GetLastError();
if(err>0) Print("Файл виртуальной торговли не создан. Ошибка: ",0);
}
}
if(UseVirtualTrade&&(VOrderBuy||VOrderSell))
{
VOrderClose(Expiration);
}
if(IsTesting())
{
OrderCloseFuncTest(Expiration);
}
if(TimeFilter()&&UseRealTrade&&CountSell() + CountBuy() == 0)
{
if(SignalOpen() == OP_BUY)
{
if(UseDebug) Print("Пробуем послать ордер в покупку");
if(UseRealTrade) OpenOrder(OP_BUY);
}
if(SignalOpen() == OP_SELL)
{
if(UseDebug) Print("Пробуем послать ордер в продажу");
if(UseRealTrade) OpenOrder(OP_SELL);
}
}
if(UseVirtualTrade&&!VOrderBuy&&!VOrderSell)
{
if(SignalOpen() == OP_BUY)
{
if(UseDebug) Print("Шлем виртуальный ордер в покупку");
if(UseVirtualTrade) VOpenOrder(OP_BUY);
}
if(SignalOpen() == OP_SELL)
{
if(UseDebug) Print("Шлем виртуальный ордер в продажу");
if(UseVirtualTrade) VOpenOrder(OP_SELL);
}
}
}
}
//+------------------------------------------------------------------+
int CountBuy()
{
int count = 0;
for (int i=0; i<OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == _Symbol &&
OrderMagicNumber() == Magic &&
OrderType() == OP_BUY)
count++;
}
}
return(count);
}
//+------------------------------------------------------------------+
int CountSell()
{
int count = 0;
for (int i=0; i<OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == _Symbol &&
OrderMagicNumber() == Magic &&
OrderType() == OP_SELL)
count++;
}
}
return(count);
}
//+------------------------------------------------------------------+
//| New bar function |
//+------------------------------------------------------------------+
bool IsNewBar(int mode=0,int period=0)
{
//0 - при первом запуске возвращает true
//1 - при первом запуске ожидает следующий бар
static datetime tm[10];
int t=tfA(period);
if(tm[t]==0&&mode==1) tm[t]=iTime(_Symbol,period,0);
if(tm[t]==iTime(_Symbol,period,0)) return (false);
tm[t]=iTime(_Symbol,period,0);
return (true);
}
int tfA(int tf)
{
switch (tf)
{
case PERIOD_M1: return (0);
case PERIOD_M5: return (1);
case PERIOD_M15: return (2);
case PERIOD_M30: return (3);
case PERIOD_H1: return (4);
case PERIOD_H4: return (5);
case PERIOD_D1: return (6);
case PERIOD_W1: return (7);
case PERIOD_MN1: return (8);
default: return (9);
}
}
int DST()
{
if(!CalculateDST)
{
if(UseDebug) Print("DST=0, авто перевод отключен");
return(0);
}
int month = Month();
int day = Day();
int day_of_week = DayOfWeek();
if (day_of_week == 0) day_of_week = 7;
if (month > 3 && month < 10)
{
return(0); // Лето
}
if (month > 10 || month < 3)
{
return(1); // Зима
}
if(DSTVariant==0)
{
if (month == 3 && 31 - day + day_of_week >= 7)
{
return(1);
}
if (month == 10 && 31 - day + day_of_week < 7)
{
return(1);
}
}
if(DSTVariant==1)
{
if (month == 3 && 31 - day + day_of_week >= 21)
{
return(1);
}
if (month == 10 && 31 - day + day_of_week < 21)
{
return(1);
}
}
return (0);
}
//+------------------------------------------------------------------+
//| Фильтр по дате и дню недели |
//+------------------------------------------------------------------+
bool TimeFilter()
{
if(!MondayTrade&&DayOfWeek()==1) return(false);
if(!TuesdayTrade&&DayOfWeek()==2) return(false);
if(!WednesdayTrade&&DayOfWeek()==3) return(false);
if(!ThursdayTrade&&DayOfWeek()==4) return(false);
if(!FridayTrade&&DayOfWeek()==5) return(false);
int NNN = GMTOffset+DST();
if(Year()<2011||(Year()==2011&&Month()<5)) NNN=GMTOffset-1+DST();
if(UseWeekEndRollover&&((((Hour()==22&&Minute()>=45)||Hour()>22)&&DayOfWeek()==5)||(Hour()==0&&Minute()<=15&&DayOfWeek()==1))) return(false);
int MyHour = NNN;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour0&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+1;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour1&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+2;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour2&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+3;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour3&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+4;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour4&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+5;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour5&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+6;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour6&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+7;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour7&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+8;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour8&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+9;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour9&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+10;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour10&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+11;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour11&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+12;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour12&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+13;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour13&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+14;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour14&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+15;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour15&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+16;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour16&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+17;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour17&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+18;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour18&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+19;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour19&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+20;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour20&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+21;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour21&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+22;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour22&&TimeHour(TimeCurrent())==MyHour) return(true);
MyHour=NNN+23;
if(MyHour<0) MyHour=MyHour+24;
if(MyHour>23) MyHour=MyHour-24;
if(Hour23&&TimeHour(TimeCurrent())==MyHour) return(true);
NNN=0;
MyHour=0;
return(false);
}
void SetPrefSuff()
{
if(IsTesting())
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "";
return;
}
switch(BrokerVariant)
{
case 1: // Grand
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "_OP";
if(UseDebug) Print("Применены настройки для брокера GrandCapital");
break;
}
case 2: // WForex America
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "ab";
if(UseDebug) Print("Применены настройки для брокера WForex America");
break;
}
case 3: // WForex Europe
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "b";
if(UseDebug) Print("Применены настройки для брокера WForex Europe");
break;
}
case 4: // GDMFX
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "bo";
if(UseDebug) Print("Применены настройки для брокера GDMFX");
break;
}
case 5: // Larson
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "_bo";
if(UseDebug) Print("Применены настройки для брокера Larson");
break;
}
case 6: // MikiForex
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "bo";
if(UseDebug) Print("Применены настройки для брокера MikiForex");
break;
}
case 7: // NoaFX
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "bo";
if(UseDebug) Print("Применены настройки для брокера NoaFX");
break;
}
case 8: // StarfishFX
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "bo";
if(UseDebug) Print("Применены настройки для брокера StarfishFX");
break;
}
case 9: // Clmforex
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "bo";
if(UseDebug) Print("Применены настройки для брокера Clmforex");
break;
}
case 10: // RinkostMarkets
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "bo";
if(UseDebug) Print("Применены настройки для брокера RinkostMarkets");
break;
}
case 11: // GoMarkets
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = ".bo";
if(UseDebug) Print("Применены настройки для брокера GoMarkets");
break;
}
case 12: // DirectFX
{
if(MyPrefix == "") MyPrefix = "";
if(MySuffix == "") MySuffix = "bo";
if(UseDebug) Print("Применены настройки для брокера DirectFX");
break;
}
}
return;
}
//+------------------------------------------------------------------+
double CountAll()
{
double count = 0;
for (int i=0; i<OrdersHistoryTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
if(OrderSymbol() == _Symbol &&
OrderMagicNumber() == Magic && OrderProfit()!=0)
count = count + 1.0;
}
}
if(count==0) return(1);
return(count);
}
//+------------------------------------------------------------------+
double CountProfitPerc()
{
double count = 0;
for (int i=0; i<OrdersHistoryTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
if(OrderSymbol() == _Symbol &&
OrderMagicNumber() == Magic &&
OrderProfit()>0)
count = count + 1.0;
}
}
if(count==0) return(1);
return(count);
}
//+------------------------------------------------------------------+
double OnTester()
{
double ret=100*CountProfitPerc()/CountAll();
CountRealProfit();
return(NormalizeDouble(ret,2));
}
void CountRealProfit()
{
double OrderResult = 0;
double RealOrderProfit = 0;
int Handle=0;
int OrderCount = 0;
string File_Name=_Symbol+"Test.csv";
if(WriteTestInfo) Handle=FileOpen(File_Name, FILE_WRITE, ";");
for (int i=0; i<OrdersHistoryTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
if(OrderSymbol() == _Symbol &&
OrderMagicNumber() == Magic)
{
if(OrderType()==OP_BUY) RealOrderProfit=OrderClosePrice()-OrderOpenPrice();
if(OrderType()==OP_SELL) RealOrderProfit=OrderOpenPrice()-OrderClosePrice();
if(RealOrderProfit>0) OrderResult = 0.85;
if(RealOrderProfit==0) OrderResult = 0;
if(RealOrderProfit<0) OrderResult = - 1;
if(WriteTestInfo)
{
FileWrite(Handle,_Symbol,TimeToStr(OrderOpenTime()),IntegerToString(TimeYear(OrderOpenTime())),IntegerToString(TimeMonth(OrderOpenTime())),
IntegerToString(TimeDay(OrderOpenTime())),IntegerToString(TimeHour(OrderOpenTime())),DoubleToStr(OrderResult,3));
}
}
}
}
if(WriteTestInfo) FileClose(Handle);
return;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Открытие ордера |
//+------------------------------------------------------------------+
void OpenOrder (int direction)
{
int ticket=0,i=0,err=0;
double Lots=MM(AccountBalance());
color Color=Black;
double OpenPrice=0;
if(BrokerVariant == 1 || BrokerVariant == 8) Comm=IntegerToString(Expiration);
else Comm="BO exp:"+IntegerToString(Expiration*60);
if(direction==OP_BUY)
{
Color=Blue;
OpenPrice=Ask;
}
if(direction==OP_SELL)
{
Color=Red;
OpenPrice=Bid;
}
for (i = 1; i <= MathMax(1, RetryAttempts); i++)
{
ticket=0;
RefreshRates();
if(UseDebug) Print("Сов шлет ордер по символу ",_Symbol,", направление=",direction,", Lots=",Lots,", OpenPrice=",OpenPrice,", Comm=",Comm);
ticket=OrderSend(_Symbol, direction,Lots, OpenPrice, 0, 0, 0,Comm, Magic, 0, Color);
if(ticket>0)
{
if(UseDebug) Print("Ордер ушел, все ок!");
if(MailSend) SendMail("Новый ордер от Charlie по паре "+_Symbol,"Новый ордер от Charlie по паре "+_Symbol+" Брокер:"+AccountInfoString(ACCOUNT_COMPANY));
if(PushSend) SendNotification("Новый ордер от Charlie по паре "+_Symbol+" Брокер:"+AccountInfoString(ACCOUNT_COMPANY));
return;
}
if(ticket<=0&&i < MathMax(1, RetryAttempts))
{
if(UseDebug) Print("Ордер не выставлен, пробуем снова через 5 секунд! Попытка №", IntegerToString(i));
err = GetLastError();
if(err>0) Print("Ошибка : ",0);
SleepRandomTime();
continue;
}
if(ticket<=0&&i == MathMax(2, RetryAttempts))
{
if(UseDebug) Print("Ордер не выставлен!");
err = GetLastError();
if(err>0)
{
Print("Ошибка : ",0);
if(MailSend) SendMail("Ордер от Charlie по паре "+_Symbol,"Новый ордер от Charlie по паре "+_Symbol+" не выставлен! Брокер:"+AccountInfoString(ACCOUNT_COMPANY)+", Ошибка:"+0);
if(PushSend) SendNotification("Новый ордер от Charlie по паре "+_Symbol+" не выставлен! Брокер:"+AccountInfoString(ACCOUNT_COMPANY)+", Ошибка:"+0);
}
return;
}
}
return;
}
double MM(double Deposit)
{
double Lots = 0;
double MinLots = MarketInfo(_Symbol,MODE_MINLOT);
double MaxLots = MarketInfo(_Symbol,MODE_MAXLOT);
double LotStep = MarketInfo(_Symbol,MODE_LOTSTEP);
switch(MMVariant)
{
case 1:
Lots = Lot;
if(UseDebug) Print("FixLot=",Lot);
break;
case 2:
Lots = Deposit*Risk/100;
if(UseDebug) Print("%Lot Risk=",Risk,", Deposit=",Deposit);
break;
case 3:
{
if(Deposit<=StartDepo) Lots = MinLots;
if(Deposit>StartDepo) Lots = MinLots + MinLots*((Deposit-StartDepo)/StepDelta)*Step;
if(UseDebug) Print("StepLot=",Lots);
break;
}
}
if(BrokerVariant==4) Lots = Lots/1000;
if(BrokerVariant==5) Lots = Lots/1000;
if (Lots<MinLots) Lots = MinLots;
if (Lots>MaxLots) Lots = MaxLots;
if (BrokerVariant==4&&Lots>1) Lots = 1.0;
if(LotStep == 1) Lots = NormalizeDouble(Lots,0);
if(LotStep == 0.1) Lots = NormalizeDouble(Lots,1);
if(LotStep == 0.01) Lots = NormalizeDouble(Lots,2);
if(LotStep == 0.001) Lots = NormalizeDouble(Lots,3);
return(Lots);
}
bool AllOrders()
{
if(MaxOrders == 0 && MaxRisk == 0) return(true);
int count = 0;
double countLots = 0;
for (int i=0; i<OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderType()==OP_BUY||OrderType()==OP_SELL)
{
count++;
countLots = countLots + OrderLots();
}
}
}
if(MaxOrders != 0 && count >= MaxOrders)
{
if(UseDebug) Print("Превышено максимальное количество открытых ордеров");
return(false);
}
if(countLots>0 && MaxRisk != 0 && (countLots/AccountBalance())*100 >=MaxRisk)
{
if(UseDebug) Print("Превышен максимальный риск по депозиту");
return(false);
}
return(true);
}
void VOrderClose(int expiration)
{
bool VProfit=false;
if(TimeCurrent() - VOrderOpenTime >= expiration * 60)
{
if(VOrderBuy)
{
FileWrite(HandleVT,_Symbol,TimeToStr(VOrderOpenTime),"Buy", DoubleToStr(VOrderOpenLots,2),DoubleToStr(VOrderOpenPrice,_Digits),IntegerToString(Magic),TimeToStr(TimeCurrent()),DoubleToStr(Bid,_Digits),DoubleToStr((Bid-VOrderOpenPrice)/_Point,2));
if(VOrderOpenPrice<Bid) VProfit=true;
}
if(VOrderSell)
{
FileWrite(HandleVT,_Symbol,TimeToStr(VOrderOpenTime),"Sell",DoubleToStr(VOrderOpenLots,2),DoubleToStr(VOrderOpenPrice,_Digits),IntegerToString(Magic),TimeToStr(TimeCurrent()),DoubleToStr(Ask,_Digits),DoubleToStr((VOrderOpenPrice-Ask)/_Point,2));
if(VOrderOpenPrice>Ask) VProfit=true;
}
VOrderBuy = false;
VOrderSell = false;
VOrderOpenTime = 0;
if(UseDebug&&VProfit) Print("Виртуальный ордер закрыт в прибыль, все ок!");
if(UseDebug&&!VProfit) Print("Виртуальный ордер закрыт в убыток, так бывает!");
VProfit=false;
}
return;
}
void VOpenOrder (int direction)
{
double OpenPrice=0;
double Lots=MM(AccountBalance());
if(direction==OP_BUY)
{
OpenPrice=Ask;
VOrderBuy = true;
if(UseDebug) Print("Выставлен виртуальный ордер бай");
}
if(direction==OP_SELL)
{
OpenPrice=Bid;
VOrderSell = true;
if(UseDebug) Print("Выставлен виртуальный ордер селл");
}
VOrderOpenTime = TimeCurrent();
VOrderOpenPrice = OpenPrice;
VOrderOpenLots = Lots;
return;
}
int SignalOpen()
{
if(!AllOrders()) return(-5);
double Close1 = iClose(_Symbol,PERIOD_H1,1);
double Close2 = iClose(_Symbol,PERIOD_M15,1);
double Close3 = iClose(_Symbol,PERIOD_M5,2);
double KeltL1 = iMA(_Symbol, PERIOD_H1, KCPeriod, 0, MODE_SMMA, PRICE_CLOSE,1) - KCDev * iATR(_Symbol,PERIOD_H1,KCPeriod,1);
double KeltH1 = iMA(_Symbol, PERIOD_H1, KCPeriod, 0, MODE_SMMA, PRICE_CLOSE,1) + KCDev * iATR(_Symbol,PERIOD_H1,KCPeriod,1);
if(Close1+KCPipDev*_Point<KeltL1)
{
double WPR1 = iWPR(_Symbol,PERIOD_M15,WPRPeriod,0);
if(WPR1<WPREnterLevel-100)
{
double RSI = iRSI(_Symbol,PERIOD_H1,RSIPer,PRICE_CLOSE,0);
if(RSI<RSIEnterLevel)
{
double KeltL15 = iMA(_Symbol, PERIOD_M1, KC2Period, 0, MODE_EMA, PRICE_CLOSE,1) - KC2Dev * iATR(_Symbol,PERIOD_M1,KC2Period,1);
double KeltL151 = iMA(_Symbol, PERIOD_M1, KC2Period, 0, MODE_EMA, PRICE_CLOSE,2) - KC2Dev * iATR(_Symbol,PERIOD_M1,KC2Period,2);
if(Close2+KC2PipDev*_Point<KeltL15&&Close3+KC2PipDev*_Point<KeltL151)
{
double WPRM15 = iWPR(_Symbol,PERIOD_M1,WPR2Period,0);
if(WPRM15<WPR2EnterLevel-100)
{
if(UseDebug&&CountBuy()==0) Print("Получен сигнал на покупку на следующих настройках: Expiration = ",Expiration,", WPRPeriod = ",WPRPeriod,
", WPREnterLevel = ",WPREnterLevel);
if(UseDebug&&CountBuy()==0) Print(", KCPeriod = ",KCPeriod,", KCPipDev = ",KCPipDev,", KCDev = ",KCDev,
", WPR2Period = ",WPR2Period,", WPR2EnterLevel = ",WPR2EnterLevel,", KC2Period = ",KC2Period,", KC2PipDev = ",KC2PipDev,
", KC2Dev = ",KC2Dev,", RSIPer = ",RSIPer,", RSIEnterLevel = ",RSIEnterLevel);
FirstOpenPrice=Ask;
FirstOpenTime = TimeCurrent();
return(OP_BUY);
}
}
}
}
}
if(Close1-KCPipDev*_Point>KeltH1)
{
double WPR1 = iWPR(_Symbol,PERIOD_M15,WPRPeriod,0);
if(WPR1>-WPREnterLevel)
{
double RSI = iRSI(_Symbol,PERIOD_H1,RSIPer,PRICE_CLOSE,0);
if(RSI>100-RSIEnterLevel)
{
double KeltH15 = iMA(_Symbol, PERIOD_M1, KC2Period, 0, MODE_EMA, PRICE_CLOSE,1) + KC2Dev * iATR(_Symbol,PERIOD_M1,KC2Period,1);
double KeltH151 = iMA(_Symbol, PERIOD_M1, KC2Period, 0, MODE_EMA, PRICE_CLOSE,2) + KC2Dev * iATR(_Symbol,PERIOD_M1,KC2Period,2);
if(Close2-KC2PipDev*_Point>KeltH15&&Close3-KC2PipDev*_Point>KeltH151)
{
double WPRM15 = iWPR(_Symbol,PERIOD_M1,WPR2Period,0);
if(WPRM15>-WPR2EnterLevel)
{
if(UseDebug&&CountSell()==0) Print("Получен сигнал на продажу на следующих настройках: Expiration = ",Expiration,", WPRPeriod = ",WPRPeriod,
", WPREnterLevel = ",WPREnterLevel);
if(UseDebug&&CountSell()==0) Print(", KCPeriod = ",KCPeriod,", KCPipDev = ",KCPipDev,", KCDev = ",KCDev,
", WPR2Period = ",WPR2Period,", WPR2EnterLevel = ",WPR2EnterLevel,", KC2Period = ",KC2Period,", KC2PipDev = ",KC2PipDev,
", KC2Dev = ",KC2Dev,", RSIPer = ",RSIPer,", RSIEnterLevel = ",RSIEnterLevel);
FirstOpenPrice=Bid;
FirstOpenTime = TimeCurrent();
return(OP_SELL);
}
}
}
}
}
return(-5);
}
//+------------------------------------------------------------------+
//| Magic generation |
//+------------------------------------------------------------------+
int makeMagicNumber(string key)
{
int i,n;
int h = 0;
if (IsTesting())
{
key = "_" + key;
}
for (i = 0; i < StringLen(key); i++)
{
n = StringGetChar(key, i);
h = h + n;
h = bitRotate(h, 5);
}
for (i = 0; i < StringLen(key); i++)
{
n = StringGetChar(key, i);
h = h + n;
h = bitRotate(h, n & 0x0000000F);
}
for (i = StringLen(key); i > 0; i--)
{
n = StringGetChar(key, i - 1);
h = h + n;
h = bitRotate(h, h & 0x0000000F);
}
return(h & 0x7fffffff);
}
int bitRotate(int value, int count)
{
int tmp, mask;
mask = (0x00000001 << count) - 1;
tmp = value & mask;
value = value >> count;
value = value | (tmp << (32 - count));
return(value);
}
// Функция включения/отключения эксперта.
void ExpertEnabled (bool Switch) // TRUE - включить эксперт, FALSE - отключить эксперт.
{
int HandlWindow = WindowHandle (Symbol(), Period()); // Системный дескриптор окна.
int HandlMT4; // Системный дескриптор окна МТ4.
int HandlToolbar; // Системный дескриптор окна инструментов.
int ArIntTemp[1]; // Временный массив.
//----
if ((Switch && !IsExpertEnabled()) || (!Switch && IsExpertEnabled()) ) {
HandlMT4 = GetAncestor (HandlWindow, 2);
HandlToolbar = GetDlgItem (HandlMT4, 0x63);
ArIntTemp[0] = HandlToolbar;
SendMessageA (HandlMT4, WM_COMMAND, 33020, ArIntTemp);
}
}
bool CheckStatus()
{
if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
ExpertEnabled (true);
Print("Кнопка автоторговли была отжата. Мы ее нажали обратно, но не делайте так больше!");
}
if(!MQLInfoInteger(MQL_TRADE_ALLOWED))
Print("Автоматическая торговля запрещена в свойствах советника! F7-вкладка Общие");
//Проверка разрешения на торговлю любым экспертам/скриптам для данного счета
if(!AccountInfoInteger(ACCOUNT_TRADE_EXPERT))
{
Print("Нигадяй брокер отключил торговлю советниками у себя на сервере!");
return(false);
}
if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
Print("Торговля не разрешена!");
if(!IsConnected())
{
Print("Связь потеряна, щас будем восстанавливать добровольно-принудительно!!");
if(!ReConnect())
{
Print("Связь ушла, но обещала вернуться. Повисим на графике, пока все не уляжется :(");
}
}
return(true);
}
void PrintAccParams()
{
string str = "";
Print("Номер счета: ", AccountInfoInteger(ACCOUNT_LOGIN));
Print("Имя клиента: ", AccountInfoString(ACCOUNT_NAME));
Print("Имя компании, обслуживающей счет: ", AccountInfoString(ACCOUNT_COMPANY));
Print("Имя торгового сервера: ", AccountInfoString(ACCOUNT_SERVER));
Print("Валюта депозита: ", AccountInfoString(ACCOUNT_CURRENCY));
switch((int)AccountInfoInteger(ACCOUNT_TRADE_MODE))
{
case ACCOUNT_TRADE_MODE_DEMO:
{
str = "Демонстрационный торговый счет";
break;
}
case ACCOUNT_TRADE_MODE_CONTEST:
{
str = "Конкурсный торговый счет";
break;
}
case ACCOUNT_TRADE_MODE_REAL:
{
str = "Реальный торговый счет";
break;
}
}
Print("Тип торгового счета: ", str);
Print("Размер предоставленного плеча: ", AccountInfoInteger(ACCOUNT_LEVERAGE));
Print("Максимально допустимое количество действующих отложенных ордеров (0-ограничений нет): ", AccountInfoInteger(ACCOUNT_LIMIT_ORDERS));
switch((int)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE))
{
case ACCOUNT_STOPOUT_MODE_PERCENT:
{
str = "Уровень задается в процентах";
break;
}
case ACCOUNT_STOPOUT_MODE_MONEY:
{
str = "Уровень задается в деньгах";
break;
}
}
Print("Режим задания минимально допустимого уровня залоговых средств: ", str);
Print("Баланс счета в валюте депозита: ", AccountInfoDouble(ACCOUNT_BALANCE));
Print("Уровень Margin Call: ", AccountInfoDouble(ACCOUNT_MARGIN_SO_CALL));
Print("Уровень Stop Out: ", AccountInfoDouble(ACCOUNT_MARGIN_SO_SO));
}
void SleepRandomTime()
{
if (IsTesting()||IsOptimization()) return;
double tenths = MathCeil(SleepTime / 0.1);
if (tenths <= 0) return;
double maxtenths = MathRound(SleepMaximum/0.1);
double p = 1.0 - 1.0/tenths;
Sleep(1000);
for(int i=0; i<maxtenths; i++) {
if (MathRand() > p*32768) break;
Sleep(1000);
}
}
//+------------------------------------------------------------------+
//| Сканирование серверов и реконнект при обрыве связи |
//+------------------------------------------------------------------+
// Функция выполняет сканирование серверов брокера и реконнект в
// случае обрыва связи
bool ReConnect()
{
if((!IsTesting() && !IsOptimization()&&!IsConnected()&&!IsStopped())||GetLastError()==6)
{
Print("Щас будем сканировать сервера!");
for (int q = 1; q <= RetryAttempts; q++)
{
ReScanServers();
if(IsConnected()) break;
SleepRandomTime();
RefreshRates();
}
if(IsConnected())
{
Print("Соединение восстановлено!");
return (true);
}
else
{
Print("Пересканирование не помогло, перезайдем на счет!");
ReLoginAccount();
}
Print("Соединение не восстановлено! Баста!");
return (false);
}
return (true);
}
int ReScanServers()
{
int hwindow=GetAncestor(WindowHandle(Symbol(),Period()),2); // получаем хендл главного окна
Print("Пересканирование! Пересканируем Серверы..."); // выведем сообщение
if(hwindow!=0)
{ // нашли главное окно
// посылаем сообщение "пересканировать серверы"
return(PostMessageA(hwindow,WM_COMMAND,37400,0));
}
return(-1);
}
void ReLoginAccount()
{
int hwnd=GetAncestor(WindowHandle(Symbol(),Period()),2); // получаем хендл главного окна
PostMessageA(hwnd,WM_COMMAND,35429,0); // открыли окно ввода Логина и Пароля.
SleepRandomTime(); // делаем паузу, ждем
hwnd=GetActiveWindow(); // нашли хэндл окна ввода Логина и Пароля
hwnd=GetDlgItem(hwnd,0x1); // нашли хэндл кнопки ЛОГИН
SleepRandomTime(); // делаем паузу, ждем
SendMessageA(hwnd,WM_COMMAND,0,0); // нажали кнопку ЛОГИН
return;
}