Знаете, ломать - не строить. Можете предолжить лучше что н-ть взамен?
Да в общем то открою секрет, что сам примерно так и вхожу в рынок. Это просто стандартное свойство пробойных систем. То есть вход при пробитии стопа противоположной позиции. Весь вопрос заключается в подборе условий, когда этот пробой окажется не ложным. А уж вариантов расчёта этого стопа огромнейшее многообразие. Я к примеру этот стоп беру либо по экстремуму предыдущего дня, либо по пробитию границы 99,9% доверительного интервала канала линейной регрессии. Мне кажется что важнее это не выбор стопа а определение условий, при которых может начаться сильное пробойное движение. Вот тут то всё и заключается. Будет это работать или не будет.
Знаете, ломать - не строить. Можете предолжить лучше что н-ть взамен?
Да в общем то открою секрет, что сам примерно так и вхожу в рынок. Это просто стандартное свойство пробойных систем. То есть вход при пробитии стопа противоположной позиции. Весь вопрос заключается в подборе условий, когда этот пробой окажется не ложным. А уж вариантов расчёта этого стопа огромнейшее многообразие. Я к примеру этот стоп беру либо по экстремуму предыдущего дня, либо по пробитию границы 99,9% доверительного интервала канала линейной регрессии. Мне кажется что самое главное это не выбор стопа а определение условий, при которых может начаться сильное пробойное движение.
Я недавно сделал советника. Вот алгоритм его работы:
// Трейлинг позиций в этом советнике обязателен!!!!
// Советник анализирует состояние торгов и в зависимости от состояния, в котором он // находится, выполняет те или иные действия. // Управление лотом здесь происходит по методу Мартингейла. Но это можно отключить.
// Состояния советника:
// Sost==1 - ордеров в рынке нет. // В этом состоянии советник выставляет на 2 стоповых ордера с равным лотом // на расстоянии LockLevel от текущей цены и прерходит в Sost==2. // Лот определяется автоматически в зависимости от процента риска, который юзер задал вручную. Стоп-лосс обоих ордеров равен LockStopLoss.
// Sost==2 В рынке 2 отложенных ордера с равным лотом // Как только 1 из ордеров сработает и станет рыночным, // советник удаляет оставшийся отложенный ордер и прерходит в Sost==3.
// Sost==3 В рынке один рыночный (не отложенный ордер). // Выставляем противоположно направленный отложенный ордер (если автоматика включена то лот будет другой; Поэтому предыдущую отложку приходится удалять) в точку Стоп-лосса // рыночного ордера и переходим в состояние 4.
// Sost==4 В рынке 2 ордера. Один отложенный и один рыночный. Если рыночный ордер вдруг закрывается принудительно, например, по пипс-профиту, или его // закрыл пользователь, то советник переходит в состояние 1, где он начинает всё сначала. Если сработал стоп-лосс или тейк-профит // у этого ордера, то советник принимает решение, что ему делать. При срабатывании тейк-профита он открывает рыночный ордер // в том же направлении, что и у сработавшего и с тем же лотом. // При срабатывании стоп-лосса 2 ситуации: // - Стоп-Лосс в зоне положительного профита: // советник считает, что ситуация неопределённая, удаляет отложенный ордер и переходит в состояние 1, где начинает всё сначала. // - Если стоп лосс сработал в зоне отрицательного профита или в точке нуля, то советник удаляет отложенный ордер, потом открывает // рыночный ордер того же направления, что только что удалённый отложенный, но с удвоенным лотом если мартингейл включен, или с лотом, // определяемым автоматически, если автолот включен, или с тем лотом, что выставил пользователь вручную, если автолот отключен. Далее он // переходит в состояние № 3. Тут надо заметить, что если автолот отключен а мартингейл включен, то советник удвоит тот лот, который был установлен // пользователем вручную в настройках в переменной Lots.
2 недели убил на то, чтоб нормально сделать код. Начал тестировать - уходит в минуса даже при отключении всяких там мартингейлов и автоматов лота. Пробовал даже пипсовать на тестере. Всёравно сливает. Ну чтож, отрицательный результат сужает круг поиска. Словом, запустил на демо - пока торгует в плюс. Пожалуй самый трудный вопрос на форексе - это не столько момент входа в рынок, сколько что делать с образовавшимся вдруг профитом? Перебираю варианты. Словом, работа идёт :) ...
Админ, закрывай тему, а то мы уже начали обсуждать торговые системы. Плохого тут ни чего нету, просто мы отклонились от самой темы.
Только лазейку мне оставь малюсенькую, чтоб я мог тут код универсального трейлинга выложить, как и обещал людям ;)
Ну это ничего, всё ещё только начинается ;o) Я вот уже больше года программирую советники, при этом никаких трудностей при программировании не испытываю, а результат пока не слишком впечатляет.
Ну это ничего, всё ещё только начинается ;o) Я вот уже больше года программирую советники, при этом никаких трудностей при программировании не испытываю, а результат пока не слишком впечатляет.
Трудность была не код набрать, а алгоритм досконально продумать. Хотя, могу сказать, что знание MQL4 - довольно хороший инструмент. Вот кажется систему торговли разработал или отыскал хорошую. Кодишь её, тестишь и радости у тя поубавилось. Одно утешение остаётся, что не зарядил денег и не начал торговать по этой псевдосуперской системе. :))
Вот обещанный советник.
Его возможности описаны в начале кода.
//+------------------------------------------------------------------+
//| Универсал_1.4.mq4 |
//| Drknn |
//| 10.02.2007 drknn@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Drknn"
#property link "drknn@mail.ru"
/*
!!!!!!!!!!!!!! Внимание!!!!!!!!!!!!!
В режиме отлова процента депозита советник закрывает все сделки по всем валютным
парам, что может негативно повлиять на работу других советников, параллельно
запущенных в терминале.
Если советник будет настроен на отлов процента, и при этом ему будет разрешено как устанавливать
отложенные ордера, так и при отлове удалять отложенные, то это может вызвать програмный конфликт.
Вполне возможно, что на текущем тике советник не успеет закрыть все ордера а на следующем начнёт
их ставить и тут же удалять, так как приказ на удаление ещё жив.
Советник умеет:
- тралить ордера любого типа (как рыночные, так и отложенные)
- пипсовать
- Ловить увеличение депозита на нужное количество процентов и, поймав закрыть сделки
по всем валютным парам и, если нужно, удалить и отложенные ордера.
- Устанавливать те отложенные ордера, которые разрешил пользователь, если советник вдруг
обнаружит, что ордера такого в рынке нет (например, ордер сработал - стал рыночным -
или были удалены ордера после отлова процента)
- показывает на экране что и как у него настрено, чтоб каждый раз не лазить в настройки
Советник задумывался как универсальный трейлинг, а всё остальное добавлено лишь для удобства.
Ненужные функции можно легко отключить в окне свойств советника.
Если пользователь разрешил советнику устанавливать отложенный ордер какого либо типа,
то этот ордер будет установлен от текущей цены на расстоянии трейлингстопа для ордеров данного типа.
*/
// ================ Параметры, настраиваимые пользователем ===========================
// ----- Параметры трала рыночных ордеров ---------------------------------------------
extern int ryn_TrStop=15; //Трейлинг-Стоп рыночного ордера. Если = 0 то тарла нет
extern int ryn_TrStep=3; //Шаг трала рыночного ордера
extern bool WaitProfit = false; // Если true, то ждать профит = значению TrailingStop и только потом начинать тралить
//Иначе, трейлинговать не дожидаясь положительного профита
// ----- Параметры трала лимитных ордеров ---------------------------------------------
extern int lim_TakeProfit=30; //Тейк-Профит лимитных ордеров
extern int lim_StopLoss=15; //Стоп-Лосс лимитных ордеров
extern int lim_TrStop=0; //Трейлинг-Стоп лимитных ордеров Если = 0 то тарла нет
extern int lim_TrStep=3; //Шаг трейлинга лимитных ордеров
// ----- Параметры трала стоповых ордеров ---------------------------------------------
extern int st_TakeProfit=30; //Тейк-Профит стоповых ордеров
extern int st_StopLoss=15; //Стоп-Лосс стоповых ордеров
extern int st_TrStop=0; //Трейлинг-Стоп стоповых ордеров. Если = 0 то тарла нет
extern int st_TrStep=3; //Шаг трала стоповых ордеров
// ----- Разрешение установить тот или иной ордер -------------------------------------
extern double Lot=0.1;//Лот для установки отложенного ордера
extern int st_Step=15;//Расстояние в пунктах от уровня текущей цены до уорвня установки стопового ордера
extern int lim_Step=15;//Расстояние в пунктах от уровня текущей цены до уорвня установки лимитного ордера
extern bool Ustan_BuyStop=true; //можно ли ставиь БайCтоп если в рынке такого у нас нет
extern bool Ustan_SellLimit=false; //можно ли ставиь CеллЛимит если в рынке такого у нас нет
extern bool Ustan_SellStop=true; //можно ли ставиь CеллCстоп если в рынке такого у нас нет
extern bool Ustan_BuyLimit=false; //можно ли ставиь БайЛимит если в рынке такого у нас нет
// ----- Параметры пипсовки ----------------------------------------------------
extern int PipsProfit=0; //профит при пипсовке можно ставить 1, 2, 3, ...
extern int Proskalz = 3; //Проскальзывание в пунктах (нужно только когда PipsProfit>0)
// ----------- Отлавливаем увеличение депозита --------------------------
extern bool Otlov=true;//отловить увеличение депозита на Pojmat процентов и закрыть все ордера
//если Otlov=false, то значениt Pojmat не важно.
extern double Pojmat=2.0;//процент желаемого увеличения депозита
extern bool DelOtlozh=false;//Удалять ли при этом и отложенные ордера.
//если Otlov=false, то значениt DelOtlozh не важно.
// ----- Прочие установки ------------------------------------------------------
extern bool UseOrderSound = true; // Использовать звуковой сигнал для установки ордеров
extern bool UseTrailingSound = true; // Использовать звуковой сигнал для трейлинга
string NameOrderSound = "alert.wav"; // Наименование звукового файла для ордеров
extern string NameTrallingSound = "expert.wav";// Наименование звукового файла для трейлинга
// =======================================================================================
// ================== Глобальные переменные ===============================================================
string Comm1,Comm2,Comm3,Comm4,Comm5,Comm6,Comm7,Comm8,Comm9,ED;
double PNT,NewPrice,SL,TP,Balans,Free;
int MinLevel,i,SchBuyStop,SchSellStop,SchBuyLimit,SchSellLimit,SchSell,SchBuy,SBid,SAsk,BBid,BAsk,Ts,GLE,total;
bool fm,Rezult,TrailBuyStop,TrailSellStop,TrailBuyLimit,TrailSellLimit;
// ========================================================================================================
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
if(!IsExpertEnabled())//если ложь
{Alert("Ошибка! Не нажата кнопка *Советники*"); Comment("Ошибка! Не нажата кнопка *Советники*"); return(0);}
else {Comment("Как только цена изменится, Советник начнёт работу."); Print("Как только цена изменится, Советник начнёт работу.");}
PNT=MarketInfo(Symbol(),MODE_POINT);//Размер пункта в валюте котировки. Для текущего инструмента хранится в предопределенной переменной Point
MinLevel=MarketInfo(Symbol(),MODE_STOPLEVEL);//Минимально допустимый уровень стоп-лосса/тейк-профита в пунктах
if(st_TrStop<MinLevel && st_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel);
Print("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel);
Alert("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel);
return(0);}
if(ryn_TrStop<MinLevel && ryn_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel);
Print("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel);
Alert("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel);
return(0);}
if(lim_TrStop<MinLevel && lim_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel);
Print("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel);
Alert("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel);
return(0);}
if(st_TrStop>=MinLevel && st_TrStep==0) {Comment("Ошибка! шаг тарала стоповых ордеров не может быть менее 1");
Print("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее 1");
Alert("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее 1");
return(0);}
if(ryn_TrStop>=MinLevel && ryn_TrStep==0) {Comment("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1");
Print("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1");
Alert("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1");
return(0);}
if(lim_TrStop>=MinLevel && lim_TrStep==0) {Comment("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1");
Print("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1");
Alert("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1");
return(0);}
if(st_Step<MinLevel) {Comment("Ошибка! переменная st_Step не может быть менее ",MinLevel);
Print("Ошибка! переменная st_Step не может быть менее ",MinLevel);
Alert("Ошибка! переменная st_Step не может быть менее ",MinLevel);
return(0);}
if(lim_Step<MinLevel) {Comment("Ошибка! переменная lim_Step не может быть менее ",MinLevel);
Print("Ошибка! переменная lim_Step не может быть менее ",MinLevel);
Alert("Ошибка! переменная lim_Step не может быть менее ",MinLevel);
return(0);}
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
RefreshRates();
//----Первичные проверки данных
if(!IsTradeAllowed())
{Comment("Торговля запрещена в настройках терминала, либо торговый поток занят");
return(0);}
//----Конец первичных проверок данных
if(st_TrStop<MinLevel && st_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel);
Print("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel);
Alert("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel);
return(0);}
if(ryn_TrStop<MinLevel && ryn_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel);
Print("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel);
Alert("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel);
return(0);}
if(lim_TrStop<MinLevel && lim_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel);
Print("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel);
Alert("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel);
return(0);}
if(st_TrStop>=MinLevel && st_TrStep==0) {Comment("Ошибка! шаг тарала стоповых ордеров не может быть менее 1");
Print("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее 1");
Alert("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее 1");
return(0);}
if(ryn_TrStop>=MinLevel && ryn_TrStep==0) {Comment("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1");
Print("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1");
Alert("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1");
return(0);}
if(lim_TrStop>=MinLevel && lim_TrStep==0) {Comment("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1");
Print("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1");
Alert("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1");
return(0);}
if(st_Step<MinLevel) {Comment("Ошибка! переменная st_Step не может быть менее ",MinLevel);
Print("Ошибка! переменная st_Step не может быть менее ",MinLevel);
Alert("Ошибка! переменная st_Step не может быть менее ",MinLevel);
return(0);}
if(lim_Step<MinLevel) {Comment("Ошибка! переменная lim_Step не может быть менее ",MinLevel);
Print("Ошибка! переменная lim_Step не может быть менее ",MinLevel);
Alert("Ошибка! переменная lim_Step не может быть менее ",MinLevel);
return(0);}
if(ryn_TrStop>0 && ryn_TrStop>=MinLevel) Comm1="Трал рыночных - Вкл."; else Comm1="Трал рыночных - Откл.";
if (lim_TrStop>0 && lim_TrStop>=MinLevel) Comm2="Трал лимитных - Вкл."; else Comm2="Трал лимитных - Откл.";
if (st_TrStop>0 && st_TrStop>=MinLevel) Comm3="Трал стоповых - Вкл."; else Comm3="Трал стоповых - Откл.";
if (PipsProfit>0) Comm4="Пипсовка - Вкл"; else Comm4="Пипсовка - Откл";
double Otl=(Balans/100*Pojmat+Balans);
Otl=NormalizeDouble(Otl, 2);
Ts=MathCeil(Otl);
if (Otlov) {Comm5="Отлов процента - Вкл"; Comm6="Ловим сумму = "+Ts+" $";} else {Comm5="Отлов процента - Откл";Comm6="";}
SchOrders();
Comment("Ордеров сейчас для ",Symbol()," :","\n","Buy = ",SchBuy," Sell = ",SchSell,"\n","BuyStop = ",SchBuyStop,
" SellLimit = ",SchSellLimit,"\n","SellStop = ",SchSellStop," BuyLimit = ",SchBuyLimit,"\n",Comm1,
"\n",Comm2,"\n",Comm3,"\n",Comm4,"\n",Comm5,"\n",Comm6);
//-------------- Отлавливаем увеличение депозита на Pojmat процентов ------------------------
if(Otlov)//Если разрешено отловить процент увеличения депозита
{
Balans=AccountBalance();//Баланс счёта
Free=AccountEquity();//Текущее количество денег в статье "Средства"
if ((Free-Balans)>=(Balans/100*Pojmat))//Если денег стало достаточно
{
Print("Депозит увеличен на ",Pojmat," процентов.","\n","Закрываем позиции.");
Comment("Депозит увеличен на ",Pojmat," процентов.","\n","Закрываем позиции.");
if (DelOtlozh)
{
DeleteAllOrders();//удаляем из рынка все ордера
Sleep(5000);
RefreshRates();
}
else
{
DelRynochn();
Sleep(5000);
RefreshRates();
}
SchOrders();
}
}
//--------------------------------------------------------------------------------------------
//=================Начало пипсовки==========================
if (PipsProfit>0)
{
int total = OrdersTotal();
for (int i = 0; i<total; i++ )//Цикл. Проходим по всем ордерам от 0 до total
{//Начало цикла
if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка ", GLE, " при выборе ордера номер ",i);
Print ("Описание ошибки - ",ED);
}
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true)// выбрали очередной ордер
{//начало работы с выбранным ордером
if(OrderSymbol()!=Symbol()) continue; // Если не наш - смотрим следующий
if(OrderType()==OP_BUY) // если он открытый в покупку, то...
{
if(Bid>=(OrderOpenPrice()+PipsProfit*Point))
{OrderClose(OrderTicket(),OrderLots(),Bid,Proskalz);}
}
if(OrderType()==OP_SELL)// если он открытый в продажу, то...
{
if(Ask<=(OrderOpenPrice() - PipsProfit*Point))
OrderClose(OrderTicket(),OrderLots(),Ask,Proskalz);
}
} // конец работы с выбранным ордером
}// Конец цикла, мы просмотрели все ордера. ----------------------------------------------------------
}
//================Конец пипсовки ======================================
//===================== Установка отложенных ордеров ===========================================================================
RefreshRates(); SchOrders();
if(SchSellStop==0 && Ustan_SellStop && st_Step>=MinLevel)
{
NewPrice=Bid-st_Step*Point;
if(st_StopLoss==0) SL=0.0000;
else SL=NewPrice+st_StopLoss*Point;
if(st_TakeProfit==0) TP=0.0000;
else TP=NewPrice-st_TakeProfit*Point;
fm=OrderSend(Symbol(),OP_SELLSTOP,Lot,NewPrice,3,SL,TP,NULL,0,0,CLR_NONE);
/*Сигналим*/ if(fm!=0 && fm!=-1 && UseOrderSound) PlaySound(NameOrderSound);
/*Комментируем*/ if(fm!=0 && fm!=-1)
{Print("Ордер SellStop установлен"); Comment("Ордер SellStop установлен"); Sleep(5000); RefreshRates();}
if(fm==0 || fm==-1)//Если установить не удалось
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка № ",GLE," установки SellStop-ордера");
Print ("Описание ошибки - ",ED);
}
}
if(SchBuyStop==0 && Ustan_BuyStop && st_Step>=MinLevel)
{
NewPrice=Ask+st_Step*Point;
if(st_StopLoss==0) SL=0.0000;
else SL=NewPrice-st_StopLoss*Point;
if(st_TakeProfit==0) TP=0.0000;
else TP=NewPrice+st_TakeProfit*Point;
fm=OrderSend(Symbol(),OP_BUYSTOP,Lot,NewPrice,3,SL,TP,NULL,0,0,CLR_NONE);
/*Сигналим*/ if(fm!=0 && fm!=-1 && UseOrderSound) PlaySound(NameOrderSound);
/*Комментируем*/ if(fm!=0 && fm!=-1)
{Print("Ордер BuyStop установлен"); Comment("Ордер BuyStop установлен"); Sleep(5000); RefreshRates();}
if(fm==0 || fm==-1)//Если установить не удалось
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка № ",GetLastError()," установки BuyStop-ордера");
Print ("Описание ошибки - ",ED);
}
}
if(SchBuyLimit==0 && Ustan_BuyLimit && lim_Step>=MinLevel)
{
NewPrice=Ask-lim_Step*Point;
if(st_StopLoss==0) SL=0.0000;
else SL=NewPrice-st_StopLoss*Point;
if(st_TakeProfit==0) TP=0.0000;
else TP=NewPrice+st_TakeProfit*Point;
fm=OrderSend(Symbol(),OP_BUYLIMIT,Lot,NewPrice,3,SL,TP,NULL,0,0,CLR_NONE);
/*Сигналим*/ if(fm!=0 && fm!=-1 && UseOrderSound) PlaySound(NameOrderSound);
/*Комментируем*/ if(fm!=0 && fm!=-1)
{Print("Ордер BuyLimit установлен"); Comment("Ордер BuyLimit установлен"); Sleep(5000); RefreshRates();}
if(fm==0 || fm==-1)//Если установить не удалось
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка № ",GetLastError()," установки BuyLimit-ордера");
Print ("Описание ошибки - ",ED);
}
}
if(SchSellLimit==0 && Ustan_SellLimit && lim_Step>=MinLevel)
{
NewPrice=Bid+lim_Step*Point;
if(st_StopLoss==0) SL=0.0000;
else SL=NewPrice+st_StopLoss*Point;
if(st_TakeProfit==0) TP=0.0000;
else TP=NewPrice-st_TakeProfit*Point;
fm=OrderSend(Symbol(),OP_SELLLIMIT,Lot,NewPrice,3,SL,TP,NULL,0,0,CLR_NONE);
/*Сигналим*/ if(fm!=0 && fm!=-1 && UseOrderSound) PlaySound(NameOrderSound);
/*Комментируем*/ if(fm!=0 && fm!=-1)
{Print("Ордер SellLimit установлен"); Comment("Ордер SellLimit установлен"); Sleep(5000); RefreshRates();}
if(fm==0 || fm==-1)//Если установить не удалось
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка № ",GetLastError()," установки SellLimit-ордера");
Print ("Описание ошибки - ",ED);
}
}
//==============================================================================================================================
// ================= Трейлинг Рыночных ордеров ==================================================================================
RefreshRates(); SchOrders();
if(ryn_TrStop>=MinLevel && ryn_TrStep>0 && (SchBuy>0 || SchSell>0))
{
for (i=0; i<OrdersTotal(); i++)//Проходим по всем ордерам
{
if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка ", GLE, " при выборе ордера номер ",i);
Print ("Описание ошибки - ",ED);
}
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if (OrderSymbol()==Symbol())
{
TrailingPositions();
}
}
}
}
if(ryn_TrStop>=MinLevel && ryn_TrStep==0)
Alert("Трейлинг невозможен - ноль в настройках советника");
// ===============================================================================================================================
//============ Трейлинг отложенных ордеров =============================================================
RefreshRates(); SchOrders();//Обновляем счётчики количества ордеров
if((st_TrStop>0 && SchBuyStop+SchSellStop>0) || (SchBuyLimit+SchSellLimit>0 && lim_TrStop>0))
{
TrailBuyStop=false; TrailSellStop=false; TrailBuyLimit=false; TrailSellLimit=false;
for (i=OrdersTotal()-1;i>=0;i--)//Цикл. Проходим по всем ордерам от 0 до total
{//Начало цикла
if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка ", GLE, " при выборе ордера номер ",i);
Print ("Описание ошибки - ",ED);
}
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true)// выбрали очередной ордер
{//начало работы с выбранным ордером
if(OrderSymbol()!=Symbol() || OrderType()==OP_BUY || OrderType()==OP_SELL) continue; // Если не наш - смотрим следующий
if(OrderType()==OP_BUYSTOP) // Он наверху и едет вниз
{
if(Ask<OrderOpenPrice()-(st_TrStop+st_TrStep)*Point)
TrailBuyStop=true;
}
if(OrderType()==OP_SELLLIMIT) // Он наверху и едет вниз
{
if(Bid<OrderOpenPrice()-(st_TrStop+st_TrStep)*Point)
TrailSellLimit=true;
}
if(OrderType()==OP_SELLSTOP) // Он внизу и едет вверх
{
if(Bid>OrderOpenPrice()+(st_TrStop+st_TrStep)*Point)
TrailSellStop=true;
}
if(OrderType()==OP_BUYLIMIT) // Он внизу и едет вверх
{
if(Ask>OrderOpenPrice()+(st_TrStop+st_TrStep)*Point)
TrailBuyLimit=true;
}
}//конец работы с выбранным ордером
}//Конец цикла
if (TrailSellLimit || TrailBuyLimit || TrailSellStop || TrailBuyStop) TrailingOtlozh();
}
//====================================================================================================
//----
return(0);
}
//+ ========================== Конец работы советника ========================================================================== +
// ___________________________________________________________________________________________
//| |
//| |
//| Далее идут подпрограммы (функции), |
//| которые в случае надобности вызываются из тела советника |
//| |
//|___________________________________________________________________________________________|
//=========== Счётчики количества ордеров =================================================================
// Функция SchOrders() проходит по всем ордерам и подсчитывает, сколько сейчас имеется ордеров каждого типа.
// Как только понадобятся значение того или иного счётчика, нужно сначала вызвать функцию SchOrders()
// Она обновит данные и потом можно смело вызывать тот или иной счётчик.
// SchBuyStop - счётчик ордеров BuyStop
// SchSellStop - счётчик ордеров SellStop
//
// SchBuyLimit - счётчик ордеров BuyLimit
// SchSellLimit счётчик ордеров SellLimit
// SchBuy - счётчик Buy ордеров
// SchSell - счётчик Sell ордеров
//----------------------------------------------------------------------------------------------------------
void SchOrders()
{
// для начала работы счётчиков мы их обнуляем
SchBuyStop=0; SchSellStop=0; SchBuyLimit=0;
SchBuy=0; SchSell=0; SchSellLimit=0;
for (i=OrdersTotal()-1;i>=0;i--)//Цикл. Проходим по всем ордерам от 0 до total
{//Начало цикла
if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка ", GLE, " при выборе ордера номер ",i);
Print ("Описание ошибки: ",ED);
}
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))// выбрали очередной ордер
{//начало работы с выбранным ордером
if(OrderSymbol()!=Symbol()) continue; // Если не наш - смотрим следующий
if(OrderType()==OP_BUYSTOP) // если он BUYSTOP, то...
SchBuyStop++;//увеличиваем значение счётчиков на 1
if(OrderType()==OP_SELLSTOP) // если он SELLSTOP, то...
SchSellStop++; //увеличиваем значение счётчиков на 1
if(OrderType()==OP_SELLLIMIT)
SchSellLimit++;
if(OrderType()==OP_BUYLIMIT)
SchBuyLimit++;
if(OrderType()==OP_BUY) // если он открытый в покупку, то...
SchBuy++;//увеличиваем значение счётчиков на 1
if(OrderType()==OP_SELL)// если он открытый в продажу, то...
SchSell++;//увеличиваем значение счётчиков на 1
}//конец работы с выбранным ордером
}//Конец цикла
}
//==========================================================================================================
//+------------------------------------------------------------------+
//| Сопровождение позиции простым тралом |
//+------------------------------------------------------------------+
void TrailingPositions()//Описание (объявление) пользовательской функции
{
if(OrderType()==OP_BUY)//Если выбранный в цикле ордер в покупку
{
if(!WaitProfit || (Bid-OrderOpenPrice())>ryn_TrStop*Point)
{
if (OrderStopLoss()<Bid-(ryn_TrStop+ryn_TrStep-1)*Point)
{ModifyStopLoss(Bid-ryn_TrStop*Point);}
}
}
if(OrderType()==OP_SELL)
{
if(!WaitProfit || OrderOpenPrice()-Ask>ryn_TrStop*Point) {
if(OrderStopLoss()>Ask+(ryn_TrStop+ryn_TrStep-1)*Point || OrderStopLoss()==0)
{ModifyStopLoss(Ask+ryn_TrStop*Point);}
}
}
}
//+------------------------------------------------------------------+
//| Перенос уровня StopLoss |
//| Параметры: |
//| ldStopLoss - уровень StopLoss |
//+------------------------------------------------------------------+
void ModifyStopLoss(double ldStopLoss)
{
fm=OrderModify(OrderTicket(),OrderOpenPrice(),ldStopLoss,OrderTakeProfit(),0,CLR_NONE);
if(fm!=0 && fm!=-1 && UseTrailingSound) PlaySound(NameTrallingSound);
if(fm==0 || fm==-1)
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Модификация ",Symbol(),"-ордера № ",OrderTicket()," вызвала ошибку № ",GLE);
Print ("Описание ошибки: ",ED);
}
}
//+------------------------------------------------------------------+
//======== Подтягивание отложенного ордера вслед ценой ============================================
// Функция TrailingOtlozh() подтягивает отложенный ордер вслед за ценой
//--------------------------------------------------------------------------------------------------
void TrailingOtlozh()
{
RefreshRates();
for (i=OrdersTotal()-1;i>=0;i--)//Цикл. Проходим по всем ордерам
{//Начало цикла
if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка ", GLE, " при выборе ордера номер ",i);
Print ("Описание ошибки: ",ED);
}
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))// выбрали очередной ордер
{//начало работы с выбранным ордером
if(OrderSymbol()!=Symbol()) {} // Если не наш - смотрим следующий
if(OrderType()==OP_BUYSTOP)//находится вверху, едет вниз
{
if(TrailBuyStop)
{
NewPrice=Ask+st_TrStop*Point;
if(st_StopLoss==0) SL=0.0000;
else SL=NewPrice-st_StopLoss*Point;
if(st_TakeProfit==0) TP=0.0000;
else TP=NewPrice+st_TakeProfit*Point;
Rezult=false;
Rezult=OrderModify(OrderTicket(),NewPrice,SL,TP,0,CLR_NONE);
if(fm!=0 && fm!=-1 && UseTrailingSound) PlaySound(NameTrallingSound);
if(Rezult!=0 && Rezult!=-1) Sleep(5000);
if(Rezult==0 || Rezult==-1)
{
Print("Корректировка BUYSTOP-ордера № ",OrderTicket(), " вернула ошибку № ",GetLastError());
Print("NewPrice BUYSTOP-ордера = ",NewPrice);
//Print("StopLoss BUYSTOP-ордера = ",SL);
//Print("TakeProfit BUYSTOP-ордера = ",TP);
}
}
}
if(OrderType()==OP_SELLSTOP) // Находится внизу, едет вверх
{
if(TrailSellStop)
{
NewPrice=Bid-st_TrStop*Point;
if(st_StopLoss==0) SL=0.0000;
else SL=NewPrice+st_StopLoss*Point;
if(st_TakeProfit==0) TP=0.0000;
else TP=NewPrice-st_TakeProfit*Point;
Rezult=false;
Rezult=OrderModify(OrderTicket(),NewPrice,SL,TP,0,CLR_NONE);
if(fm!=0 && fm!=-1 && UseTrailingSound) PlaySound(NameTrallingSound);
if(Rezult!=0 && Rezult!=-1) Sleep(5000);
if(Rezult==0 || Rezult==-1)
{
Print("Корректировка SELLSTOP-ордера № ",OrderTicket(), " вернула ошибку № ",GetLastError());
Print("NewPrice SELLSTOP-ордера = ",NewPrice);
//Print("StopLoss SELLSTOP-ордера = ",SL);
//Print("TakeProfit SELLSTOP-ордера = ",TP);
}
}
}
if(OrderType()==OP_BUYLIMIT) // Находится внизу, едет вверх
{
if(TrailBuyLimit)
{
NewPrice=Ask-st_TrStop*Point;
if(st_StopLoss==0) SL=0.0000;
else SL=NewPrice-st_StopLoss*Point;
if(st_TakeProfit==0) TP=0.0000;
else TP=NewPrice+st_TakeProfit*Point;
Rezult=false;
Rezult=OrderModify(OrderTicket(),NewPrice,SL,TP,0,CLR_NONE);
if(fm!=0 && fm!=-1 && UseTrailingSound) PlaySound(NameTrallingSound);
if(Rezult!=0 && Rezult!=-1) Sleep(5000);
if(Rezult==0 || Rezult==-1)
{
Print("Корректировка BUYLIMIT-ордера № ",OrderTicket(), " вернула ошибку № ",GetLastError());
Print("NewPrice BUYLIMIT-ордера = ",NewPrice);
//Print("StopLoss BUYLIMIT-ордера = ",SL);
//Print("TakeProfit BUYLIMIT-ордера = ",TP);
}
}
}
if(OrderType()==OP_SELLLIMIT)//находится вверху, едет вниз
{
if(TrailSellLimit)
{
NewPrice=Bid+st_TrStop*Point;
if(st_StopLoss==0) SL=0.0000;
else SL=NewPrice+st_StopLoss*Point;
if(st_TakeProfit==0) TP=0.0000;
else TP=NewPrice-st_TakeProfit*Point;
Rezult=false;
Rezult=OrderModify(OrderTicket(),NewPrice,SL,TP,0,CLR_NONE);
if(fm!=0 && fm!=-1 && UseTrailingSound) PlaySound(NameTrallingSound);
if(Rezult!=0 && Rezult!=-1) Sleep(5000);
if(Rezult==0 || Rezult==-1)
{
Print("Корректировка SELLLIMIT-ордера № ",OrderTicket(), " вернула ошибку № ",GetLastError());
Print("NewPrice SELLLIMIT-ордера = ",NewPrice);
//Print("StopLoss SELLLIMIT-ордера = ",SL);
//Print("TakeProfit SELLLIMIT-ордера = ",TP);
}
}
}
}//конец работы с выбранным ордером
}//Конец цикла
}//конец функции
//=========================================================================================
//=========== Удаление ВСЕХ ИМЕЮЩИХСЯ в рынке ордеров ========================
// Функция DeleteAllOrders()
// Удаляет ВСЕ ИМЕЮЩИЕСЯ ордера - и рыночные и отложенные,
// независимо от того, к какой валютной паре прицеплен советник
//----------------------------------------------------------------------------
bool DeleteAllOrders()
{
for (int i=OrdersTotal()-1; i>=0; i--)
{
if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка ", GLE, " при выборе ордера номер ",i);
Print ("Описание ошибки - ",ED);
}
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if (OrderType()==OP_BUYLIMIT || OrderType()==OP_SELLLIMIT || OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP)
OrderDelete(OrderTicket());
if(OrderType()==OP_BUY) // если он открытый в покупку, то...
OrderClose(OrderTicket(),OrderLots(),Bid,3);
if(OrderType()==OP_SELL)// если он открытый в продажу, то...
OrderClose(OrderTicket(),OrderLots(),Ask,3);
}
}
}
//============================================================================
// ======== Удаление только рыночных ордеров ================================
// Удаляет ВСЕ рыночные ордера,
// независимо от того, к какой валютной паре прицеплен советник
//----------------------------------------------------------------------------
void DelRynochn()
{
for (int i=OrdersTotal()-1; i>=0; i--)
{
if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
GLE=GetLastError();
ED=ErrorDescription(GLE);
Print("Ошибка ", GLE, " при выборе ордера номер ",i);
Print ("Описание ошибки - ",ED);
}
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderType()==OP_BUY) // если он открытый в покупку, то...
OrderClose(OrderTicket(),OrderLots(),Bid,3);
if(OrderType()==OP_SELL)// если он открытый в продажу, то...
OrderClose(OrderTicket(),OrderLots(),Ask,3);
}
}
}
//============================================================================
//========= Словестное описание ошибок =========================================================================================
// Функция возвращает не код ошибки а её словестное описание
//-----------------------------------------------------------
string ErrorDescription(int error_code)
{
string error_string;
//----
switch(error_code)
{
//---- codes returned from trade server
case 0: error_string=" Нет ошибки"; break;
case 1: error_string=" Нет ошибки, но результат неизвестен"; break;
case 2: error_string=" Общая ошибка"; break;
case 3: error_string=" Неправильные параметры"; break;
case 4: error_string=" Торговый сервер занят"; break;
case 5: error_string=" Старая версия клиентского терминала"; break;
case 6: error_string=" Нет связи с торговым сервером"; break;
case 7: error_string=" Недостаточно прав"; break;
case 8: error_string=" Слишком частые запросы"; break;
case 9: error_string=" Недопустимая операция нарушающая функционирование сервера"; break;
case 64: error_string=" Счет заблокирован"; break;
case 65: error_string=" Неправильный номер счета"; break;
case 128: error_string=" Истек срок ожидания совершения сделки"; break;
case 129: error_string=" Неправильная цена"; break;
case 130: error_string=" Неправильные стопы"; break;
case 131: error_string=" Неправильный объем"; break;
case 132: error_string=" Рынок закрыт"; break;
case 133: error_string=" Торговля запрещена"; break;
case 134: error_string=" Недостаточно денег для совершения операции"; break;
case 135: error_string=" Цена изменилась"; break;
case 136: error_string=" Нет цен"; break;
case 137: error_string=" Брокер занят"; break;
case 138: error_string=" Новые цены"; break;
case 139: error_string=" Ордер заблокирован и уже обрабатывается"; break;
case 140: error_string=" Разрешена только покупка"; break;
case 141: error_string=" Слишком много запросов"; break;
case 145: error_string=" Модификация запрещена, так как ордер слишком близок к рынку"; break;
case 146: error_string=" Подсистема торговли занята"; break;
case 147: error_string=" Использование даты истечения ордера запрещено брокером"; break;
case 148: error_string=" Количество открытых и отложенных ордеров достигло предела, установленного брокером"; break;
case 4000: error_string=" Нет ошибки"; break;
case 4001: error_string=" Неправильный указатель функции"; break;
case 4002: error_string=" Индекс массива - вне диапазона"; break;
case 4003: error_string=" Нет памяти для стека функций"; break;
case 4004: error_string=" Переполнение стека после рекурсивного вызова"; break;
case 4005: error_string=" На стеке нет памяти для передачи параметров"; break;
case 4006: error_string=" Нет памяти для строкового параметра"; break;
case 4007: error_string=" Нет памяти для временной строки"; break;
case 4008: error_string=" Неинициализированная строка"; break;
case 4009: error_string=" Неинициализированная строка в массиве"; break;
case 4010: error_string=" Нет памяти для строкового массива"; break;
case 4011: error_string=" Слишком длинная строка"; break;
case 4012: error_string=" Остаток от деления на ноль"; break;
case 4013: error_string=" Деление на ноль"; break;
case 4014: error_string=" Неизвестная команда"; break;
case 4015: error_string=" Неправильный переход"; break;
case 4016: error_string=" Неинициализированный массив"; break;
case 4017: error_string=" Вызовы DLL не разрешены"; break;
case 4018: error_string=" Невозможно загрузить библиотеку"; break;
case 4019: error_string=" Невозможно вызвать функцию"; break;
case 4020: error_string=" Вызовы внешних библиотечных функций не разрешены"; break;
case 4021: error_string=" Недостаточно памяти для строки, возвращаемой из функции"; break;
case 4022: error_string=" Система занята"; break;
case 4050: error_string=" Неправильное количество параметров функции"; break;
case 4051: error_string=" Недопустимое значение параметра функции"; break;
case 4052: error_string=" Внутренняя ошибка строковой функции"; break;
case 4053: error_string=" Ошибка массива"; break;
case 4054: error_string=" Неправильное использование массива-таймсерии"; break;
case 4055: error_string=" Ошибка пользовательского индикатора"; break;
case 4056: error_string=" Массивы несовместимы"; break;
case 4057: error_string=" Ошибка обработки глобальныех переменных"; break;
case 4058: error_string=" Глобальная переменная не обнаружена"; break;
case 4059: error_string=" Функция не разрешена в тестовом режиме"; break;
case 4060: error_string=" Функция не подтверждена"; break;
case 4061: error_string=" Ошибка отправки почты"; break;
case 4062: error_string=" Ожидается параметр типа string"; break;
case 4063: error_string=" Ожидается параметр типа integer"; break;
case 4064: error_string=" Ожидается параметр типа double"; break;
case 4065: error_string=" В качестве параметра ожидается массив"; break;
case 4066: error_string=" Запрошенные исторические данные в состоянии обновления"; break;
case 4067: error_string=" Ошибка при выполнении торговой операции"; break;
case 4099: error_string=" Конец файла"; break;
case 4100: error_string=" Ошибка при работе с файлом"; break;
case 4101: error_string=" Неправильное имя файла"; break;
case 4102: error_string=" Слишком много открытых файлов"; break;
case 4103: error_string=" Невозможно открыть файл"; break;
case 4104: error_string=" Несовместимый режим доступа к файлу"; break;
case 4105: error_string=" Ни один ордер не выбран"; break;
case 4106: error_string=" Неизвестный символ"; break;
case 4107: error_string=" Неправильный параметр цены для торговой функции"; break;
case 4108: error_string=" Неверный номер тикета"; break;
case 4109: error_string=" Торговля не разрешена"; break;
case 4110: error_string=" Длинные позиции не разрешены"; break;
case 4111: error_string=" Короткие позиции не разрешены"; break;
case 4200: error_string=" Объект уже существует"; break;
case 4201: error_string=" Запрошено неизвестное свойство объекта"; break;
case 4202: error_string=" Объект не существует"; break;
case 4203: error_string=" Неизвестный тип объекта"; break;
case 4204: error_string=" Нет имени объекта"; break;
case 4205: error_string=" Ошибка координат объекта"; break;
case 4206: error_string=" Не найдено указанное подокно"; break;
case 4207: error_string=" Ошибка при работе с объектом"; break;
}
//----
return(error_string);
}
//===============================================================================================================================
Что-то советник сделок не открывает. Всё что написано в логе тестера это: 22:41:52 2007.01.15 03:00 unuversal GBPUSDm,M30: Как только цена изменится, Советник начнёт работу. И больше ни одной записи!
Возможно это из-за того, что в советнике отсутствует нормализация цен на открытие позиций.
Что-то советник сделок не открывает.
Всё что написано в логе тестера это:
22:41:52 2007.01.15 03:00 unuversal GBPUSDm,M30: Как только цена изменится, Советник начнёт работу.
И больше ни одной записи!
Возможно это из-за того, что в советнике отсутствует нормализация цен на открытие позиций.
Почему у меня всё прекрасно открывает?
Переприсоедини советника к графику по новой.
А вообще, он может наткнуться на занятость торгового потока и ждать пока поток освободится. Я не стал коммент писать по этому поводу, чтоб журнал не засорять. Может надо просто подождать ещё одного тика?
Есть ещё вариант - там установлен счётчик ордеров. Если устнаовленных отложенных ордеров достаточно то надпись не изменится. Комментов сейчас добавлю и будет отображаться и в логе в окне графика.
Что-то советник сделок не открывает.
Всё что написано в логе тестера это:
22:41:52 2007.01.15 03:00 unuversal GBPUSDm,M30: Как только цена изменится, Советник начнёт работу.
И больше ни одной записи!
Возможно это из-за того, что в советнике отсутствует нормализация цен на открытие позиций.
Я добавил комменты в код советника ну там и кое что ещё по мелочам. Изменённый код находится на месте прежнего (кстати поставил номер версии - см. вверху кода)
Так что можно смело копировать и компилировать его.
Просто гениально! ;o)
Потестите, потестите её... Это все тестируют.
Знаете, ломать - не строить. Можете предолжить лучше что н-ть взамен?
Знаете, ломать - не строить. Можете предолжить лучше что н-ть взамен?
Да в общем то открою секрет, что сам примерно так и вхожу в рынок. Это просто стандартное свойство пробойных систем. То есть вход при пробитии стопа противоположной позиции. Весь вопрос заключается в подборе условий, когда этот пробой окажется не ложным. А уж вариантов расчёта этого стопа огромнейшее многообразие. Я к примеру этот стоп беру либо по экстремуму предыдущего дня, либо по пробитию границы 99,9% доверительного интервала канала линейной регрессии. Мне кажется что важнее это не выбор стопа а определение условий, при которых может начаться сильное пробойное движение. Вот тут то всё и заключается. Будет это работать или не будет.
Знаете, ломать - не строить. Можете предолжить лучше что н-ть взамен?
Да в общем то открою секрет, что сам примерно так и вхожу в рынок. Это просто стандартное свойство пробойных систем. То есть вход при пробитии стопа противоположной позиции. Весь вопрос заключается в подборе условий, когда этот пробой окажется не ложным. А уж вариантов расчёта этого стопа огромнейшее многообразие. Я к примеру этот стоп беру либо по экстремуму предыдущего дня, либо по пробитию границы 99,9% доверительного интервала канала линейной регрессии. Мне кажется что самое главное это не выбор стопа а определение условий, при которых может начаться сильное пробойное движение.
Я недавно сделал советника. Вот алгоритм его работы:
// Трейлинг позиций в этом советнике обязателен!!!!
// Советник анализирует состояние торгов и в зависимости от состояния, в котором он
// находится, выполняет те или иные действия.
// Управление лотом здесь происходит по методу Мартингейла. Но это можно отключить.
// Состояния советника:
// Sost==1 - ордеров в рынке нет.
// В этом состоянии советник выставляет на 2 стоповых ордера с равным лотом
// на расстоянии LockLevel от текущей цены и прерходит в Sost==2.
// Лот определяется автоматически в зависимости от процента риска, который юзер задал вручную. Стоп-лосс обоих ордеров равен LockStopLoss.
// Sost==2 В рынке 2 отложенных ордера с равным лотом
// Как только 1 из ордеров сработает и станет рыночным,
// советник удаляет оставшийся отложенный ордер и прерходит в Sost==3.
// Sost==3 В рынке один рыночный (не отложенный ордер).
// Выставляем противоположно направленный отложенный ордер (если автоматика включена то лот будет другой; Поэтому предыдущую отложку приходится удалять) в точку Стоп-лосса
// рыночного ордера и переходим в состояние 4.
// Sost==4 В рынке 2 ордера. Один отложенный и один рыночный. Если рыночный ордер вдруг закрывается принудительно, например, по пипс-профиту, или его
// закрыл пользователь, то советник переходит в состояние 1, где он начинает всё сначала. Если сработал стоп-лосс или тейк-профит
// у этого ордера, то советник принимает решение, что ему делать. При срабатывании тейк-профита он открывает рыночный ордер
// в том же направлении, что и у сработавшего и с тем же лотом.
// При срабатывании стоп-лосса 2 ситуации:
// - Стоп-Лосс в зоне положительного профита:
// советник считает, что ситуация неопределённая, удаляет отложенный ордер и переходит в состояние 1, где начинает всё сначала.
// - Если стоп лосс сработал в зоне отрицательного профита или в точке нуля, то советник удаляет отложенный ордер, потом открывает
// рыночный ордер того же направления, что только что удалённый отложенный, но с удвоенным лотом если мартингейл включен, или с лотом,
// определяемым автоматически, если автолот включен, или с тем лотом, что выставил пользователь вручную, если автолот отключен. Далее он
// переходит в состояние № 3. Тут надо заметить, что если автолот отключен а мартингейл включен, то советник удвоит тот лот, который был установлен
// пользователем вручную в настройках в переменной Lots.
2 недели убил на то, чтоб нормально сделать код.
Начал тестировать - уходит в минуса даже при отключении всяких там мартингейлов и автоматов лота. Пробовал даже пипсовать на тестере. Всёравно сливает. Ну чтож, отрицательный результат сужает круг поиска. Словом, запустил на демо - пока торгует в плюс. Пожалуй самый трудный вопрос на форексе - это не столько момент входа в рынок, сколько что делать с образовавшимся вдруг профитом? Перебираю варианты. Словом, работа идёт :) ...
Только лазейку мне оставь малюсенькую, чтоб я мог тут код универсального трейлинга выложить, как и обещал людям ;)
Ну это ничего, всё ещё только начинается ;o) Я вот уже больше года программирую советники, при этом никаких трудностей при программировании не испытываю, а результат пока не слишком впечатляет.
Ну это ничего, всё ещё только начинается ;o) Я вот уже больше года программирую советники, при этом никаких трудностей при программировании не испытываю, а результат пока не слишком впечатляет.
Трудность была не код набрать, а алгоритм досконально продумать. Хотя, могу сказать, что знание MQL4 - довольно хороший инструмент. Вот кажется систему торговли разработал или отыскал хорошую. Кодишь её, тестишь и радости у тя поубавилось. Одно утешение остаётся, что не зарядил денег и не начал торговать по этой псевдосуперской системе. :))
Его возможности описаны в начале кода.
//+------------------------------------------------------------------+ //| Универсал_1.4.mq4 | //| Drknn | //| 10.02.2007 drknn@mail.ru | //+------------------------------------------------------------------+ #property copyright "Drknn" #property link "drknn@mail.ru" /* !!!!!!!!!!!!!! Внимание!!!!!!!!!!!!! В режиме отлова процента депозита советник закрывает все сделки по всем валютным парам, что может негативно повлиять на работу других советников, параллельно запущенных в терминале. Если советник будет настроен на отлов процента, и при этом ему будет разрешено как устанавливать отложенные ордера, так и при отлове удалять отложенные, то это может вызвать програмный конфликт. Вполне возможно, что на текущем тике советник не успеет закрыть все ордера а на следующем начнёт их ставить и тут же удалять, так как приказ на удаление ещё жив. Советник умеет: - тралить ордера любого типа (как рыночные, так и отложенные) - пипсовать - Ловить увеличение депозита на нужное количество процентов и, поймав закрыть сделки по всем валютным парам и, если нужно, удалить и отложенные ордера. - Устанавливать те отложенные ордера, которые разрешил пользователь, если советник вдруг обнаружит, что ордера такого в рынке нет (например, ордер сработал - стал рыночным - или были удалены ордера после отлова процента) - показывает на экране что и как у него настрено, чтоб каждый раз не лазить в настройки Советник задумывался как универсальный трейлинг, а всё остальное добавлено лишь для удобства. Ненужные функции можно легко отключить в окне свойств советника. Если пользователь разрешил советнику устанавливать отложенный ордер какого либо типа, то этот ордер будет установлен от текущей цены на расстоянии трейлингстопа для ордеров данного типа. */ // ================ Параметры, настраиваимые пользователем =========================== // ----- Параметры трала рыночных ордеров --------------------------------------------- extern int ryn_TrStop=15; //Трейлинг-Стоп рыночного ордера. Если = 0 то тарла нет extern int ryn_TrStep=3; //Шаг трала рыночного ордера extern bool WaitProfit = false; // Если true, то ждать профит = значению TrailingStop и только потом начинать тралить //Иначе, трейлинговать не дожидаясь положительного профита // ----- Параметры трала лимитных ордеров --------------------------------------------- extern int lim_TakeProfit=30; //Тейк-Профит лимитных ордеров extern int lim_StopLoss=15; //Стоп-Лосс лимитных ордеров extern int lim_TrStop=0; //Трейлинг-Стоп лимитных ордеров Если = 0 то тарла нет extern int lim_TrStep=3; //Шаг трейлинга лимитных ордеров // ----- Параметры трала стоповых ордеров --------------------------------------------- extern int st_TakeProfit=30; //Тейк-Профит стоповых ордеров extern int st_StopLoss=15; //Стоп-Лосс стоповых ордеров extern int st_TrStop=0; //Трейлинг-Стоп стоповых ордеров. Если = 0 то тарла нет extern int st_TrStep=3; //Шаг трала стоповых ордеров // ----- Разрешение установить тот или иной ордер ------------------------------------- extern double Lot=0.1;//Лот для установки отложенного ордера extern int st_Step=15;//Расстояние в пунктах от уровня текущей цены до уорвня установки стопового ордера extern int lim_Step=15;//Расстояние в пунктах от уровня текущей цены до уорвня установки лимитного ордера extern bool Ustan_BuyStop=true; //можно ли ставиь БайCтоп если в рынке такого у нас нет extern bool Ustan_SellLimit=false; //можно ли ставиь CеллЛимит если в рынке такого у нас нет extern bool Ustan_SellStop=true; //можно ли ставиь CеллCстоп если в рынке такого у нас нет extern bool Ustan_BuyLimit=false; //можно ли ставиь БайЛимит если в рынке такого у нас нет // ----- Параметры пипсовки ---------------------------------------------------- extern int PipsProfit=0; //профит при пипсовке можно ставить 1, 2, 3, ... extern int Proskalz = 3; //Проскальзывание в пунктах (нужно только когда PipsProfit>0) // ----------- Отлавливаем увеличение депозита -------------------------- extern bool Otlov=true;//отловить увеличение депозита на Pojmat процентов и закрыть все ордера //если Otlov=false, то значениt Pojmat не важно. extern double Pojmat=2.0;//процент желаемого увеличения депозита extern bool DelOtlozh=false;//Удалять ли при этом и отложенные ордера. //если Otlov=false, то значениt DelOtlozh не важно. // ----- Прочие установки ------------------------------------------------------ extern bool UseOrderSound = true; // Использовать звуковой сигнал для установки ордеров extern bool UseTrailingSound = true; // Использовать звуковой сигнал для трейлинга string NameOrderSound = "alert.wav"; // Наименование звукового файла для ордеров extern string NameTrallingSound = "expert.wav";// Наименование звукового файла для трейлинга // ======================================================================================= // ================== Глобальные переменные =============================================================== string Comm1,Comm2,Comm3,Comm4,Comm5,Comm6,Comm7,Comm8,Comm9,ED; double PNT,NewPrice,SL,TP,Balans,Free; int MinLevel,i,SchBuyStop,SchSellStop,SchBuyLimit,SchSellLimit,SchSell,SchBuy,SBid,SAsk,BBid,BAsk,Ts,GLE,total; bool fm,Rezult,TrailBuyStop,TrailSellStop,TrailBuyLimit,TrailSellLimit; // ======================================================================================================== //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- if(!IsExpertEnabled())//если ложь {Alert("Ошибка! Не нажата кнопка *Советники*"); Comment("Ошибка! Не нажата кнопка *Советники*"); return(0);} else {Comment("Как только цена изменится, Советник начнёт работу."); Print("Как только цена изменится, Советник начнёт работу.");} PNT=MarketInfo(Symbol(),MODE_POINT);//Размер пункта в валюте котировки. Для текущего инструмента хранится в предопределенной переменной Point MinLevel=MarketInfo(Symbol(),MODE_STOPLEVEL);//Минимально допустимый уровень стоп-лосса/тейк-профита в пунктах if(st_TrStop<MinLevel && st_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel); Print("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel); Alert("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel); return(0);} if(ryn_TrStop<MinLevel && ryn_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel); Print("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel); Alert("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel); return(0);} if(lim_TrStop<MinLevel && lim_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel); Print("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel); Alert("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel); return(0);} if(st_TrStop>=MinLevel && st_TrStep==0) {Comment("Ошибка! шаг тарала стоповых ордеров не может быть менее 1"); Print("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее 1"); Alert("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее 1"); return(0);} if(ryn_TrStop>=MinLevel && ryn_TrStep==0) {Comment("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1"); Print("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1"); Alert("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1"); return(0);} if(lim_TrStop>=MinLevel && lim_TrStep==0) {Comment("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1"); Print("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1"); Alert("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1"); return(0);} if(st_Step<MinLevel) {Comment("Ошибка! переменная st_Step не может быть менее ",MinLevel); Print("Ошибка! переменная st_Step не может быть менее ",MinLevel); Alert("Ошибка! переменная st_Step не может быть менее ",MinLevel); return(0);} if(lim_Step<MinLevel) {Comment("Ошибка! переменная lim_Step не может быть менее ",MinLevel); Print("Ошибка! переменная lim_Step не может быть менее ",MinLevel); Alert("Ошибка! переменная lim_Step не может быть менее ",MinLevel); return(0);} //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //---- RefreshRates(); //----Первичные проверки данных if(!IsTradeAllowed()) {Comment("Торговля запрещена в настройках терминала, либо торговый поток занят"); return(0);} //----Конец первичных проверок данных if(st_TrStop<MinLevel && st_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel); Print("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel); Alert("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее ",MinLevel); return(0);} if(ryn_TrStop<MinLevel && ryn_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel); Print("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel); Alert("Ошибка! ТрейлингСтоп рыночных ордеров не может быть менее ",MinLevel); return(0);} if(lim_TrStop<MinLevel && lim_TrStop!=0) {Comment("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel); Print("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel); Alert("Ошибка! ТрейлингСтоп лимитных ордеров не может быть менее ",MinLevel); return(0);} if(st_TrStop>=MinLevel && st_TrStep==0) {Comment("Ошибка! шаг тарала стоповых ордеров не может быть менее 1"); Print("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее 1"); Alert("Ошибка! ТрейлингСтоп стоповых ордеров не может быть менее 1"); return(0);} if(ryn_TrStop>=MinLevel && ryn_TrStep==0) {Comment("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1"); Print("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1"); Alert("Ошибка! Шаг тарала рыночных ордеров не может быть менее 1"); return(0);} if(lim_TrStop>=MinLevel && lim_TrStep==0) {Comment("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1"); Print("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1"); Alert("Ошибка! Шаг тарала лимитных ордеров не может быть менее 1"); return(0);} if(st_Step<MinLevel) {Comment("Ошибка! переменная st_Step не может быть менее ",MinLevel); Print("Ошибка! переменная st_Step не может быть менее ",MinLevel); Alert("Ошибка! переменная st_Step не может быть менее ",MinLevel); return(0);} if(lim_Step<MinLevel) {Comment("Ошибка! переменная lim_Step не может быть менее ",MinLevel); Print("Ошибка! переменная lim_Step не может быть менее ",MinLevel); Alert("Ошибка! переменная lim_Step не может быть менее ",MinLevel); return(0);} if(ryn_TrStop>0 && ryn_TrStop>=MinLevel) Comm1="Трал рыночных - Вкл."; else Comm1="Трал рыночных - Откл."; if (lim_TrStop>0 && lim_TrStop>=MinLevel) Comm2="Трал лимитных - Вкл."; else Comm2="Трал лимитных - Откл."; if (st_TrStop>0 && st_TrStop>=MinLevel) Comm3="Трал стоповых - Вкл."; else Comm3="Трал стоповых - Откл."; if (PipsProfit>0) Comm4="Пипсовка - Вкл"; else Comm4="Пипсовка - Откл"; double Otl=(Balans/100*Pojmat+Balans); Otl=NormalizeDouble(Otl, 2); Ts=MathCeil(Otl); if (Otlov) {Comm5="Отлов процента - Вкл"; Comm6="Ловим сумму = "+Ts+" $";} else {Comm5="Отлов процента - Откл";Comm6="";} SchOrders(); Comment("Ордеров сейчас для ",Symbol()," :","\n","Buy = ",SchBuy," Sell = ",SchSell,"\n","BuyStop = ",SchBuyStop, " SellLimit = ",SchSellLimit,"\n","SellStop = ",SchSellStop," BuyLimit = ",SchBuyLimit,"\n",Comm1, "\n",Comm2,"\n",Comm3,"\n",Comm4,"\n",Comm5,"\n",Comm6); //-------------- Отлавливаем увеличение депозита на Pojmat процентов ------------------------ if(Otlov)//Если разрешено отловить процент увеличения депозита { Balans=AccountBalance();//Баланс счёта Free=AccountEquity();//Текущее количество денег в статье "Средства" if ((Free-Balans)>=(Balans/100*Pojmat))//Если денег стало достаточно { Print("Депозит увеличен на ",Pojmat," процентов.","\n","Закрываем позиции."); Comment("Депозит увеличен на ",Pojmat," процентов.","\n","Закрываем позиции."); if (DelOtlozh) { DeleteAllOrders();//удаляем из рынка все ордера Sleep(5000); RefreshRates(); } else { DelRynochn(); Sleep(5000); RefreshRates(); } SchOrders(); } } //-------------------------------------------------------------------------------------------- //=================Начало пипсовки========================== if (PipsProfit>0) { int total = OrdersTotal(); for (int i = 0; i<total; i++ )//Цикл. Проходим по всем ордерам от 0 до total {//Начало цикла if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка ", GLE, " при выборе ордера номер ",i); Print ("Описание ошибки - ",ED); } if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true)// выбрали очередной ордер {//начало работы с выбранным ордером if(OrderSymbol()!=Symbol()) continue; // Если не наш - смотрим следующий if(OrderType()==OP_BUY) // если он открытый в покупку, то... { if(Bid>=(OrderOpenPrice()+PipsProfit*Point)) {OrderClose(OrderTicket(),OrderLots(),Bid,Proskalz);} } if(OrderType()==OP_SELL)// если он открытый в продажу, то... { if(Ask<=(OrderOpenPrice() - PipsProfit*Point)) OrderClose(OrderTicket(),OrderLots(),Ask,Proskalz); } } // конец работы с выбранным ордером }// Конец цикла, мы просмотрели все ордера. ---------------------------------------------------------- } //================Конец пипсовки ====================================== //===================== Установка отложенных ордеров =========================================================================== RefreshRates(); SchOrders(); if(SchSellStop==0 && Ustan_SellStop && st_Step>=MinLevel) { NewPrice=Bid-st_Step*Point; if(st_StopLoss==0) SL=0.0000; else SL=NewPrice+st_StopLoss*Point; if(st_TakeProfit==0) TP=0.0000; else TP=NewPrice-st_TakeProfit*Point; fm=OrderSend(Symbol(),OP_SELLSTOP,Lot,NewPrice,3,SL,TP,NULL,0,0,CLR_NONE); /*Сигналим*/ if(fm!=0 && fm!=-1 && UseOrderSound) PlaySound(NameOrderSound); /*Комментируем*/ if(fm!=0 && fm!=-1) {Print("Ордер SellStop установлен"); Comment("Ордер SellStop установлен"); Sleep(5000); RefreshRates();} if(fm==0 || fm==-1)//Если установить не удалось { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка № ",GLE," установки SellStop-ордера"); Print ("Описание ошибки - ",ED); } } if(SchBuyStop==0 && Ustan_BuyStop && st_Step>=MinLevel) { NewPrice=Ask+st_Step*Point; if(st_StopLoss==0) SL=0.0000; else SL=NewPrice-st_StopLoss*Point; if(st_TakeProfit==0) TP=0.0000; else TP=NewPrice+st_TakeProfit*Point; fm=OrderSend(Symbol(),OP_BUYSTOP,Lot,NewPrice,3,SL,TP,NULL,0,0,CLR_NONE); /*Сигналим*/ if(fm!=0 && fm!=-1 && UseOrderSound) PlaySound(NameOrderSound); /*Комментируем*/ if(fm!=0 && fm!=-1) {Print("Ордер BuyStop установлен"); Comment("Ордер BuyStop установлен"); Sleep(5000); RefreshRates();} if(fm==0 || fm==-1)//Если установить не удалось { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка № ",GetLastError()," установки BuyStop-ордера"); Print ("Описание ошибки - ",ED); } } if(SchBuyLimit==0 && Ustan_BuyLimit && lim_Step>=MinLevel) { NewPrice=Ask-lim_Step*Point; if(st_StopLoss==0) SL=0.0000; else SL=NewPrice-st_StopLoss*Point; if(st_TakeProfit==0) TP=0.0000; else TP=NewPrice+st_TakeProfit*Point; fm=OrderSend(Symbol(),OP_BUYLIMIT,Lot,NewPrice,3,SL,TP,NULL,0,0,CLR_NONE); /*Сигналим*/ if(fm!=0 && fm!=-1 && UseOrderSound) PlaySound(NameOrderSound); /*Комментируем*/ if(fm!=0 && fm!=-1) {Print("Ордер BuyLimit установлен"); Comment("Ордер BuyLimit установлен"); Sleep(5000); RefreshRates();} if(fm==0 || fm==-1)//Если установить не удалось { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка № ",GetLastError()," установки BuyLimit-ордера"); Print ("Описание ошибки - ",ED); } } if(SchSellLimit==0 && Ustan_SellLimit && lim_Step>=MinLevel) { NewPrice=Bid+lim_Step*Point; if(st_StopLoss==0) SL=0.0000; else SL=NewPrice+st_StopLoss*Point; if(st_TakeProfit==0) TP=0.0000; else TP=NewPrice-st_TakeProfit*Point; fm=OrderSend(Symbol(),OP_SELLLIMIT,Lot,NewPrice,3,SL,TP,NULL,0,0,CLR_NONE); /*Сигналим*/ if(fm!=0 && fm!=-1 && UseOrderSound) PlaySound(NameOrderSound); /*Комментируем*/ if(fm!=0 && fm!=-1) {Print("Ордер SellLimit установлен"); Comment("Ордер SellLimit установлен"); Sleep(5000); RefreshRates();} if(fm==0 || fm==-1)//Если установить не удалось { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка № ",GetLastError()," установки SellLimit-ордера"); Print ("Описание ошибки - ",ED); } } //============================================================================================================================== // ================= Трейлинг Рыночных ордеров ================================================================================== RefreshRates(); SchOrders(); if(ryn_TrStop>=MinLevel && ryn_TrStep>0 && (SchBuy>0 || SchSell>0)) { for (i=0; i<OrdersTotal(); i++)//Проходим по всем ордерам { if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка ", GLE, " при выборе ордера номер ",i); Print ("Описание ошибки - ",ED); } if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if (OrderSymbol()==Symbol()) { TrailingPositions(); } } } } if(ryn_TrStop>=MinLevel && ryn_TrStep==0) Alert("Трейлинг невозможен - ноль в настройках советника"); // =============================================================================================================================== //============ Трейлинг отложенных ордеров ============================================================= RefreshRates(); SchOrders();//Обновляем счётчики количества ордеров if((st_TrStop>0 && SchBuyStop+SchSellStop>0) || (SchBuyLimit+SchSellLimit>0 && lim_TrStop>0)) { TrailBuyStop=false; TrailSellStop=false; TrailBuyLimit=false; TrailSellLimit=false; for (i=OrdersTotal()-1;i>=0;i--)//Цикл. Проходим по всем ордерам от 0 до total {//Начало цикла if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка ", GLE, " при выборе ордера номер ",i); Print ("Описание ошибки - ",ED); } if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true)// выбрали очередной ордер {//начало работы с выбранным ордером if(OrderSymbol()!=Symbol() || OrderType()==OP_BUY || OrderType()==OP_SELL) continue; // Если не наш - смотрим следующий if(OrderType()==OP_BUYSTOP) // Он наверху и едет вниз { if(Ask<OrderOpenPrice()-(st_TrStop+st_TrStep)*Point) TrailBuyStop=true; } if(OrderType()==OP_SELLLIMIT) // Он наверху и едет вниз { if(Bid<OrderOpenPrice()-(st_TrStop+st_TrStep)*Point) TrailSellLimit=true; } if(OrderType()==OP_SELLSTOP) // Он внизу и едет вверх { if(Bid>OrderOpenPrice()+(st_TrStop+st_TrStep)*Point) TrailSellStop=true; } if(OrderType()==OP_BUYLIMIT) // Он внизу и едет вверх { if(Ask>OrderOpenPrice()+(st_TrStop+st_TrStep)*Point) TrailBuyLimit=true; } }//конец работы с выбранным ордером }//Конец цикла if (TrailSellLimit || TrailBuyLimit || TrailSellStop || TrailBuyStop) TrailingOtlozh(); } //==================================================================================================== //---- return(0); } //+ ========================== Конец работы советника ========================================================================== + // ___________________________________________________________________________________________ //| | //| | //| Далее идут подпрограммы (функции), | //| которые в случае надобности вызываются из тела советника | //| | //|___________________________________________________________________________________________| //=========== Счётчики количества ордеров ================================================================= // Функция SchOrders() проходит по всем ордерам и подсчитывает, сколько сейчас имеется ордеров каждого типа. // Как только понадобятся значение того или иного счётчика, нужно сначала вызвать функцию SchOrders() // Она обновит данные и потом можно смело вызывать тот или иной счётчик. // SchBuyStop - счётчик ордеров BuyStop // SchSellStop - счётчик ордеров SellStop // // SchBuyLimit - счётчик ордеров BuyLimit // SchSellLimit счётчик ордеров SellLimit // SchBuy - счётчик Buy ордеров // SchSell - счётчик Sell ордеров //---------------------------------------------------------------------------------------------------------- void SchOrders() { // для начала работы счётчиков мы их обнуляем SchBuyStop=0; SchSellStop=0; SchBuyLimit=0; SchBuy=0; SchSell=0; SchSellLimit=0; for (i=OrdersTotal()-1;i>=0;i--)//Цикл. Проходим по всем ордерам от 0 до total {//Начало цикла if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка ", GLE, " при выборе ордера номер ",i); Print ("Описание ошибки: ",ED); } if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))// выбрали очередной ордер {//начало работы с выбранным ордером if(OrderSymbol()!=Symbol()) continue; // Если не наш - смотрим следующий if(OrderType()==OP_BUYSTOP) // если он BUYSTOP, то... SchBuyStop++;//увеличиваем значение счётчиков на 1 if(OrderType()==OP_SELLSTOP) // если он SELLSTOP, то... SchSellStop++; //увеличиваем значение счётчиков на 1 if(OrderType()==OP_SELLLIMIT) SchSellLimit++; if(OrderType()==OP_BUYLIMIT) SchBuyLimit++; if(OrderType()==OP_BUY) // если он открытый в покупку, то... SchBuy++;//увеличиваем значение счётчиков на 1 if(OrderType()==OP_SELL)// если он открытый в продажу, то... SchSell++;//увеличиваем значение счётчиков на 1 }//конец работы с выбранным ордером }//Конец цикла } //========================================================================================================== //+------------------------------------------------------------------+ //| Сопровождение позиции простым тралом | //+------------------------------------------------------------------+ void TrailingPositions()//Описание (объявление) пользовательской функции { if(OrderType()==OP_BUY)//Если выбранный в цикле ордер в покупку { if(!WaitProfit || (Bid-OrderOpenPrice())>ryn_TrStop*Point) { if (OrderStopLoss()<Bid-(ryn_TrStop+ryn_TrStep-1)*Point) {ModifyStopLoss(Bid-ryn_TrStop*Point);} } } if(OrderType()==OP_SELL) { if(!WaitProfit || OrderOpenPrice()-Ask>ryn_TrStop*Point) { if(OrderStopLoss()>Ask+(ryn_TrStop+ryn_TrStep-1)*Point || OrderStopLoss()==0) {ModifyStopLoss(Ask+ryn_TrStop*Point);} } } } //+------------------------------------------------------------------+ //| Перенос уровня StopLoss | //| Параметры: | //| ldStopLoss - уровень StopLoss | //+------------------------------------------------------------------+ void ModifyStopLoss(double ldStopLoss) { fm=OrderModify(OrderTicket(),OrderOpenPrice(),ldStopLoss,OrderTakeProfit(),0,CLR_NONE); if(fm!=0 && fm!=-1 && UseTrailingSound) PlaySound(NameTrallingSound); if(fm==0 || fm==-1) { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Модификация ",Symbol(),"-ордера № ",OrderTicket()," вызвала ошибку № ",GLE); Print ("Описание ошибки: ",ED); } } //+------------------------------------------------------------------+ //======== Подтягивание отложенного ордера вслед ценой ============================================ // Функция TrailingOtlozh() подтягивает отложенный ордер вслед за ценой //-------------------------------------------------------------------------------------------------- void TrailingOtlozh() { RefreshRates(); for (i=OrdersTotal()-1;i>=0;i--)//Цикл. Проходим по всем ордерам {//Начало цикла if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка ", GLE, " при выборе ордера номер ",i); Print ("Описание ошибки: ",ED); } if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))// выбрали очередной ордер {//начало работы с выбранным ордером if(OrderSymbol()!=Symbol()) {} // Если не наш - смотрим следующий if(OrderType()==OP_BUYSTOP)//находится вверху, едет вниз { if(TrailBuyStop) { NewPrice=Ask+st_TrStop*Point; if(st_StopLoss==0) SL=0.0000; else SL=NewPrice-st_StopLoss*Point; if(st_TakeProfit==0) TP=0.0000; else TP=NewPrice+st_TakeProfit*Point; Rezult=false; Rezult=OrderModify(OrderTicket(),NewPrice,SL,TP,0,CLR_NONE); if(fm!=0 && fm!=-1 && UseTrailingSound) PlaySound(NameTrallingSound); if(Rezult!=0 && Rezult!=-1) Sleep(5000); if(Rezult==0 || Rezult==-1) { Print("Корректировка BUYSTOP-ордера № ",OrderTicket(), " вернула ошибку № ",GetLastError()); Print("NewPrice BUYSTOP-ордера = ",NewPrice); //Print("StopLoss BUYSTOP-ордера = ",SL); //Print("TakeProfit BUYSTOP-ордера = ",TP); } } } if(OrderType()==OP_SELLSTOP) // Находится внизу, едет вверх { if(TrailSellStop) { NewPrice=Bid-st_TrStop*Point; if(st_StopLoss==0) SL=0.0000; else SL=NewPrice+st_StopLoss*Point; if(st_TakeProfit==0) TP=0.0000; else TP=NewPrice-st_TakeProfit*Point; Rezult=false; Rezult=OrderModify(OrderTicket(),NewPrice,SL,TP,0,CLR_NONE); if(fm!=0 && fm!=-1 && UseTrailingSound) PlaySound(NameTrallingSound); if(Rezult!=0 && Rezult!=-1) Sleep(5000); if(Rezult==0 || Rezult==-1) { Print("Корректировка SELLSTOP-ордера № ",OrderTicket(), " вернула ошибку № ",GetLastError()); Print("NewPrice SELLSTOP-ордера = ",NewPrice); //Print("StopLoss SELLSTOP-ордера = ",SL); //Print("TakeProfit SELLSTOP-ордера = ",TP); } } } if(OrderType()==OP_BUYLIMIT) // Находится внизу, едет вверх { if(TrailBuyLimit) { NewPrice=Ask-st_TrStop*Point; if(st_StopLoss==0) SL=0.0000; else SL=NewPrice-st_StopLoss*Point; if(st_TakeProfit==0) TP=0.0000; else TP=NewPrice+st_TakeProfit*Point; Rezult=false; Rezult=OrderModify(OrderTicket(),NewPrice,SL,TP,0,CLR_NONE); if(fm!=0 && fm!=-1 && UseTrailingSound) PlaySound(NameTrallingSound); if(Rezult!=0 && Rezult!=-1) Sleep(5000); if(Rezult==0 || Rezult==-1) { Print("Корректировка BUYLIMIT-ордера № ",OrderTicket(), " вернула ошибку № ",GetLastError()); Print("NewPrice BUYLIMIT-ордера = ",NewPrice); //Print("StopLoss BUYLIMIT-ордера = ",SL); //Print("TakeProfit BUYLIMIT-ордера = ",TP); } } } if(OrderType()==OP_SELLLIMIT)//находится вверху, едет вниз { if(TrailSellLimit) { NewPrice=Bid+st_TrStop*Point; if(st_StopLoss==0) SL=0.0000; else SL=NewPrice+st_StopLoss*Point; if(st_TakeProfit==0) TP=0.0000; else TP=NewPrice-st_TakeProfit*Point; Rezult=false; Rezult=OrderModify(OrderTicket(),NewPrice,SL,TP,0,CLR_NONE); if(fm!=0 && fm!=-1 && UseTrailingSound) PlaySound(NameTrallingSound); if(Rezult!=0 && Rezult!=-1) Sleep(5000); if(Rezult==0 || Rezult==-1) { Print("Корректировка SELLLIMIT-ордера № ",OrderTicket(), " вернула ошибку № ",GetLastError()); Print("NewPrice SELLLIMIT-ордера = ",NewPrice); //Print("StopLoss SELLLIMIT-ордера = ",SL); //Print("TakeProfit SELLLIMIT-ордера = ",TP); } } } }//конец работы с выбранным ордером }//Конец цикла }//конец функции //========================================================================================= //=========== Удаление ВСЕХ ИМЕЮЩИХСЯ в рынке ордеров ======================== // Функция DeleteAllOrders() // Удаляет ВСЕ ИМЕЮЩИЕСЯ ордера - и рыночные и отложенные, // независимо от того, к какой валютной паре прицеплен советник //---------------------------------------------------------------------------- bool DeleteAllOrders() { for (int i=OrdersTotal()-1; i>=0; i--) { if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка ", GLE, " при выборе ордера номер ",i); Print ("Описание ошибки - ",ED); } if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if (OrderType()==OP_BUYLIMIT || OrderType()==OP_SELLLIMIT || OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP) OrderDelete(OrderTicket()); if(OrderType()==OP_BUY) // если он открытый в покупку, то... OrderClose(OrderTicket(),OrderLots(),Bid,3); if(OrderType()==OP_SELL)// если он открытый в продажу, то... OrderClose(OrderTicket(),OrderLots(),Ask,3); } } } //============================================================================ // ======== Удаление только рыночных ордеров ================================ // Удаляет ВСЕ рыночные ордера, // независимо от того, к какой валютной паре прицеплен советник //---------------------------------------------------------------------------- void DelRynochn() { for (int i=OrdersTotal()-1; i>=0; i--) { if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { GLE=GetLastError(); ED=ErrorDescription(GLE); Print("Ошибка ", GLE, " при выборе ордера номер ",i); Print ("Описание ошибки - ",ED); } if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderType()==OP_BUY) // если он открытый в покупку, то... OrderClose(OrderTicket(),OrderLots(),Bid,3); if(OrderType()==OP_SELL)// если он открытый в продажу, то... OrderClose(OrderTicket(),OrderLots(),Ask,3); } } } //============================================================================ //========= Словестное описание ошибок ========================================================================================= // Функция возвращает не код ошибки а её словестное описание //----------------------------------------------------------- string ErrorDescription(int error_code) { string error_string; //---- switch(error_code) { //---- codes returned from trade server case 0: error_string=" Нет ошибки"; break; case 1: error_string=" Нет ошибки, но результат неизвестен"; break; case 2: error_string=" Общая ошибка"; break; case 3: error_string=" Неправильные параметры"; break; case 4: error_string=" Торговый сервер занят"; break; case 5: error_string=" Старая версия клиентского терминала"; break; case 6: error_string=" Нет связи с торговым сервером"; break; case 7: error_string=" Недостаточно прав"; break; case 8: error_string=" Слишком частые запросы"; break; case 9: error_string=" Недопустимая операция нарушающая функционирование сервера"; break; case 64: error_string=" Счет заблокирован"; break; case 65: error_string=" Неправильный номер счета"; break; case 128: error_string=" Истек срок ожидания совершения сделки"; break; case 129: error_string=" Неправильная цена"; break; case 130: error_string=" Неправильные стопы"; break; case 131: error_string=" Неправильный объем"; break; case 132: error_string=" Рынок закрыт"; break; case 133: error_string=" Торговля запрещена"; break; case 134: error_string=" Недостаточно денег для совершения операции"; break; case 135: error_string=" Цена изменилась"; break; case 136: error_string=" Нет цен"; break; case 137: error_string=" Брокер занят"; break; case 138: error_string=" Новые цены"; break; case 139: error_string=" Ордер заблокирован и уже обрабатывается"; break; case 140: error_string=" Разрешена только покупка"; break; case 141: error_string=" Слишком много запросов"; break; case 145: error_string=" Модификация запрещена, так как ордер слишком близок к рынку"; break; case 146: error_string=" Подсистема торговли занята"; break; case 147: error_string=" Использование даты истечения ордера запрещено брокером"; break; case 148: error_string=" Количество открытых и отложенных ордеров достигло предела, установленного брокером"; break; case 4000: error_string=" Нет ошибки"; break; case 4001: error_string=" Неправильный указатель функции"; break; case 4002: error_string=" Индекс массива - вне диапазона"; break; case 4003: error_string=" Нет памяти для стека функций"; break; case 4004: error_string=" Переполнение стека после рекурсивного вызова"; break; case 4005: error_string=" На стеке нет памяти для передачи параметров"; break; case 4006: error_string=" Нет памяти для строкового параметра"; break; case 4007: error_string=" Нет памяти для временной строки"; break; case 4008: error_string=" Неинициализированная строка"; break; case 4009: error_string=" Неинициализированная строка в массиве"; break; case 4010: error_string=" Нет памяти для строкового массива"; break; case 4011: error_string=" Слишком длинная строка"; break; case 4012: error_string=" Остаток от деления на ноль"; break; case 4013: error_string=" Деление на ноль"; break; case 4014: error_string=" Неизвестная команда"; break; case 4015: error_string=" Неправильный переход"; break; case 4016: error_string=" Неинициализированный массив"; break; case 4017: error_string=" Вызовы DLL не разрешены"; break; case 4018: error_string=" Невозможно загрузить библиотеку"; break; case 4019: error_string=" Невозможно вызвать функцию"; break; case 4020: error_string=" Вызовы внешних библиотечных функций не разрешены"; break; case 4021: error_string=" Недостаточно памяти для строки, возвращаемой из функции"; break; case 4022: error_string=" Система занята"; break; case 4050: error_string=" Неправильное количество параметров функции"; break; case 4051: error_string=" Недопустимое значение параметра функции"; break; case 4052: error_string=" Внутренняя ошибка строковой функции"; break; case 4053: error_string=" Ошибка массива"; break; case 4054: error_string=" Неправильное использование массива-таймсерии"; break; case 4055: error_string=" Ошибка пользовательского индикатора"; break; case 4056: error_string=" Массивы несовместимы"; break; case 4057: error_string=" Ошибка обработки глобальныех переменных"; break; case 4058: error_string=" Глобальная переменная не обнаружена"; break; case 4059: error_string=" Функция не разрешена в тестовом режиме"; break; case 4060: error_string=" Функция не подтверждена"; break; case 4061: error_string=" Ошибка отправки почты"; break; case 4062: error_string=" Ожидается параметр типа string"; break; case 4063: error_string=" Ожидается параметр типа integer"; break; case 4064: error_string=" Ожидается параметр типа double"; break; case 4065: error_string=" В качестве параметра ожидается массив"; break; case 4066: error_string=" Запрошенные исторические данные в состоянии обновления"; break; case 4067: error_string=" Ошибка при выполнении торговой операции"; break; case 4099: error_string=" Конец файла"; break; case 4100: error_string=" Ошибка при работе с файлом"; break; case 4101: error_string=" Неправильное имя файла"; break; case 4102: error_string=" Слишком много открытых файлов"; break; case 4103: error_string=" Невозможно открыть файл"; break; case 4104: error_string=" Несовместимый режим доступа к файлу"; break; case 4105: error_string=" Ни один ордер не выбран"; break; case 4106: error_string=" Неизвестный символ"; break; case 4107: error_string=" Неправильный параметр цены для торговой функции"; break; case 4108: error_string=" Неверный номер тикета"; break; case 4109: error_string=" Торговля не разрешена"; break; case 4110: error_string=" Длинные позиции не разрешены"; break; case 4111: error_string=" Короткие позиции не разрешены"; break; case 4200: error_string=" Объект уже существует"; break; case 4201: error_string=" Запрошено неизвестное свойство объекта"; break; case 4202: error_string=" Объект не существует"; break; case 4203: error_string=" Неизвестный тип объекта"; break; case 4204: error_string=" Нет имени объекта"; break; case 4205: error_string=" Ошибка координат объекта"; break; case 4206: error_string=" Не найдено указанное подокно"; break; case 4207: error_string=" Ошибка при работе с объектом"; break; } //---- return(error_string); } //===============================================================================================================================Всё что написано в логе тестера это:
22:41:52 2007.01.15 03:00 unuversal GBPUSDm,M30: Как только цена изменится, Советник начнёт работу.
И больше ни одной записи!
Возможно это из-за того, что в советнике отсутствует нормализация цен на открытие позиций.
Всё что написано в логе тестера это:
22:41:52 2007.01.15 03:00 unuversal GBPUSDm,M30: Как только цена изменится, Советник начнёт работу.
И больше ни одной записи!
Возможно это из-за того, что в советнике отсутствует нормализация цен на открытие позиций.
Почему у меня всё прекрасно открывает?
Переприсоедини советника к графику по новой.
А вообще, он может наткнуться на занятость торгового потока и ждать пока поток освободится. Я не стал коммент писать по этому поводу, чтоб журнал не засорять. Может надо просто подождать ещё одного тика?
Есть ещё вариант - там установлен счётчик ордеров. Если устнаовленных отложенных ордеров достаточно то надпись не изменится. Комментов сейчас добавлю и будет отображаться и в логе в окне графика.
Всё что написано в логе тестера это:
22:41:52 2007.01.15 03:00 unuversal GBPUSDm,M30: Как только цена изменится, Советник начнёт работу.
И больше ни одной записи!
Возможно это из-за того, что в советнике отсутствует нормализация цен на открытие позиций.
Я добавил комменты в код советника ну там и кое что ещё по мелочам. Изменённый код находится на месте прежнего (кстати поставил номер версии - см. вверху кода)
Так что можно смело копировать и компилировать его.