[АРХИВ]Любой вопрос новичка, чтоб не захламлять форум. Профи, не проходите мимо. Без вас никуда - 5. - страница 289

 
qwert2:
Это я написал что происходит если скрипт просто переложить в папку с экспертами. Он работает но не так как нужно. Скрипт создаёт 8 отложенных ордеров а если его просто сохранить в папке с экспертами то он создаёт 8 отложенных ордеров после каждого тика. А мне нужно что бы он откладывал новые 8 ордеров только после закрытия старых.

А вы в своём скрипте написали только "откладывалку" ? Тады он и будет только и откладывать: сколь тиков придёт - столь он и нало... ой... отложит.

Вам туда нужно впихнуть ещё проверялку-запрещалку ...

 
qwert2:
Это я написал что происходит если скрипт просто переложить в папку с экспертами. Он работает но не так как нужно. Скрипт создаёт 8 отложенных ордеров а если его просто сохранить в папке с экспертами то он создаёт 8 отложенных ордеров после каждого тика. А мне нужно что бы он откладывал новые 8 ордеров только после закрытия старых.
В вопросе этого не было. Это уже не отноститься как скрипт в эксперт переделать. Это другая реализация программы.
 
Roger:

Нашел ошибку. В библиотеке для данной функции в строке

надо удалить по нулю в 13, 14 и 15 числе.


Теперь правильно



Привет библиотечным функциям. 
 
Roger:

Нашел ошибку. В библиотеке для данной функции в строке
надо удалить по нулю в 13, 14 и 15 числе.

Теперь правильно
tara:
Привет библиотечным функциям. 
Нет! Нельзя трогать функции из стандартной библиотеки! Дима запретил  :-))
 
artmedia70:

А вы в своём скрипте написали только "откладывалку" ? Тады он и будет только и откладывать: сколь тиков придёт - столь он и нало... ой... отложит.

Вам туда нужно впихнуть ещё проверялку-запрещалку ... 


))))) Не удержался)))))

Так, ладно, теперь по делу. Работаю над оптимизацией кода секундного ТФ, задался целью перевести double в int[2], чтобы записывать структуру RateInfo одним блоком. Подумал-подумал, решил расписать все возможные в т.ч. нереализуемые способы, чтобы кого-то возможно предостеречь от ошибок.

1. WinAPI (msdn). Вообщем-то, там по функциям конвертации кот наплакал. Это связано с тем, что при конвертации широко используется си-тип перевода, это что-то типа

char s1;
char s2="g";//код ANSI 0x67
int i1=1357;//0x54D в шестн. представлении
int i2;

s1=(char)i1;//0x4D, "M", старший разряд (5) был усечён по границе байта (две шестн. цифры), остался один байт (0x4D, десятичное 77)
i2=(int)s2;//0x00 0x00 0x00 0x67, десятичное 103

 в предпоследней строчке int i1 конвертируется в char, а в последней char s2 конвертируется в int. В итоге всё это хозяйство дружно используется в т.н. "функциях конвертации", которых фактически нет ни в одной dll WinAPI, а они только объявляются в заголовочных .h файлах макросами типа

#define _dtoi64(d)     (*((int64_t *)&(d)))
#define _dtoui64(d)     (*((uint64_t *)&(d)))

 которые препроцессором при компиляции разворачиваются в строку по типу первого кода. А заголовочные .h файлы - это не dll и используются только в среде разработки (Студия, Борланд, gcc и т.д.). Отчего для MQL4 ни холодно, ни жарко. Впрочем, можно всегда перепроверить, действительно объявлена ли функция только в заголовочном .h-файле или есть где-нибудь в скрываемых от лишних глаз экспортируемых функциях в какой-нибудь dll в System32, сейчас распишу как.

2. WinAPI (dll CRT). Эти dll с именами msvcp*, msvcr*, msvcrt*, msvci*, msvcirt. Тут выбор более широк: _atodbl, _atoi64, _atoldbl, _ftol, _i64toa, _itoa, _ltoa, _strtoi64, _strtoui64 _ui64toa, _ultoa, atof, atoi, atol, strtod, strtol, strtoul. Символы в названии имеют следующее значение: 

a, str, w - string
f, l, i, ui, ul - int (4 байта)
d, dbl, i64 - double, int[2] (8 байт)
ldbl - int[2.5] (шучу) - 10 байт.

 Но ожидаемой _dtoi64/_dtoui64 как не было, так и нет. Использовать же определённые в msvcrt*, msvci*, msvcirt.dll

istream::operator>>(double &)
ostream::operator<<(double)

  можно, даже если извернуться, только как файловые операции (они консольные).

Искать, окромя msdn, можно на этом сайте, вот строка поиска по сайту. Аналогичная "удобная" строка поиска по msdn вот. Чем они отличаются? На msdn хорошее описание функций, но некоторых нет вообще (например, NativeAPI). На альтернативном же есть любая таблица экспорта системных dll, но нет описания. В принципе, набор таблиц экспорта на сайте это проще, чем выдёргивать таблицы экспорта из dll самому (IDA, PE Explorer, и т.д.). 

 3. Ассемблерные вставки (точнее, вставки в машинном коде). Сейчас объясню, т.к. оф.документация в этом отношении очень туманна. На MQL4 C++-шные

asm{//или _asm{
   //
   //какой-либо ассемблерный код
   //
}

 нереализуемы, т.к. asm/_asm - не функция, а директива препроцессора, и в system32/*.dll нигде не определена (см. поиск по тому сайту). Другими словами, нет такой 

#import "/Windows/system32/superpuper.dll"
   asm(string& item[]);//в строковый массив заносим команы ассемблера
#import

 В чистом же машинном коде на MQL4 писать можно, но только в одном случае: когда по определению WinAPI-функции в msdn в неё должен передаваться указатель на функцию/процедуру типа lpTimerFunc (законченный пример здесь на форуме), в msdn она объявляется как:

UINT_PTR SetTimer(

    HWND hWnd,
    UINT_PTR nIDEvent,
    UINT uElapse,
    TIMERPROC lpTimerFunc//<-
);

 или lpfnWndProc (незаконченный пример здесь на форуме, msdn-объявление и попытка mql4-объявления структуры). Иначе - никак: MQL4 - интерпретатор, адреса у функции не существует, передавать нечего, только если писать в машинных кодах. Их потом упаковывать в интовый массив, а массив по ссылке передавать уже в функцию.

 Так что компилированные ассемблерные вставки (то есть машинный код) для данной задачи неприменимы - у них совершенно другая область применения. Максимум, что из этого можно выжать - это запустить такой интовый массив через debug в cmd через shell32.dll. Командную строку там передавать кажется нельзя, но можно писать виртуальными клавишами через keybd_event.

4. Написание своей функции конвертации double в int[2] на чистом MQL4 без вставок. Но я так прикинул объём кода и скорость его быстродействия, просто отказался. Сам модуль даже не писал, но алгоритм так понимаю там следующий:

1. Объявляем bool[64].
2. bool[0] равен 0, если плюс, и 1, если минус (отрицательное число то есть).
3. Находим значение выражения целая_часть(log_2(число))+1023. В цикле находим остатки от деления его на 2, заносим их в bool[11]-bool[1]
        в обратном порядке.
4. Разделяем целую и дробную чсти, сохраняем их в разные переменные.
5. Для целой части в цикле находим остаток от деления её на 2, пока не останется остаток от деления 1 или 0, заносим в этом же цикле значения
        в массив с bool[13+log_2(целая_часть)] до bool[12], в обратном порядке.
6. Для дробной части в цикле находим целую часть числа при циклическом умножении на 2. Целую часть запоминаем и отбрасываем, дробную умножаем дальше.
        Цикл до тех пор, пока при умножении в результате не получится 1. Заносим в прямом порядке, т.е. с начала (а начало на следующей ячейке после
        окончания пред. записи).
7. Теперь в цикле собираем в int[2] с конца bool[64], помня, что в int[0] идёт bool[0]-bool[31], а в int[1] идёт bool[32]-bool[63].
8. Ах, да, ещё BigEndian забыл.

 что очень долго будет выполняться. Так пришёл-таки к самому очевидному и самому простому решению

5. Использование самонаписанной dll на C++. Код вышел следующий:

#include "stdafx.h"

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                                         )
{
    return TRUE;
}

__declspec(dllexport) void __stdcall dtoi(unsigned _int64 Dbl, int iDbl[2])
 {
        iDbl[0]=static_cast<unsigned int>(Dbl);
        iDbl[1]=static_cast<unsigned int>(Dbl>>32);
        return;
 }

 В скрипте

#property show_inputs //для вывода окна с настройкой параметров

#import "double.dll"//самонаписанная dll
   void dtoi(double Dbl, int& iDbl[]);
#import

extern double Dbl=96.578;//в параметрах передаём любую double-переменную
int iDbl[2];//и выходной double->int[2] массив
int handle;//хэндл тестового файла

int start(){
   handle=FileOpen("test.txt",FILE_BIN|FILE_WRITE);//открываем тестовый файл как бинарный "только на запись"
   FileWriteDouble(handle, Dbl);//записываем в тестовый файл double-переменную (8 байт)
   dtoi(Dbl, iDbl);//вызываем функцию конвертации; в iDbl помещается разпарсенный double
   FileWriteArray(handle, iDbl, 0, 2);//записываем в тестовый файл int[2]-переменную (8 байт)
   FileClose(handle);//сначала идут 8 байт double, затем 4+4=8 байт сконвертированных int
   return(0);//Получаем перезаписываемый \experts\files\test.txt в 16 байт.
  }

 В int upper[0] обратно меняется потому, что мы его передаём по ссылке. Получаем:

 

 ...заработало, строки в дампе идиентичны. Прикрепляю папочку, в ней в libraries находится double.dll, в samples - исходники dll, в scripts - скрипт.

Вечером: перезалил архив и немного подделал код скрипта и dll.

Файлы:
ftdqcs.zip  57 kb
 

Не пойму, что я сделал не так. Почему-то закрытие позиции происходит не так, как я планировал?

 Вот критерий на открытие позиции

         if (Ask > iBands(NULL,0,M,2,0,N,MODE_LOWER,0)&& Low [1] < iBands(NULL,0,M,2,0,N,MODE_LOWER,1) && Hour()>=23 || Hour()<4)
         if (iStochastic(NULL,0,K,D,L,MODE_SMA,0,MODE_MAIN,0)> 20 && iStochastic(NULL,0,K,D,L,MODE_SMA,0,MODE_MAIN,1) < 20)
           {     
            Opn_B  =  true;     // Критерий открs. Buy
            OpenFunction ( Opn_B,  Opn_S, Lots);     //окрываем позицию
            
           }
         
         if (Bid < iBands(NULL,0,M,2,0,N,MODE_UPPER,0)&& High [1] > iBands(NULL,0,M,2,0,N,MODE_UPPER,1) && Hour()>=23 || Hour()<4)
         if (iStochastic(NULL,0,K,D,L,MODE_SMA,0,MODE_MAIN,0)> 80 && iStochastic(NULL,0,K,D,L,MODE_SMA,0,MODE_MAIN,1) < 80)
       
           {   
            Opn_S  =  true;     // Критерий откр. Sell
            OpenFunction ( Opn_B,  Opn_S,  Lots);     //окрываем позицию 
            
           }

 Вот критерий на закрытие позиции

if (Bid >= iBands(NULL,0,M,2,0,N,MODE_UPPER,0))    
         {                                                                      
         Cls_B  =  true;     // ... получаем критерий для закрытия позиции Buy
         CloseFunction ();     //исполняем функцию закрытия ордеров
         return;
         }
       
       if (Ask <= iBands(NULL,0,M,2,0,N,MODE_LOWER,0))       
         {                                                                      
         Cls_S  =  true;
         CloseFunction ();     //исполняем функцию закрытия ордеров
         return;
         }

 а вот, что получаем:

 

 

 
Zhunko:
Нет! Нельзя трогать функции из стандартной библиотеки! Дима запретил  :-))


Ну  что ты здесь клоунаду устраиваешь? Если ошибка, то или в сервисдеск надо сообщать, или делать свою копию файла. 
 
GaNDarM:

Не пойму, что я сделал не так. Почему-то закрытие позиции происходит не так, как я планировал?

 Вот критерий на открытие позиции

 Вот критерий на закрытие позиции

 а вот, что получаем:

 

 


И как часто проверяется критерий закрытия? Не по барам случайно?
 
ilunga:

И как часто проверяется критерий закрытия? Не по барам случайно?

Не совсем понял суть вопроса. Модель тестирования по ценам открытия (быстрый метод на сформировавшихся барах)
 
Надо вывести деньги из WMZ на QIWI. ищу людей для сотрудничества. Готов взять на себя примерно 5% комиссии