Примеры: Передача торговых сигналов в универсальном советнике.

 

New article Передача торговых сигналов в универсальном советнике. has been published:

В статье описываются различные способы передачи торговых сигналов из сигнального модуля универсального советника в модуль управления позициями и ордерами. Рассматриваются последовательный и параллельный интерфейсы.

Author: Igor Kim

 

Игорь, спасибо за тему, очень интересно!
У меня к вам такой практический вопрос по свинговой торговле с доливками.
Как будет выглядеть такой вариант функции int NumberOfBarLastPos(string sym="", int tf=0, int op=-1, int mn=-1) в случае если необходимо произвести 3 доливки с различных уровней и при обязательном сигнале. Для полной ясности, пример: Канальная тактика, открыта позиция OrderType() = OP_BUY, профит которой в минусе, текущая цена вышла на первый заданный уровень NormalizeDouble(Ask + FirstLevel*Point, Digits ) <= OrderOpenPrice() и поступил вновь сигнал SIGNAL_BUY, производим доливку. Затем производим доливку со второго уровня SecondLevel и опять при сигнале SIGNAL_BUY и доливка с третьего уровня ThirdLevel и соответственно при наличии сигнала. Все остальное согласно тактики - при поступлении сигнала на продажу SIGNAL_SELL, закрываем все позиции OrderType() = OP_BUY и открываем OrderType() = OP_SELL. При аналогичных условиях осуществляем доливку по продаже.
С уважением, Вячеслав.

P.S. Вычисление всех уровней производится от OrderOpenPrice() первой основной позиции.



 
Вячеслав, функция int NumberOfBarLastPos() возвращает количество баров, прошедшее с момента открытия последней позиции. И основное её назначение - это ограничение количества открытий на некотором количестве баров. Например, один бар - одна позиция или три бара - одна позиция. У Вас, насколько я понял, нет такого ограничения и оно Вам не нужно. Вам удобнее будет применить функцию int NumberOfPositions(string sym="", int op=-1, int mn=-1), которая возвращает количество позиций. Код будет выглядеть примерно так:
if (SIGNAL_BUY) {
  ClosePositions("", OP_SELL);
  if (NumberOfPositions("", OP_BUY)<1) // первая покупка
 
  if (NumberOfPositions("", OP_BUY)==1) {
    SecondLevel= // находим его значение
    if (SecondLevel>Ask) // вторая покупка
  }
  
  if (NumberOfPositions("", OP_BUY)==2) {
    ThirdLevel= // находим его значение
    if (ThirdLevel>Ask) // третья покупка
  }
}
 
if (SIGNAL_SELL) {
  ClosePositions("", OP_BUY);
  if (NumberOfPositions("", OP_SELL)<1) // первая продажа
 
  if (NumberOfPositions("", OP_SELL)==1) {
    SecondLevel= // находим его значение
    if (SecondLevel>0 && SecondLevel<Bid) // вторая продажа
  }
  
  if (NumberOfPositions("", OP_SELL)==2) {
    ThirdLevel= // находим его значение
    if (ThirdLevel>0 && ThirdLevel<Bid) // третья продажа
  }
}
 
//+----------------------------------------------------------------------------+
//|  Закрытие позиций по рыночной цене                                         |
//|  Параметры:                                                                |
//|    sym - наименование инструмента  ("" - текущий символ)                   |
//|    op  - операция                  (-1 - любая позиция)                    |
//|    mn  - MagicNumber               (-1 - любой магик)                      |
//+----------------------------------------------------------------------------+
void ClosePositions(string sym="", int op=-1, int mn=-1) {
  bool   fc;
  double pp;
  int    err, i, it, k=OrdersTotal();
 
  if (sym=="") sym=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==sym && (op<0 || OrderType()==op)) {
        if (mn<0 || OrderMagicNumber()==mn) {
          fc=False;
          for (it=1; it<=NumberOfTry; it++) {
            while (!IsTradeAllowed()) Sleep(5000);
            RefreshRates();
            if (OrderType()==OP_BUY) {
              pp=NormalizeDouble(Bid, Digits);
              fc=OrderClose(OrderTicket(), OrderLots(), pp, Slippage, clCloseBuy);
              if (fc) {
                if (UseSound) PlaySound(NameFileSound); break;
              } else {
                err=GetLastError();
                Print("Error(",err,") closing buy: ",ErrorDescription(err),", try ",it);
                Sleep(1000*PauseAfterError);
              }
            }
            if (OrderType()==OP_SELL) {
              pp=NormalizeDouble(Ask, Digits);
              fc=OrderClose(OrderTicket(), OrderLots(), pp, Slippage, clCloseSell);
              if (fc) {
                if (UseSound) PlaySound(NameFileSound); break;
              } else {
                err=GetLastError();
                Print("Error(",err,") closing buy: ",ErrorDescription(err),", try ",it);
                Sleep(1000*PauseAfterError);
              }
            }
          }
        }
      }
    }
  }
}
 
//+----------------------------------------------------------------------------+
//|  Возвращает количество позиций.                                            |
//|  Параметры:                                                                |
//|    sym - наименование инструмента ("" - текущий символ)                    |
//|    op  - операция                 (-1 - любая позиция)                     |
//|    mn  - MagicNumber              (-1 - любой магик)                       |
//+----------------------------------------------------------------------------+
int NumberOfPositions(string sym="", int op=-1, int mn=-1) {
  int i, k=OrdersTotal(), kp=0;
 
  if (sym=="") sym=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==sym) {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          if (op<0 || OrderType()==op) {
            if (mn<0 || OrderMagicNumber()==mn) kp++;
          }
        }
      }
    }
  }
  return(kp);
}
//+----------------------------------------------------------------------------+
 

Игорь, спасибо !

 
Один из моих знакомых обратил моё внимание на неправильное использование функции NumberOfBarLastPos() в функции ManagePositions() в советнике e-SampleSwingAdd. Я не учёл того, что при отсутствии позиций в истории функция NumberOfBarLastPos() возвращает -1. Поэтому вместо условия:

NumberOfBarLastPos()>0 следует использовать:
NumberOfBarLastPos()<0 || NumberOfBarLastPos()>NumberOfBars, где NumberOfBars - это количество баров, на котором разрешается только один вход.
 
Игорь, спасибо за большую работу, которую Вы делаете. Ваш код чёткий и хорошо оформлен, что позволяет легко его понять. Но рекомендую учесть следующее:
в функции void ClosePositions(string sym="", int op=-1, int mn=-1)
цикл следует делать с вычитание for (i=k-1; i>=0; i--) иначе не все ордера закрываются. Это объясняется в статьях Rosh'а и я столкнулся с этим на практике.
 
С чего начать писать void ManagePositions() по сведующим условиям

Есть массивы
for (tf = 0; tf < 5; tf++) 
{
...... 
int TF[tf] - time frame {5,15,30,60,240}
int signal[tf] - „1“ – buy
  - „2“ – close buy
  - „-1“ – sell
  - „-2“ – close sell
int mn_b[tf] - magic_number_buy разный для всех time frame
int mn_s[tf] - magic_number_sell разный для всех time frame
}

Надо
Open
на time frame 5,15 открывается в одну сторону до трех ордеров
- 1 ордер ММ = 1 Моней
- 2 ордер ММ = 2
- 3 ордер ММ = 3
на time frame 30 открывается в одну сторону до двух ордеров
- 1 ордер ММ = 2
- 2 ордер ММ = 3

на time frame 60 открывается в одну сторону один ордер
- 1 ордер ММ = 3

на time frame 240 неоткрывается

Доливка второго и третего ордеров по отдельным условиям

Всего получается не больше 9 ордеров в одну сторону  

Close
При появлении сигнала с time frame close sell закрывает все ордера sell на данном ТФ 
При появлении сигнала с time frame close buy закрывает все ордера buy на данном ТФ 


Помогите пожалуйста
Причина обращения: