Скачать MetaTrader 5
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Миллионы трейдеров качают коды из библиотеки MQL5. Поделись своей программой!
hoz
1936
hoz 2014.08.16 17:39 

 Тестирую некоторые классы. Взял инюк RSI и на нём накатал сов сугубо для обкатки класссов. Обнаружил, что в класс передаются значение рыночных данных одни, а на выходе выходят другие, а точнее сплошные еденицы. Почему так? Я распринтовал всё, что б было видно, что куда идёт в коде ниже. Выложу места, которые учавствуют в данным ситуациях.

Вот так в эксперте посылаю ордер:

//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                                           GetTPiSL()                                                                  |
//+---------------------------------------------------------------------------------------------------------------------------------------+
void GetTPiSL (double& fd_SL, double& fd_TP, int fi_Type)
{
   if (fi_Type == OP_BUY)
   {
      if (id_SL != 0)
          fd_SL = Bid - id_SL * SSym.gd_Pt;
      if (id_TP != 0)
          fd_TP = Ask + id_TP * SSym.gd_Pt;
   }
   if (fi_Type == OP_SELL)
   {
      if (id_SL != 0)
          fd_SL = Ask + id_SL * SSym.gd_Pt;
      if (id_SL != 0)
          fd_TP = Bid - id_TP * SSym.gd_Pt;
   }
}
//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                                            Trade()                                                                    |
//+---------------------------------------------------------------------------------------------------------------------------------------+
bool Trade (int fi_signal)
{
   double OOP, SL, TP;
   int    PosType, ticket;

 //  if (!IsTimeForTrading())
   //    return (true);
   Print ("SSym.gi_Digits = ", SSym.gi_Digits);
   if (fi_signal == SIGNAL_BUY/* && long*/)
   {
       Print ("fi_signal == SIGNAL_BUY");
       PosType = OP_BUY;
       GetTPiSL (SL, TP, PosType);
       Print ("Trade(): Ask = ", Ask);
       OOP = NormalizeDouble (Ask, 5);
       Print ("Trade(): OOP = ", OOP);
       
       ticket = CPosMan.fOrderSend (_Symbol, PosType, 0.01, OOP, 15, ND (SL), ND (TP), ii_Magic);
   }       
   if (fi_signal == SIGNAL_SELL/* && short*/)
   {
       Print ("fi_signal == SIGNAL_SELL");
       PosType = OP_SELL;
       GetTPiSL (SL, TP, PosType);
       Print ("Trade(): Bid = ", Bid);
       OOP = NormalizeDouble (Bid, 5);
       Print ("Trade(): OOP = ", OOP);
       
       ticket = CPosMan.fOrderSend (_Symbol, PosType, 0.01, OOP, 15, ND (SL), ND (TP), ii_Magic);
   }

   return (true);
}

 Вот код начала метода вызываемого класса ( весь не публикую, дабы не принуждать ни кого ломать свой мозг ). Да и не нужно весь, там на входе принты показали, что параметры не так передаются :

// 1.1 Функция посылает ордер. ============================================================================================================
int PositionsManipulations::fOrderSend (string    fs_Symbol,             // OrderSymbol()
                                        int       fi_Type,               // OrderType()
                                        double    fd_Lot,                // OrderLots()
                                        double    fd_Price,              // OrderOpenPrice()
                                        int       fi_Slip,               // Slippage
                                        double    fd_SL,                 // OrderStopLoss()
                                        double    fd_TP,                 // OrderTakeProfit()
                                        int       fi_Magic = 0,          // OrderMagicNumber()
                                        string    fs_Comm = "",          // OrderComment()
                                        datetime  fdt_Expiration = 0,    // Срок истечения отложенного ордера
                                        color     fc_Arrow = CLR_NONE)   // Цвет открывающей стрелки на графике
{
   int    li_Cmd,
          li_Cnt = 0,
          li_Ticket = -1;
   bool   lb_InvalidSTOP = false,
          lb_FixInvalidPrice = false;
   Print ("fOrderSend(); fs_Symbol = ", fs_Symbol);
   Print ("fOrderSend(); fi_Type = ", IToS (fi_Type));
   Print ("fOrderSend(); fd_Lot = ", DToS (fd_Lot));
   Print ("fOrderSend(); fd_Price = ", DToS (fd_Price));
   Print ("fOrderSend(); fi_Slip = ", DToS (fi_Slip));
   Print ("fOrderSend(); fd_SL = ", DToS (fd_SL));
   Print ("fOrderSend(); fd_TP = ", DToS (fd_TP));
   Print ("fOrderSend(); fi_Magic = ", DToS (fi_Magic));
   //---- Получаем актуальную информацию по символу
   CBase.GetMarkerInfo (fs_Symbol, -1);
   //... ДАЛЬШЕ ОСТАЛЬНОЙ КОД ИДЁТ.....

 Вот библиотечные функции, которые применяются в принтах:

//=========================================================================================================================================
// 1.1a Нормализация числа с плавающей запятой по Digits. =================================================================================
double ND (double v) export
{
    return (NormalizeDouble (v, SSym.gi_Digits));
}
//=========================================================================================================================================
// 1.1b Нормализация числа с плавающей запятой до целого. =================================================================================
double ND0 (double v) export
{
   return (NormalizeDouble (v, 0));
}
//=========================================================================================================================================
// 1.2 Преобразование числа типа double в текстовую строку string, содержащую символьное представление числа в указанном формате точности.
string DToS (double v) export  // DSD
{
    return (DoubleToStr (v, SSym.gi_Digits));
}

 А вот самое главное, лог:

2014.08.16 20:31:00.676 2014.06.20 12:40  RSI EURUSD,M5: GetTradeSignal Output
2014.08.16 20:31:00.676 2014.06.20 12:40  RSI EURUSD,M5: GetTradeSignal Input
2014.08.16 20:31:00.676 2014.06.20 12:40  RSI EURUSD,M5: GetRSI(0) = 47.0
2014.08.16 20:31:00.676 2014.06.20 12:40  RSI EURUSD,M5: GetRSI(1) = 46.0
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: OrderSend error 138
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fd_TP = 1.0
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fd_SL = 0.0
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fd_Price = 1.0
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: Bid = 1.36099
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: Ask = 1.36117
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fOrderSend(); fi_Magic = 3333021
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fOrderSend(); fd_TP = 1
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fOrderSend(); fd_SL = 0
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fOrderSend(); fi_Slip = 15
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fOrderSend(); fd_Price = 1
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fOrderSend(); fd_Lot = 0
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fOrderSend(); fi_Type = 0
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fOrderSend(); fs_Symbol = EURUSD
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: Trade(): OOP = 1.36117
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: Trade(): Ask = 1.36117
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: fi_signal == SIGNAL_BUY
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: SSym.gi_Digits = 5
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: GetRSI (0) > id_RSIToUpLimit: 56.0 > 55.0
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: GetRSI (1) < id_RSIToUpLimit: 54.0 < 55.0
2014.08.16 20:30:57.731 2014.06.20 12:35  RSI EURUSD,M5: GetTradeSignal Input

 Здесь чётко видно, как я с эксперта в функции bool Trade (int fi_signal) вызываю метод CPosMan.fOrderSend () и принтуются соответствующие входящие данные, в том числе, и АСК с БИДом. Потом попадаю в метод класса, эти данные почему-то стали еденицами и нулями. Как это происходит.. ЧТо это вообще такое? Прошу пояснить. Я уже замудохался.

hoz
1936
hoz 2014.08.16 19:00  
Я перекинул в эксперт метод (из класса) и вызываю уже из эксперта данную функцию. Разницы нет. В логе тоже самое. Значения попадают в функцию не верные. Теже 1 и 0. Почему?
Простак
315
Простак 2014.08.16 19:57  
hoz:
Я перекинул в эксперт метод (из класса) и вызываю уже из эксперта данную функцию. Разницы нет. В логе тоже самое. Значения попадают в функцию не верные. Теже 1 и 0. Почему?

Может, неверно печатается? Можно "расширить" печатаемое:

   Print ("fOrderSend(); DToS(fd_Price) = ", DToS (fd_Price), ",  fd_Price = ", fd_Price, ", digits = ", SSym.gi_Digits);

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

hoz
1936
hoz 2014.08.16 20:58  

В общем, я тут копался как обычно. Принтовал всё до самого самого косяка. Нашёл где трабл.

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

 Функция вот начало библиотеки:

#property library
#property copyright "hoz"
#property link      ""
#property version   "1.00"
#property strict
//----
//=========================================================================================================================================
// 1.1a Нормализация числа с плавающей запятой по Digits. =================================================================================
double ND (double v) export
{
    return (NormalizeDouble (v, SSym.gi_Digits));
}
//=========================================================================================================================================
// 1.1b Нормализация числа с плавающей запятой до целого. =================================================================================
/*double ND0 (double v) export
{
   return (NormalizeDouble (v, 0));
}*/
//=========================================================================================================================================
// 1.2 Преобразование числа типа double в текстовую строку string, содержащую символьное представление числа в указанном формате точности.
string DToS (double v) export  // DSD
{
    return (DoubleToStr (v, SSym.gi_Digits));
}

 В эксперте вызываю нужные мне функции библиотеки:

#import     "LDataConvertion.ex4"
   double ND (double v);
   string DToS (double v);
   string IToS (int v);
   string DToSByLots(double v);
#import

 Вот функция, где получаю значения TP и SL. На ней и остановимся...

void GetTPiSL (double& fd_SL, double& fd_TP, int fi_Type)
{
   if (fi_Type == OP_BUY)
   {
      if (id_SL != 0)
          fd_SL = ND (Bid - id_SL * SSym.gd_Pt);
          Print ("GetTPiSL: fd_SL = ", fd_SL);
          Print ("GetTPiSL: ND (fd_SL) = ", ND (fd_SL));
      if (id_TP != 0)
          fd_TP = ND (Ask + id_TP * SSym.gd_Pt);
          Print ("GetTPiSL: fd_TP = ", fd_TP);
          Print ("GetTPiSL: ND (fd_TP) = ", ND (fd_TP));
   }
   if (fi_Type == OP_SELL)
   {
      if (id_SL != 0)
          fd_SL = Ask + id_SL * SSym.gd_Pt;
          Print ("GetTPiSL: fd_SL = ", fd_SL);
          Print ("GetTPiSL: ND (fd_SL) = ", ND (fd_SL));
/*          fd_SL = ND (Ask + id_SL * SSym.gd_Pt);
          Print ("GetTPiSL: fd_SL = ", fd_SL);*/
      if (id_TP != 0)
          fd_TP = Bid - id_TP * SSym.gd_Pt;
          Print ("GetTPiSL: fd_TP = ", fd_TP);
          Print ("GetTPiSL: ND (fd_TP) = ", ND (fd_TP));
/*          fd_TP = ND (Bid - id_TP * SSym.gd_Pt);
          Print ("GetTPiSL: fd_TP = ", fd_TP);*/
   }
}

 А вот и лог в этой функции:

2014.08.16 23:44:32.225 2014.06.20 00:05  RSI EURUSD,M5: GetTPiSL: ND (fd_TP) = 1.0
2014.08.16 23:44:32.225 2014.06.20 00:05  RSI EURUSD,M5: GetTPiSL: fd_TP = 1.35959
2014.08.16 23:44:32.225 2014.06.20 00:05  RSI EURUSD,M5: GetTPiSL: ND (fd_SL) = 0.0
2014.08.16 23:44:32.225 2014.06.20 00:05  RSI EURUSD,M5: GetTPiSL: fd_SL = 0.0
2014.08.16 23:44:32.225 2014.06.20 00:05  RSI EURUSD,M5: fi_signal == SIGNAL_SELL
2014.08.16 23:44:32.225 2014.06.20 00:05  RSI EURUSD,M5: SSym.gi_Digits = 5

 Чётко видно, что если значения не нормализовать, т.е. не использовать библиотечную функцию ND(), то значения остаются такими какими и должны быть. А вот если использовать библиотечную функцию ND(), то данное значения каким-то чудесным образом превращается в 0 или в 1.

 Вот почему так происходит, я что-то в втыкаю. Есть предложения?

Простак
315
Простак 2014.08.17 01:48  
hoz:

В общем, я тут копался как обычно. Принтовал всё до самого самого косяка. Нашёл где трабл.

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

 Функция вот начало библиотеки:

 В эксперте вызываю нужные мне функции библиотеки:

 Вот функция, где получаю значения TP и SL. На ней и остановимся...

 А вот и лог в этой функции:

 Чётко видно, что если значения не нормализовать, т.е. не использовать библиотечную функцию ND(), то значения остаются такими какими и должны быть. А вот если использовать библиотечную функцию ND(), то данное значения каким-то чудесным образом превращается в 0 или в 1.

 Вот почему так происходит, я что-то в втыкаю. Есть предложения?

Есть. Значение SSym.gi_Digits "в библиотеке" равно 0. Ведь именно в этом случае NormalizeDouble вернёт то, что она возвращает в реальности. Имеет смысл распечатать его прямо оттуда:

// 1.1a Нормализация числа с плавающей запятой по Digits. =================================================================================
double ND (double v) export
{
     Print ("SSym.gi_Digits = ", SSym.gi_Digits);
     return (NormalizeDouble (v, SSym.gi_Digits));
}

И посмотреть на результат. Формат вывода в логе, возможно, "испортится", но оно того стоит, чтобы узнать правду.

hoz
1936
hoz 2014.08.17 10:43  
 Я так понял, что для мультивалютника библиотеку не написать удобную. По-любому придётся передавать параметров туда много. Хотел чисто количество знаков выбранного инструмента с класса туда посылать, но не вышло.. Если поставить _Digits всё работает.
Dmitry Fedoseev
41217
Dmitry Fedoseev 2014.08.17 11:48  
hoz:

 Тестирую некоторые классы. Взял инюк RSI и на нём накатал сов сугубо для обкатки класссов. Обнаружил, что в класс передаются значение рыночных данных одни, а на выходе выходят другие, а точнее сплошные еденицы. Почему так?...


Такое случаетcя, когда вместо типа double используется тип int.
Простак
315
Простак 2014.08.17 13:23  
hoz:
 Я так понял, что для мультивалютника библиотеку не написать удобную. По-любому придётся передавать параметров туда много. Хотел чисто количество знаков выбранного инструмента с класса туда посылать, но не вышло.. Если поставить _Digits всё работает.

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

Необязательно передавать много параметров: можно собрать их в классе и передать туда объект этого класса по ссылке. Класс должен скрывать сами данные (private), а доступ к ним должен быть организован с помощью открытых (public) методов.

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

Тогда получится написать библиотеку, в том числе, удобную.

/
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий