Обучение языку MQL4 под MetaTrader 4📌

От xbms, 13 апреля, 2013 в Уголок Программиста

#5251

хранение в индикаторе 1000 значений разве влияет на производительность?

Само по себе хранение не влияет, на реале если вызывать индюк на открытии бара - почти не заметно, по при тестировании - влияет, в основном все за время теста и опта бьются... При вызове индюка происходит масса телодвижений терема - создаются стеки вызова и прочие низкоуровневые движения. Вот Вы знаете сколько экземпляров индюка в памяти при вызове из совы с помощью iCustom нескольких буферов одного индюка с одинаковыми настройками? Я так и не выяснил, но терзают смутные сомнения.
#5252

Эх, :-H ещё один глупый вопрос по MQL4.
Как говорилось выше, изучаю советника.
В советнике есть функция void Start(). Если я правильно понимаю, то она выполняется только при старте советника? Но справка говорит, что событие Start присуще только скриптам, но ни как не индикаторам и советникам. Другие источники говорят, что Start() - это OnTick().
Исходя из непонимания данного события, я недопонимаю логику советника. Подтолкните, пожалуйста, в нужное направление ^:)^.

#5253

start - это OnTick, выполняется каждый тик
init(), start(), и deinit() - устаревшие названия. им соответствуют OnInit(), OnTick() и OnDeinit()
OnStart() - не равно start()
при запуске скриптов - выполняется OnStart(), а при запуске советников и индикаторов - OnInit()

#5254

Не получается запустить трал, ордера открывает в безубыток переносит, а тралить не хочет в чем может быть ошибка?


void OnTick()
{
if (TrailingStop!=0) Trailing();

if ( isNewBar() )
{
Основная программа (открытие ордеров по условию)

}
{
Перенос ордеров в безубыток

}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
void Trailing()
{
for(int i=OrdersTotal() - 1; i>= 0; i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
if(OrderSymbol()==Symbol()||OrderMagicNumber()==Magic)
if(OrderType()==OP_BUY)
{
if(TrailingStop>0)
{
if(Bid-OrderOpenPrice()>TrailingStop)
{

int sl = NormalizeDouble(Bid - TrailingStop*Point, Digits);
OrderModify(OrderTicket(),OrderOpenPrice(), sl,OrderTakeProfit(),0,Green);

}
}
}

#5255


if(OrderSymbol()==Symbol()||OrderMagicNumber()==Magic)


if(OrderSymbol()==Symbol()&&OrderMagicNumber()==Magic)

if(Bid-OrderOpenPrice()>TrailingStop)


if(Bid-OrderOpenPrice()>TrailingStop*Point)
#5256

Подправил, не помогло :(

#5257

Если после OP_BUY далее идёт такое же условие, только с OP_SELL, то оно выполняться не будет, т.к., код после

      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
if(OrderSymbol()==Symbol()||OrderMagicNumber()==Magic)
не заключён в фигурные скобки

Проще бы так:
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=Magic) continue;
#5258

Всем спасибо за помощь, получилось. Перепутал тип переменных СтопЛос обозначил как int а надо было double

#5259

Универсальное решение- считывать показания индикаторов 1 раз в свечу.
Все остальное перечисленное , ИМХО, не поможет .(помещать код индикатора в свечу говорят поможет, но на сколько...)


это интересно. а как это в общих чертах лучше реализовать?
- взять расчетную часть инд. в условие if(NewBar()).
- установить в сове вызов iCustom в условие if(NewBar())
- или ка то по другому?
#5260

- установить в сове вызов iCustom в условие if(NewBar())


Я бы так сделал... Если логика индикатора позволяет обращаться раз в свечу
#5261

Подскажите как закрывать ордера в определенный день и час, или допустим через определенное время после открытия?

#5262

Подскажите как закрывать ордера в определенный день и час, или допустим через определенное время после открытия?

Примерно так:
if ( Day() == 5 && Hour() == 18 ) OrderClose(...);
или
if ( TimeCurrent() - OrderOpenTime() > minutClose * 60 ) OrderClose(...);
#5263

Доброго времени суток, уважаемые программисты.
Цель: отследить исполнение TP сделок, открытых советником.
Мой метод: После расчета TP и перед его модификацией записываю OrderTicket() в переменную LastOrderTicket. По каждому тику сравниваю значение переменной с последним ордером в истории сделок LastHistOrderTicket (отдельно для buy, отдельно для sell).
Проблема: Среди множества сделок (несколько лет истории) нашлась одна нехорошая, которая закрылась по TP слишком быстро, настолько быстро, что LastOrderTicket не успел модифицировать. Тестирование на "Контрольных точках", на "Тиках" все проходит, на демке тоже пока без проблем, но хотелось бы решить эту проблему для всех методов тестирования.
Часть кода прилагается:

Спойлер

void OnTick(){
fOrdersHistoryCounting();
for(int pos=OrdersTotal()-1;pos>=0;pos--){
if(!OrderSelect(pos,SELECT_BY_POS,MODE_TRADES)) continue;
if(OrderType()==OP_BUY && OrderMagicNumber()==MagicNumber && OrderSymbol()==_Symbol){
BLastOrderTicket=OrderTicket();
if(OrderTakeProfit()!=NormalizeDouble(B_Take_Profit,Digits)){
fModifyPosition(OrderTicket(),OrderOpenPrice(),OrderStopLoss(),NormalizeDouble(B_Take_Profit,Digits),OrderExpiration(),clrRed);
}
}
}
}
void fOrdersHistoryCounting()
{
for(int pos=0;pos {
if(!OrderSelect(pos,SELECT_BY_POS,MODE_HISTORY)) continue;
if(OrderType()==OP_BUY && OrderMagicNumber()==MagicNumber && OrderSymbol()==_Symbol) BLastHistOrderTicket=OrderTicket();
}
if(BLastHistOrderTicket==BLastOrderTicket){
buy=0;
}
}

Изменено 25 октября, 2018 пользователем Finchi

#5264
Finchi если правильно понял, то нужно понять закрыт -ли ордер по ТП?
Я при этом ни чего не сохраняю, просто перебирая закрытые ордера сравниваю ТП с ценой закрытия и если не далее Слиппажа - значит ТП состоялся. Сейчас в моде частичные закрытия и даже открытия, т.е. получаются в истории не один ордер с известным тикетом, а несколько (лично видел 3 шт.), поэтому Ваш алгоритм с сохранением тикета может выдать неожиданный результат.
#5265

Такой вопрос:
Нашел в сети индикатор ProFx_Strength_Oscillator, он привязан к DLL ProFx32.dll. В тестере стратегий индикатор гоняется нормально и бегло.
Захотел написать с ним советник и тут уже терминал просто начинает виснуть и тормозить при взятии данных c индюка раз в бар.

Спойлер

double ProFSO_Neutral1 = iCustom(NULL,0,"ProFx_Strength_Oscillator",ProFSO_Period1,ProFSO_Period2,ProFSO_Period3,PRICE_CLOSE,Indicators_BarCount,1,1);

После остановки тестера прошло 5 баров, и тут же на графике отображается 5 индикаторов, хотя должен один.
Никогда с таким не сталкивался при работе с iCustom...
Может быть проблема в DLL к которому этот индюк привязан?

Снимок.PNG
ProFx_Strength_Oscillator.rar1 скач.

#5266

Может быть проблема в DLL к которому этот индюк привязан?


Возможно - длл ведь ломаный, а может и др., причины.
#5267

Может быть проблема в DLL к которому этот индюк привязан?

Тоже впервые вижу. По идее длл не может контролировать терем - она про него ничего знать не должна и тем более запустить в тереме индюк повторно. Я знаю ты не любишь классы или здесь использовал? - может там задвоилось что-то.
#5268

Я знаю ты не любишь классы или здесь использовал? - может там задвоилось что-то.


Ничего не использовал, все по старинке, никакого ООП.
Просто раз в свечу вызываю данные индикатора (код выше писал). Даже ничего с ними не делаю, просто вызов. Если вызов нескольких значений - сразу подгружается несколько раз )) Сколько пробовал сторонних индикаторов через iCustom - такое впервые. Грешу на dll, т.к. с ним раньше не присоединял их. Можешь сам попробовать, если время есть, индюк во вложении.
#5269

Господа, подскажите. Поставил совы на vps (windows server 2008 eng), одна сова не смогла рассчитать стоимость пункта (на домашнем работало без проблем)..... в другой почему то русские шрифты превратились в тыкву))), в третьей все нормально. Выбрал в настройках русский яз. везде где только можно, но все равно, в одной сове все нормально с буквами в настройках, в другой знаки вопроса и краказямбы......

функция определения цены пункта, ей передаем переменную _Symbol


double StoimPunkt(string B) //цена пункта для одного лота
{
RefreshRates();
double S=0;
if(MarketInfo(B,MODE_TICKVALUE)!=0 && MarketInfo(B,MODE_TICKSIZE)!=0 && MarketInfo(B,MODE_POINT)!=0)
{
S=MarketInfo(B,MODE_TICKVALUE)/(MarketInfo(B,MODE_TICKSIZE)/MarketInfo(B,MODE_POINT));
}
return(S);
}
#5270


функция определения цены пункта, ей передаем переменную _Symbol


double StoimPunkt(string B) //цена пункта для одного лота
{
RefreshRates();
double S=0;
if(MarketInfo(B,MODE_TICKVALUE)!=0 && MarketInfo(B,MODE_TICKSIZE)!=0 && MarketInfo(B,MODE_POINT)!=0)
{
S=MarketInfo(B,MODE_TICKVALUE)/(MarketInfo(B,MODE_TICKSIZE)/MarketInfo(B,MODE_POINT));
}
return(S);
}

Могут при первом запросе вернуть 0.
do { TickValue = MarketInfo(symb, MODE_TICKVALUE); } while(TickValue == 0);
Интересно, бывают ли случаи, чтобы оно и при повторных проверках тоже вернуло 0, и выполнение зациклилось?
#5271



функция определения цены пункта, ей передаем переменную _Symbol


double StoimPunkt(string B) //цена пункта для одного лота
{
RefreshRates();
double S=0;
if(MarketInfo(B,MODE_TICKVALUE)!=0 && MarketInfo(B,MODE_TICKSIZE)!=0 && MarketInfo(B,MODE_POINT)!=0)
{
S=MarketInfo(B,MODE_TICKVALUE)/(MarketInfo(B,MODE_TICKSIZE)/MarketInfo(B,MODE_POINT));
}
return(S);
}

Могут при первом запросе вернуть 0.
do { TickValue = MarketInfo(symb, MODE_TICKVALUE); } while(TickValue == 0);
Интересно, бывают ли случаи, чтобы оно и при повторных проверках тоже вернуло 0, и выполнение зациклилось?

Значит надо два раза спрашивать :)) Сервер глуховат. Спасибо.
#5272

Интересно, бывают ли случаи, чтобы оно и при повторных проверках тоже вернуло 0, и выполнение зациклилось?

Бывает на не подключенном тереме. Я бы в цикл Sleep и проверку IsStopped добавил.
#5273

У меня такой общий код был.
До ошибки никогда не доходило, вроде бы.

double GetTickValue() {
double _TickValue;
int a=0;
do {
_TickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
a++;
if (_TickValue == 0) Sleep(500);
} while (_TickValue == 0 && a if (_TickValue == 0) { Print("TickValue Error"); return(0); }
return _TickValue;
}
#5274

Добрый день!

Просмотрел второй урок и столкнулся со следующей проблемой. В случае определения МАКС и МИН перебирая 10 баров не происходит сброса. Т.е. если к примеру запустить данного советника в тестер то он запоминает последний хай и минимум и будет ставить ордера только в случае если будет превышение последнего определенного хая и мин..

Как написать так чтобы к примеру каждый новый день в 11 часов он сбрасывал вчерашний результат и определял новый пересчитывая указанное последнее кол-во баров.

вод код советника на писаного во втором уроке:

Спойлер


extern int BarCount = 10;
extern int HourStart = 11;
extern double Lots = 0.01;
extern int StopLoss = 300;
extern int TakeProfit = 200;
extern int Magic = 12345;

double minprice = 999999,
maxprice = -999999,
mp, SL, TP;

int ticket;


//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---

//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---

}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{


GetMaxPrice();
GetMinPrice();

if(TimeHour(TimeCurrent()) == HourStart)
{
if (BuyLimitCount() == 0 && BuyCount() == 0)
{
SL = NormalizeDouble(minprice - StopLoss*Point, 5);
TP = NormalizeDouble(minprice + TakeProfit*Point, 5);
ticket = OrderSend(Symbol(), OP_BUYLIMIT, Lots, minprice, 3, SL, TP, "", Magic, 0, Blue);

if(ticket Print("Не удалось открыть ордер");
}

if (SellLimitCount() == 0 && SellCount() == 0)
{
SL = NormalizeDouble(maxprice + StopLoss*Point, 5);
TP = NormalizeDouble(maxprice - TakeProfit*Point, 5);
ticket = OrderSend(Symbol(), OP_SELLLIMIT, Lots, maxprice, 3, SL, TP, "", Magic, 0, Red);

if(ticket Print("Не удалось открыть ордер");
}
}




Comment("Maxprice:" +DoubleToStr(maxprice, 5) + "\n"+
"Minprice:" +DoubleToStr(minprice, 5));

}

//+------------------------------------------------------------------+
int BuyLimitCount()
{
int count = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true &&
OrderMagicNumber() == Magic &&
OrderType() == OP_BUYLIMIT)
{
count++;
}
}
return(count);
}

//+------------------------------------------------------------------+
int SellLimitCount()
{
int count = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true &&
OrderMagicNumber() == Magic &&
OrderType() == OP_SELLLIMIT)
{
count++;
}
}
return(count);
}

//+------------------------------------------------------------------+
int BuyCount()
{
int count = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true &&
OrderMagicNumber() == Magic &&
OrderType() == OP_BUY)
{
count++;
}
}
return(count);
}

//+------------------------------------------------------------------+
int SellCount()
{
int count = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true &&
OrderMagicNumber() == Magic &&
OrderType() == OP_SELL)
{
count++;
}
}
return(count);
}

//+------------------------------------------------------------------+
void GetMinPrice()
{
for(int i=0; i {
mp = iLow(Symbol(), PERIOD_CURRENT, i);
if(mp minprice=mp;
}
return;
}

//+------------------------------------------------------------------+
void GetMaxPrice()
{
for(int i=0; i {
mp = iHigh(Symbol(), PERIOD_CURRENT, i);
if(mp > maxprice)
maxprice=mp;
}
return;
}

Изменено 4 ноября, 2018 пользователем 0ll

#5275
Спойлер


Добрый день!

Просмотрел второй урок и столкнулся со следующей проблемой. В случае определения МАКС и МИН перебирая 10 баров не происходит сброса. Т.е. если к примеру запустить данного советника в тестер то он запоминает последний хай и минимум и будет ставить ордера только в случае если будет превышение последнего определенного хая и мин..

Как написать так чтобы к примеру каждый новый день в 11 часов он сбрасывал вчерашний результат и определял новый пересчитывая указанное последнее кол-во баров.

вод код советника на писаного во втором уроке:

extern int BarCount = 10;
extern int HourStart = 11;
extern double Lots = 0.01;
extern int StopLoss = 300;
extern int TakeProfit = 200;
extern int Magic = 12345;

double minprice = 999999,
maxprice = -999999,
mp, SL, TP;

int ticket;


//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---

//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---

}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{


GetMaxPrice(); для чего вызывать здесь эту функцию?
GetMinPrice(); для чего вызывать здесь эту функцию?

if(TimeHour(TimeCurrent()) == HourStart)
{
if (BuyLimitCount() == 0 && BuyCount() == 0)
{
SL = NormalizeDouble(minprice - StopLoss*Point, 5);
TP = NormalizeDouble(minprice + TakeProfit*Point, 5);
ticket = OrderSend(Symbol(), OP_BUYLIMIT, Lots, minprice, 3, SL, TP, "", Magic, 0, Blue);

if(ticket Print("Не удалось открыть ордер");
}

if (SellLimitCount() == 0 && SellCount() == 0)
{
SL = NormalizeDouble(maxprice + StopLoss*Point, 5);
TP = NormalizeDouble(maxprice - TakeProfit*Point, 5);
ticket = OrderSend(Symbol(), OP_SELLLIMIT, Lots, maxprice, 3, SL, TP, "", Magic, 0, Red);

if(ticket Print("Не удалось открыть ордер");
}
}




Comment("Maxprice:" +DoubleToStr(maxprice, 5) + "\n"+
"Minprice:" +DoubleToStr(minprice, 5));

}

//+------------------------------------------------------------------+
int BuyLimitCount()
{
int count = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true &&
OrderMagicNumber() == Magic &&
OrderType() == OP_BUYLIMIT)
{
count++;
}
}
return(count);
}

//+------------------------------------------------------------------+
int SellLimitCount()
{
int count = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true &&
OrderMagicNumber() == Magic &&
OrderType() == OP_SELLLIMIT)
{
count++;
}
}
return(count);
}

//+------------------------------------------------------------------+
int BuyCount()
{
int count = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true &&
OrderMagicNumber() == Magic &&
OrderType() == OP_BUY)
{
count++;
}
}
return(count);
}

//+------------------------------------------------------------------+
int SellCount()
{
int count = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true &&
OrderMagicNumber() == Magic &&
OrderType() == OP_SELL)
{
count++;
}
}
return(count);
}

//+------------------------------------------------------------------+
void GetMinPrice()
{
for(int i=0; i {
mp = iLow(Symbol(), PERIOD_CURRENT, i);
if(mp minprice=mp;
}
return;
}

//+------------------------------------------------------------------+
void GetMaxPrice()
{
for(int i=0; i {
mp = iHigh(Symbol(), PERIOD_CURRENT, i);
if(mp > maxprice)
maxprice=mp;
}
return;
}


У вас функции GetMaxPrice() и GetMinPrice() типа void, а надо double, чтобы они возвращали значение цены. И когда хотите открыть ордер, вызовите эту функцию.
например:
double price_open = GetMinPrice();
SL = NormalizeDouble(minprice price_open- StopLoss*Point, 5);
TP = NormalizeDouble(minprice price_open + TakeProfit*Point, 5);
ticket = OrderSend(Symbol(), OP_BUYLIMIT, Lots, minprice price_open, 3, SL, TP, "", Magic, 0, Blue);

Comment("Maxprice:" +DoubleToStr(maxpriceGetMaxPrice(), 5) + "\n"+
"Minprice:" +DoubleToStr(minpriceGetMinPrice(), 5));
Вот пример функции GetMaxPrice()

double GetMaxPrice() // Функция для определения максимальной цены за n баров
{
double maxprice = -99999;

for (int i=BarCount-1; i>=0; i--)
{
double mp = iHigh(Symbol(), PERIOD_CURRENT, i);
if(mp > maxprice)
maxprice = mp;
MaxPrice = maxprice;
}
return(MaxPrice); //что вернет функция
}

Изменено 3 ноября, 2018 пользователем Sergey Forex

Для публикации сообщений создайте учётную запись или авторизуйтесь

Перейти к списку тем
Форум · 2.0.20260627.0025