Грааль от СК

 

Из статьи "мой первый грааль" хотел сделать демо-игрушку, но он сделан под лимитники и весь график обсеивается ими и перегружается траффик. а хочется аккуратно, чисто и красиво. то есть хочу перевести на маркет ордеры и убрать клоуз, чтобы ордера закрывались по тп и сл. компилируется без ошибок, торговать торгует, но мт4 постоянно выдает ошибки 138. не могу понять в чем дело, ведь все правильно сделал!

extern int TakeProfit=6; // TakeProfit ордера
extern int StopLoss= 10; // StopLoss ордера
extern int Distan = 4; // Дистанция от средней МА
extern int period_MA= 2; // Период средней МА
extern int Time_1 = 19; // Время начала работы
extern int Time_2 = 5; // Время окончания работы
extern int Risk = 20; // Процент от свободных средств

//--------------------------------------------------------------------------------------------
int
total, // Количество лотов
b = 0, // 1 = факт налиия ордера Buy
s = 0; // 1 = факт налиия ордера Sell
//--------------------------------------------------------------------------------------------
double
OP, // OpenPrice (абсолютн. пунктов)
SL, // StopLoss ордера (относит.пункт.)
TP, // TakeProfit ордера (относит.пункт.)
dist, // Дистанция от средней МА(отн.пун.)
OP_b, // OpenPrice Buy (абс. пунктов)
OP_s, // OpenPrice Sell(абс. пунктов)
MA, // Значение МА (курс)
spred, // Спред (абс. пунктов)
Lot; // Количество лотов
//--------------------------------------------------------------------------------------------
int init()
{
SL=StopLoss*Point; // StopLoss ордера (относит.пункт.)
TP=TakeProfit*Point; // TakeProfit ордера (относит.пункт.)
dist=Distan*Point; // Дистанция от средней МА(отн.пун.)
spred=Ask-Bid; // Спред (абс. пунктов)
return;
}
//--------------------------------------------------------------------------------------------
int start()
{
//--------------------------------------------------------------------------------------------
total=OrdersTotal(); // Количество лотов
b=0; // Обнулимся в начале прохода
s=0; // Обнулимся в начале прохода
//--------------------------------------------------------------------------------------------
for (int i=total; i>=0; i--) // По всем ордерам
{
if (OrderSelect(i,SELECT_BY_POS)==true && // Выделим ордер
OrderSymbol()==Symbol())
{

//--------------------------------------------------------------------------------------------
if (OrderType()==OP_BUY) // Ордер Buy
{
b =1; // Есть такой ордер
}
//--------------------------------------------------------------------------------------------
if (OrderType()==OP_SELL) // Ордер Sell
{
s =1; // Есть такой ордер
}
//--------------------------------------------------------------------------------------------
}
}
//--------------------------------------------------------------------------------------------
MA = iMA(NULL,0, period_MA, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Текущее значение МА
Open_order() ; // Активизируем открытие
return;
}
//--------------------------------------------------------------------------------------------
void Open_order() // Открывающая функция
{
int Tek_Time=TimeHour(CurTime()); // Для тестирования по времени
if (Tek_Time>Time_2 && Tek_Time<Time_1) return; // Для тестирования по времени
//--------------------------------------------------------------------------------------------
if (b==0) // Нет никаких баёв, открываем b
{
OP=MA-dist; // Курс открытия ордера b
OP=NormalizeDouble(OP,Digits); // Нормализация (МА даёт 5й знак)
OrderSend(Symbol(),OP_BUY, Lots(),OP,3,OP-SL,OP+TP,"",0,0,Blue);// Открываемся
b=1; // Теперь есть бай
}
//--------------------------------------------------------------------------------------------
if (s==0) // Нет никаких селов, открываем s
{
OP=MA+spred+dist; // Курс открытия ордера s
OP=NormalizeDouble(OP,Digits); // Нормализация (МА даёт 5й знак)
OrderSend(Symbol(),OP_SELL,Lots(),OP,3,OP+SL,OP-TP,"",0,0,Red);// Открываемся
s=1; // Теперь есть s
}
//--------------------------------------------------------------------------------------------
return;
}
//--------------------------------------------------------------------------------------------
double Lots() // Вычисление лотов
{
//--------------------------------------------------------------------------------------------
Lot=NormalizeDouble(AccountEquity()*Risk/100/1000,1);// Вычисляем колич. лотов
double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // Минимально допустимая стоим. лотов
if (Lot == 0 ) Lot = Min_Lot; // Для теста на постоян. миним. лотах
//--------------------------------------------------------------------------------------------
return(Lot);
}
//--------------------------------------------------------------------------------------------

и еще, стал на одном баре совершать по нескольку раз покупать или продавать, это тоже неправильно. ведь по условиям надо, чтобы когда цена отклонилась от МА на заданное кол-во пунктов совершить лишь одну операцию.

 
delyus:

Из статьи "мой первый грааль" хотел сделать демо-игрушку ...


А смысл ...
 

Совет автору, не примите как критику просто сами потом спасибо скажете :-), если Вы будете писать по так называемой "Венгерской Нотации", т.е. с мнемонически понятными именами переменных (типа TakeProfit и не перемешивать в наименовании английские и русские понятия типа Tek_Time) и симметричными отступами кода по логическим блокам,

void ErrorCheckOut(bool LastErr)
  {
    int Error;
    if(LastErr != TRUE) 
      { 
        Error = GetLastError(); 
        if(Error != 0)
            Print("LastError = ",Error," : ",ErrorDescription(Error)); 
      }
  }
то код будет на много более читабельным. А уж если будуте комментировать каждый логический блок, то через пол года свой код не придется заново изучать :-)
 
пока ничего вразумительного по существу не услышал от вас, дорогие форумчане)) поправил то, что совершает несколько сделок на одном баре. но то почему выдает ордер сенд эррор 138 пока никак не могу найти. причем, сначала в журнале пишет ошибку 130, через некоторое время она переименовывается на 138! дело осложняется тем, что при компиляции ошибок не выдает и не указывает, где собака порылась
 
нн-дааа, закидали просто ответами
 
delyus:
пока ничего вразумительного по существу не услышал от вас, дорогие форумчане)) поправил то, что совершает несколько сделок на одном баре. но то почему выдает ордер сенд эррор 138 пока никак не могу найти. причем, сначала в журнале пишет ошибку 130, через некоторое время она переименовывается на 138! дело осложняется тем, что при компиляции ошибок не выдает и не указывает, где собака порылась


Вы пытаетесь открыться на локальном экстремуме ценового движения, цена в этом положении весьма неустойчива. Чего же Вы хотите? Гарантированного открытия по выгодной для Вас цене? Попробуйте внедрить RefreshRates(), но вряд ли это поможет...

А Вы статью про грааль целиком прочитали? Может стоит еще раз перечитать? Там есть ответы на Ваши вопросы....

З.Ы. А компиляция ошибок не выдает, потому как ошибка может быть не обязательно в коде, но и в логике, тут компилятор бессилен.

 
delyus:
нн-дааа, закидали просто ответами

К сожалению не могу помочь...а так бы с удовольствием.
 

фигаро,

дело именно в коде, логика проста, если цена отклоняется от некой скользящей средней на заданное кол-во пунктов, совершается контрсделка. ничего криминального здесь нет. где можно узнать что значит ошибка 130 и 138 всего-навсего и поправить код

 
ERR_INVALID_STOPS 130 Слишком близкие стопы или неправильно рассчитанные или ненормализованные цены в стопах (или в цене открытия отложенного ордера). Попытку можно повторять только в том случае, если ошибка произошла из-за устаревания цены. Необходимо после задержки от 5 секунд обновить данные при помощи функции RefreshRates и повторить попытку. Если ошибка не исчезает, необходимо прекратить все попытки торговых операций и изменить логику программы.
ERR_REQUOTE 138 Запрошенная цена устарела, либо перепутаны bid и ask. Можно без задержки обновить данные при помощи функции RefreshRates и повторить попытку. Если ошибка не исчезает, необходимо прекратить все попытки торговых операций и изменить логику программы.

Как опытный пипсер Вы должны бы уже знать эти ошибки как "Отче Наш")))

 

фигаро,

спасибо. только почему в другом точно таком же советнике только с другой манерой написания кода все нормально, а именно в этом такие ошибки, этот советник я переделал сам из лимит ордеров на маркет ордера и убрал ордерклоуз, чтобы ордера закрывались не по клоуз а по ТП и СЛ. значит я неправильно переделал, а не потому что близко к цене, бывало и ближе без ошибок. вот как было

extern int TakeProfit=5; // TakeProfit ордера
extern int StopLoss= 29; // StopLoss ордера
extern int Distan = 2; // Дистанция от средней МА
extern int Cls = 2; // Закрыть при ** пнктов прибыли
extern int period_MA=16; // Период средней МА
extern int Time_1 = 21; // Время начала работы
extern int Time_2 = 7; // Время окончания работы
extern int Prots = 0; // Процент от свободных средств

//--------------------------------------------------------------------------------------------
int
Nom_bl, // Номер ордера BuyLimit
Nom_sl, // Номер ордера SellLimit
total, // Количество лотов
bl = 0, // 1 = факт налиия ордера BuyLimit
sl = 0, // 1 = факт налиия ордера SellLimit
b = 0, // 1 = факт налиия ордера Buy
s = 0; // 1 = факт налиия ордера Sell
//--------------------------------------------------------------------------------------------
double
OP, // OpenPrice (абсолютн. пунктов)
SL, // StopLoss ордера (относит.пункт.)
TP, // TakeProfit ордера (относит.пункт.)
dist, // Дистанция от средней МА(отн.пун.)
Level, // Миним. допуст дистанция отл.орд
OP_bl, // OpenPrice BuyLimit (абс. пунктов)
OP_sl, // OpenPrice SellLimit(абс. пунктов)
cls, // Закрыть при ** прибыли (абс. пун.)
MA, // Значение МА (курс)
spred, // Спред (абс. пунктов)
Lot; // Количество лотов
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int init()
{
Level=MarketInfo(Symbol(),MODE_STOPLEVEL); // Выясним что нам даёт сервер
Level=(Level+1)*Point; // ?:)
SL=StopLoss*Point; // StopLoss ордера (относит.пункт.)
TP=TakeProfit*Point; // TakeProfit ордера (относит.пункт.)
dist=Distan*Point; // Дистанция от средней МА(отн.пун.)
cls=Cls*Point; // Закрыть при ** прибыли (абс. пун.)
spred=Ask-Bid; // Спред (абс. пунктов)
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
int start()
{
//============================================================================================
total=OrdersTotal(); // Количество лотов
bl=0; // Обнулимся в начале прохода
sl=0; // Обнулимся в начале прохода
b=0; // Обнулимся в начале прохода
s=0; // Обнулимся в начале прохода
//--------------------------------------------------------------------------------------------
for (int i=total; i>=0; i--) // По всем ордерам
{
if (OrderSelect(i,SELECT_BY_POS)==true && // Выделим ордер
OrderSymbol()==Symbol())
{

//--------------------------------------------------------------------------------------------
if (OrderType()==OP_BUY) // Ордер Buy
{
b =1; // Есть такой ордер
Close_B(OrderTicket(),OrderLots()); // Закрыть ордер (надо ли решит ф-ия)
}
//--------------------------------------------------------------------------------------------
if (OrderType()==OP_SELL) // Ордер Sell
{
s =1; // Есть такой ордер
Close_S(OrderTicket(),OrderLots()); // Закрыть ордер (если надо)
}
//--------------------------------------------------------------------------------------------
if (OrderType()==OP_BUYLIMIT) // Ордер BuyLimit
{
OP_bl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice BuyLimit(абс. пунктов)
Nom_bl=OrderTicket();
bl=1; // Есть такой ордер
}
//--------------------------------------------------------------------------------------------
if (OrderType()==OP_SELLLIMIT) // ОрдерSellLimit
{
OP_sl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice SellLimit(абс.пунктов)
Nom_sl=OrderTicket();
sl=1; // Есть такой ордер
}
//--------------------------------------------------------------------------------------------
}
}
//--------------------------------------------------------------------------------------------
MA = iMA(NULL,0, period_MA, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Текущее значение МА
Modify_order(); // Активизируем модификацию
Open_order() ; // Активизируем открытие
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Close_B(int Nomber, double lots) // Закрытие ордеров Buy
{
//============================================================================================
if (NormalizeDouble(Bid-OrderOpenPrice(),Digits)>=cls)// Если достигнут заданный профит
{
OrderClose( Nomber, lots, Bid, 1, Yellow); // Закрываемся
b = 0; // И больше нет бая
}
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Close_S(int Nomber, double lots) // Закрытие ордеров Sell
{
//============================================================================================
if (NormalizeDouble(OrderOpenPrice()-Ask,Digits)>=cls)// Если достигнут заданный профит
{
OrderClose( Nomber, lots, Ask, 1, Yellow); // Закрываемся
s = 0; // И больше нет селла
}
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Modify_order() // Модификация ордеров
{
//============================================================================================
if (bl==1) // Если есть БайЛимит
{
OP=MA-dist; // Он должен стоять здесь
if (MathAbs(OP_bl-OP)>0.5*Point) // А если он здесь не стоит
{
OrderModify(Nom_bl,OP,OP-SL,OP+TP,0,DeepSkyBlue);// Модификация ордера
}
}
//--------------------------------------------------------------------------------------------
if (sl==1) // Если есть СеллЛимит
{
OP=MA+spred+dist; // Он должен стоять здесь
if (MathAbs(OP_sl-OP)>0.5*Point) // А если он здесь не стоит
{
OrderModify( Nom_sl, OP, OP+SL, OP-TP, 0, Pink);// Модификация ордера
}
}
//============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
void Open_order() // Открывающая функция
{
// int Tek_Time=TimeHour(CurTime()); // Для тестирования по времени
// if (Tek_Time>Time_2 && Tek_Time<Time_1) return; // Для тестирования по времени
//============================================================================================
if (b==0 && bl==0) // Нет никаких баёв, открываем bl
{
OP=MA-dist; // Курс открытия ордера bl
if(OP>Ask-Level) OP=Ask-Level; // Уточнение ОР в соотв. с допуском
OP=NormalizeDouble(OP,Digits); // Нормализация (МА даёт 5й знак)
OrderSend(Symbol(),OP_BUYLIMIT, Lots(),OP,3,OP-SL,OP+TP,"",0,0,Blue);// Открываемся
bl=1; // Теперь есть бай
}
//--------------------------------------------------------------------------------------------
if (s==0 && sl==0) // Нет никаких селов, открываем sl
{
OP=MA+spred+dist; // Курс открытия ордера sl
if(OP<Bid+Level) OP=Bid+Level; // Уточнение ОР в соотв. с допуском
OP=NormalizeDouble(OP,Digits); // Нормализация (МА даёт 5й знак)
OrderSend(Symbol(),OP_SELLLIMIT,Lots(),OP,3,OP+SL,OP-TP,"",0,0,Red);// Открываемся
sl=1; // Теперь есть sl
}
///============================================================================================
return;
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
double Lots() // Вычисление лотов
{
//============================================================================================
Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Вычисляем колич. лотов
double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // Минимально допустимая стоим. лотов
if (Lot == 0 ) Lot = Min_Lot; // Для теста на постоян. миним. лотах
//============================================================================================
return(Lot);
}
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

 
delyus:

фигаро,

спасибо. только почему в другом точно таком же советнике только с другой манерой написания кода все нормально, а именно в этом такие ошибки, этот советник я переделал сам из лимит ордеров на маркет ордера и убрал ордерклоуз, чтобы ордера закрывались не по клоуз а по ТП и СЛ. значит я неправильно переделал, а не потому что близко к цене, бывало и ближе без ошибок. вот как было

MarketInfo(Symbol(),MODE_STOPLEVEL)

Это выдает нам минимальный уровень для установки отложников, стопов в пунктах от текущей цены, хуже того этот уровень весьма не постоянен)

Далее, перед каждой установкой ордера неплохо провереть получаемые уровни стопов на их соответствие этому уровню, причем лучше сверять хотя бы с:

MarketInfo(Symbol(),MODE_STOPLEVEL) + 1

Ну это в кратце... А вообще процедура открытия ордера не так проста, по уму это делается так:

Файлы:
Причина обращения: