Любой вопрос новичка, чтоб не захламлять форум. Профи, не проходите мимо. Без вас никуда - 6. - страница 342

 

Вот файл .cpp проекта, порассматривам его и сходив пару раз в гугл и яндекс, я не обнаружил чего-то вовсе мозголомного, в целом понятно. Вроде даже просто.

//+------------------------------------------------------------------+
//| Sample DLL for MQL4 |
//| Copyright 2001-2012, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
//---
#define MT4_EXPFUNC __declspec(dllexport) //это что?
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#pragma pack(push,1)
struct RateInfo // Структура, переменные
{
unsigned int ctm;
double open;
double low;
double high;
double close;
double vol;
};
#pragma pack(pop)
//---
struct MqlStr
{
int len;
char *string // Указатель на стринг, я плохо помню.
};
static int CompareMqlStr(const void *left,const void *right);
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)//функция 
{
//---
switch(ul_reason_for_call) // оператор что делать
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH: //что это всюду, не понял.
break;
}
//---
return(TRUE);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall GetIntValue(const int ipar) // __stdcall кладет аргументы в стек справа налево
{ // MT4_EXPFUNC говорит что функция будет видима из метатрайдера, я не совсем понял.
printf("GetIntValue takes %d\n",ipar);
return(ipar);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall GetDoubleValue(const double dpar)
{
printf("GetDoubleValue takes %.8lf\n",dpar);
return(dpar);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC char* __stdcall GetStringValue(char *spar)
{
printf("GetDoubleValue takes \"%s\"\n",spar);
return(spar);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall GetArrayItemValue(const double *arr,const int arraysize,const int nitem)
{
//---
if(arr==NULL)
{
printf("GetArrayItemValue: NULL array\n");
return(0.0);
}
if(arraysize<=0)
{
printf("GetArrayItemValue: wrong arraysize (%d)\n", arraysize);
return(0.0);
}
if(nitem<0 || nitem>=arraysize)
{
printf("GetArrayItemValue: wrong item number (%d)\n", nitem);
return(0.0);
}
//---
return(arr[nitem]);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC BOOL __stdcall SetArrayItemValue(double *arr,const int arraysize,const int nitem,const double value)
{
//---
if(arr==NULL)
{
printf("GetArrayItemValue: NULL array\n");
return(FALSE);
}
if(arraysize<=0)
{
printf("GetArrayItemValue: wrong arraysize (%d)\n", arraysize);
return(FALSE);
}
if(nitem<0 || nitem>=arraysize)
{
printf("GetArrayItemValue: wrong item number (%d)\n", nitem);
return(FALSE);
}
//---
arr[nitem]=value;
return(TRUE);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall GetRatesItemValue(const RateInfo* rates,const int rates_total,const int shift,const int nrate)
{
//---
if(rates==NULL)
{
printf("GetRatesItemValue: NULL array\n");
return(0.0);
}
//---
if(rates_total<0)
{
printf("GetRatesItemValue: wrong rates_total number (%d)\n", rates_total);
return(0.0);
}
//---
if(shift<0 || shift>=rates_total)
{
printf("GetRatesItemValue: wrong shift number (%d)\n", shift);
return(0.0);
}
//---
if(nrate<0 || nrate>5)
{
printf("GetRatesItemValue: wrong rate index (%d)\n", nrate);
return(0.0);
}
//---
int nitem=rates_total-1-shift;
switch(nrate)
{
case 0: return double(rates[nitem].ctm);
case 1: return rates[nitem].open;
case 2: return rates[nitem].low;
case 3: return rates[nitem].high;
case 4: return rates[nitem].close;
case 5: return rates[nitem].vol;
}
//---
return(0.0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall SortStringArray(MqlStr *arr,const int arraysize)
{
//---
if(arr==NULL)
{
printf("SortStringArray: NULL array\n");
return(-1);
}
if(arraysize<=0)
{
printf("SortStringArray: wrong arraysize (%d)\n", arraysize);
return(-1);
}
//---
qsort(arr,arraysize,sizeof(MqlStr),CompareMqlStr);
//---
return(arraysize);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall ProcessStringArray(MqlStr *arr,const int arraysize)
{
int len1,len2;
//---
if(arr==NULL)
{
printf("ProcessStringArray: NULL array\n");
return(-1);
}
if(arraysize<=0)
{
printf("ProcessStringArray: wrong arraysize (%d)\n", arraysize);
return(-1);
}
//---
for(int i=0; i<arraysize-1; i++)
{
if(arr[i].string==NULL) len1=0;
else len1=strlen(arr[i].string);
if(arr[i+1].string==NULL) len2=0;
else len2=strlen(arr[i+1].string);
//--- uninitialized string
if(arr[i+1].string==NULL) continue;
//--- destination string is uninitialized and cannot be allocated within dll
if(arr[i].string==NULL) continue;
//--- memory piece is less than needed and cannot be reallocated within dll
if(arr[i].len<len1+len2) continue;
//--- final processing
strcat(arr[i].string,arr[i+1].string);
}
//---
return(arraysize);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CompareMqlStr(const void *left,const void *right)
{
MqlStr *leftstr=(MqlStr *)left;
MqlStr *rightstr=(MqlStr *)right;
//---
if(leftstr->string==NULL) return(-1); //-> вот этот знак я не знаю
if(rightstr->string==NULL) return(1);
//---
return(strcmp(leftstr->string,rightstr->string));
}
//+------------------------------------------------------------------+

А как же это работает?? Я не совсем понял, как обращаться в эту ddl - из кода советника? Как? Во-первых, вроде так #include <GetIntValue> Нет как то не так..

2. При вызове dll ведь не обязательно держать включенную студию, так? как же она выполняется?

Покажите пожалуста наипростейший пример обращения к этой самой dll из кода mql.

 
Trader7777:

ничего не пойму тут..


надо чтобы размер лота увеличивался в геометрической прогрессии ( с множителем 2), если открывается второй однонаправленный ордер.



получится вот такой результат

тогда вот так

double OrderLotsSell(string sy="", int op=-1, int mn=-1) { 
 datetime o;
   int      i, k=OrdersTotal(); double r=-1;

  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==sy || sy=="") {
        if ( OrderType()==OP_SELL) {
          if (op<0 || OrderType()==OP_SELL) {
            if (mn<0 || OrderMagicNumber()==Magic) {
              r=OrderLots()*2;
            }
          }
        }
      }
    }
  }
  return(r);
}

double OrderLotsBuy(string sy="", int op=-1, int mn=-1) { 
 datetime o;
   int      i, k=OrdersTotal(); double r=-1;

  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==sy || sy=="") {
        if ( OrderType()==OP_BUY) {
          if (op<0 || OrderType()==OP_BUY) {
            if (mn<0 || OrderMagicNumber()==Magic) {
              r=OrderLots()*2;
            }
          }
        }
      }
    }
  }
  return(r);
}





 
max020780:


получится вот такой результат

тогда вот так


спасибо, ход мыслей понял.. разобрался вернее.

для чего эта строчка?


datetime o;
 

Еще вот такой вопрос. у меня есть трейлинг. Когда открыт 1 однонаправленный ордер, все работает замечательно, если больше, то он почему-то не работает. Почему?

void Trailing ()
{
for(int i = 0; i<OrdersTotal(); i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
{
if (OrderType() == OP_BUY)
{
if(Bid - OrderOpenPrice() > TrailingStop*Point)
{
if (OrderStopLoss() < Bid - (TrailingStop + TrailingStep)*Point)
{
SL = NormalizeDouble(Bid - TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify(OrderTicket(),OrderOpenPrice(),SL,0,0);
}
}
}
if (OrderType() == OP_SELL)
{
if(OrderOpenPrice() - Ask > TrailingStop*Point)
{
if (OrderStopLoss() > Ask + (TrailingStop+ TrailingStep)*Point)
{
SL = NormalizeDouble (Ask+TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify (OrderTicket(), OrderOpenPrice(), SL,0,0);
}
}
}
}
}
}
}


 
Vladimirovits:

Вот файл .cpp проекта, порассматривам его и сходив пару раз в гугл и яндекс, я не обнаружил чего-то вовсе мозголомного, в целом понятно. Вроде даже просто.

А как же это работает?? Я не совсем понял, как обращаться в эту ddl - из кода советника? Как? Во-первых, вроде так #include <GetIntValue> Нет как то не так..

Примерно вот таким образом. Чтоб заработало, надо ДЛЛ откомпилировать и положить в папку experts/libraries (читайте справку и учебник, там все подробно расписано).

//сначала надо объявить импорт функции из DLL
#import "имя_вашей_длл.dll"
int SortStringArray(string *arr[],const int arraysize);
#import


//в тексте программы вызов проще простого

string arr[];
int size;
...
//где-то в коде массив заполняется
...
//а вот и вызов сортировки
SortStringArray(arr,size);

2. При вызове dll ведь не обязательно держать включенную студию, так? как же она выполняется?

Dll - это, упрощенно говоря, обычная программа Windows, за тем исключением, что функции, реализованные в ней вызываются не пользователем, а другой программой. Для того, чтобы это было возможно, мы и указываем компилятору языка C++ модификатор __declspec(dllexport).
 
Trader7777:

Еще вот такой вопрос. у меня есть трейлинг. Когда открыт 1 однонаправленный ордер, все работает замечательно, если больше, то он почему-то не работает. Почему?

void Trailing ()
{
for(int i = 0; i<OrdersTotal(); i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
{
if (OrderType() == OP_BUY)
{
if(Bid - OrderOpenPrice() > TrailingStop*Point)
{
if (OrderStopLoss() < Bid - (TrailingStop + TrailingStep)*Point)
{
SL = NormalizeDouble(Bid - TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify(OrderTicket(),OrderOpenPrice(),SL,0,0);
}
}
}
if (OrderType() == OP_SELL)
{
if(OrderOpenPrice() - Ask > TrailingStop*Point)
{
if (OrderStopLoss() > Ask + (TrailingStop+ TrailingStep)*Point)
{
SL = NormalizeDouble (Ask+TrailingStop*Point,Digits);
if (OrderStopLoss() !=SL)
OrderModify (OrderTicket(), OrderOpenPrice(), SL,0,0);
}
}
}
}
}
}
}


потому что в функцию необходимо передать параметры пробуйте так

bool IfProfTrail=false; // Использовать только дял профитных позиций - режим безубытка
int TrailingStop=0; // Дистанция трейлинга = 0 - минимально допустимый
int TrailingStep=1; // Шаг дистанции


void Trailing(string sy="",int op=-1,int mn=-1)
  {
   double po,pp;
   int    i,k=OrdersTotal();
   

   if(sy=="0") sy=Symbol();
   if(TrailingStop==0)TrailingStop=MarketInfo(Symbol(),MODE_STOPLEVEL);
   for(i=0;i<k;i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if((OrderSymbol()==sy || sy=="") && (op<0 || OrderType()==op))
           {
            po=MarketInfo(OrderSymbol(),MODE_POINT);
            if(mn<0 || OrderMagicNumber()==mn)
              {
               if(OrderType()==OP_BUY)
                 {
                  pp=MarketInfo(OrderSymbol(),MODE_BID);
                  if((!IfProfTrail && OrderProfit()>0) || pp-OrderOpenPrice()>TrailingStop*po)
                    {
                     if(OrderStopLoss()<pp-(TrailingStop+TrailingStep-1)*po)
                       {
                        ModifyOrder(-1,pp-TrailingStop*po,-1);
                       }
                    }
                 }
               if(OrderType()==OP_SELL)
                 {
                  pp=MarketInfo(OrderSymbol(),MODE_ASK);
                  if((!IfProfTrail && OrderProfit()>0) || OrderOpenPrice()-pp>TrailingStop*po)
                    {
                     if(OrderStopLoss()>pp+(TrailingStop+TrailingStep-1)*po || OrderStopLoss()==0)
                       {
                        ModifyOrder(-1,pp+TrailingStop*po,-1);
                       }
                    }
                 }
              }
           }
        }
     }
  }


 
Forexman77:

Спасибо огромное!

Теперь стало понятно в чем проблемма.

Для покупки использовал:

На сколько знаю покупка идет по ask, а iClose(Symbol(),Period(),0) берет цены из bid. Вследствии чего наверное и происходит ошибка.

Теперь использую следующюю комбинацию:

Но, тут же возникает вопрос так как, советник не пипсовый, цена находилась в зоне покупки долгое время и обновлялась при каждом тике.

Почему не открывается сделка? Получается советник зависает на ошибке и не видит дальнейшее изменение цены?

Заготовку для советника взял отсюда https://c.mql5.com/mql4/book/mq4/experts/tradingexpert.mq4

На Ваш взгляд стоит в данном советнике добавить в функию обработки ошибок, проверку на 129 и 138 ошибку?

Если да, то как примерно это сделать?

Как минимум у вас должна быть своя функция для открытия позиций/установки ордеров, обрабатывающая все ошибки. Именно в ней нужно получать последние цены.

Не смотрел никаких заготовок. Но скажу: в советнике нужно обрабатывать все ошибки, возвращаемые сервером. И этого ещё мало. Он должен уметь без потерь функциональности и без сбоя своего алгоритма подхватывать свои позиции после любой непредвиденной ситуации, и продолжить свою работу так, как будто ничего экстраординарного не произошло.

 
откомпилировать и положить в папку experts/libraries Вот, спасибо!!! Щас попробую. А я раньше встречал, а вот теперь ненахожу ничего такого подробного и удобоваримого, по теме.
 
artmedia70:

Как минимум у вас должна быть своя функция для открытия позиций/установки ордеров, обрабатывающая все ошибки. Именно в ней нужно получать последние цены.

Не смотрел никаких заготовок. Но скажу: в советнике нужно обрабатывать все ошибки, возвращаемые сервером. И этого ещё мало. Он должен уметь без потерь функциональности и без сбоя своего алгоритма подхватывать свои позиции после любой непредвиденной ситуации, и продолжить свою работу так, как будто ничего экстраординарного не произошло.


Шаблон взял из учебника. Не особо сейчас силен в функциях по обработке ошибок.

На открытии ордеров там есть RefreshRates(); (биды и аски заменил через маркет инфо, как сказали)

 while(true)                                  // Цикл закрытия орд.
     {
      if (Total==0 && Opn_B==true)              // Открытых орд. нет +
        {                                       // критерий откр. Buy
         RefreshRates();                        // Обновление данных
         SL=Bid - New_Stop(StopLoss)*Point;     // Вычисление SL откр.
         TP=Bid + New_Stop(TakeProfit)*Point;   // Вычисление TP откр.
         Alert("Попытка открыть Buy. Ожидание ответа..");
         Ticket=OrderSend(Symb,OP_BUY,Lts,Ask,2,SL,TP);//Открытие Buy
         if (Ticket > 0)                        // Получилось :)
           {
            Alert ("Открыт ордер Buy ",Ticket);
            return;                             // Выход из start()
           }
         if (Fun_Error(GetLastError())==1)      // Обработка ошибок
            continue;                           // Повторная попытка
         return;                                // Выход из start()
        }

И функция обработки ошибок:

int Fun_Error(int Error)                        // Ф-ия обработ ошибок
  {
   switch(Error)
     {                                          // Преодолимые ошибки            
      case  4: Alert("Торговый сервер занят. Пробуем ещё раз..");
         Sleep(3000);                           // Простое решение
         return(1);                             // Выход из функции
      case 135:Alert("Цена изменилась. Пробуем ещё раз..");
         RefreshRates();                        // Обновим данные
         return(1);                             // Выход из функции
      case 136:Alert("Нет цен. Ждём новый тик..");
         while(RefreshRates()==false)           // До нового тика
            Sleep(1);                           // Задержка в цикле
         return(1);                             // Выход из функции
      case 137:Alert("Брокер занят. Пробуем ещё раз..");
         Sleep(3000);                           // Простое решение
         return(1);                             // Выход из функции
      case 146:Alert("Подсистема торговли занята. Пробуем ещё..");
         Sleep(500);                            // Простое решение
         return(1);                             // Выход из функции
         // Критические ошибки
      case  2: Alert("Общая ошибка.");
         return(0);                             // Выход из функции
      case  5: Alert("Старая версия терминала.");
         Work=false;                            // Больше не работать
         return(0);                             // Выход из функции
      case 64: Alert("Счет заблокирован.");
         Work=false;                            // Больше не работать
         return(0);                             // Выход из функции
      case 133:Alert("Торговля запрещена.");
         return(0);                             // Выход из функции
      case 134:Alert("Недостаточно денег для совершения операции.");
         return(0);                             // Выход из функции
      default: Alert("Возникла ошибка ",Error); // Другие варианты   
         return(0);                             // Выход из функции
     }
  }

Хотел спросить. Можно в нее следующую строку внести от 129 ошибки к примеру так?

      case 129:Alert("Неправильные цены. Пробуем ещё раз..");
         RefreshRates();                        // Обновим данные
         return(1); 
 
У меня в папке experts лежит весь проэкт визуал студии... Откомпилировать- это же файл .exe, точно? Хотел вот скопировать его в папку либрариес... Не найду прикиньте!! Вот папка дебаг проэкта. Я уж извняюсь, тема новая.
Причина обращения: