Вопросы (Yerkin Sagandykov) - страница 3

 
union DblChar {
        double  d;
        uchar   c[8];
} dc;



//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
string
GVarGetString(string name) {
        double dbl[];
        int i;
        
        // Читаем части переменной: Имя, Имя(1), Имя(2), ...
        for (i = 0; ; ++i) {
                string s = (i == 0)? "" : "(" + (string)i + ")";
                double t = GlobalVariableGet(name + s);
                if (t == 0)
                        break;
                
                ArrayResize(dbl, i + 1);
                dbl[i] = t;
        }
        
        uchar tmp0[];
        ArrayResize(tmp0, i * 8);
        for (int idx = 0, j = 0; j < i; idx += 8, ++j) {
                dc.d = dbl[j];
                ArrayCopy(tmp0, dc.c, idx, 0, 8);
        }
        
        uchar tmp1[], key[];  
        if (tmp0[0] == 0) {
                // Со сжатием
                ArrayCopy(tmp1, tmp0, 0, 1);
                CryptDecode(CRYPT_ARCH_ZIP, tmp1, key, tmp0);
        }
        return CharArrayToString(tmp0);
}



//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
datetime GVarSetString(string name, string val) {
        GVarDel(name);
        
        //uchar zero[1];
        
        int len = StringLen(val);
        uchar _val[];
        StringToCharArray(val, _val, 0, len);
        
        double dbl[];
        uchar tmp[], key[];
        int size;
        int cnt = CryptEncode(CRYPT_ARCH_ZIP, _val, key, tmp);
        if (cnt >= len) {
                // Без сжатия
                size = (len + 7) / 8;
                ArrayResize(dbl, size);
                int i, j;
                for (i = 0, j = 0; j < size; i += 8, ++j) {
                        ArrayCopy(dc.c, _val, 0, i, 8);
                        if (len > 0 && len < 8)
                                ArrayFill(dc.c, len, 8 - len, 0);
                        len -= 8;
                        dbl[j] = dc.d;
                }
        }
        else {
                // Со сжатием
                
                size = (cnt + 1 + 7) / 8;
                ArrayResize(dbl, size);
                
                dc.c[0] = 0;                                                                            // Байт[0] == 0 - со сжатием, с байта[1] - данные
                ArrayCopy(dc.c, tmp, 1, 0, 7);
                cnt -= 7;
                dbl[0] = dc.d;
                
                int i, j;
                for (i = 7, j = 1; j < size; i += 8, ++j) {
                        ArrayCopy(dc.c, tmp, 0, i, 8);
                        if (cnt > 0 && cnt < 8)
                                ArrayFill(dc.c, cnt, 8 - cnt, 0);
                        cnt -= 8;
                        dbl[j] = dc.d;
                }
        }
        
        // Пишем части переменной: Имя, Имя(1), Имя(2), ...
        const datetime res = GlobalVariableSet(name, dbl[0]);
        for (int i = 1; i < size; ++i)
                if (GlobalVariableSet(name + "(" + (string)i + ")", dbl[i]) == 0) {
                        DebugBreak();
                        return 0;
                }
        
        GlobalVariablesFlush();
        return res;
}



//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
bool GVarDel(const string name) {
        return GlobalVariableDel(name) && (GlobalVariablesDeleteAll(name + "(") >= 0);
}



//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void OnStart() {
        GVarSetString("t", "12345678");
        string s = GVarGetString("t");
        
        GVarSetString("t", "123456789");
        s = GVarGetString("t");
        
        GVarSetString("t", "123123123123123123123123123123");
        s = GVarGetString("t");
}
 
Edgar Akhmadeev #:

Я храню строковые переменные как имена файлов. Макс. длина больше 100 (не помню точно, да и можно увеличить правкой в реестре). Работает очень быстро (каталог имён кешируется в памяти) и не занимает место (файл нулевой длины, а минимальный блок - 4К, вроде).

Только надо следить (кроме длины строки) за неразрешёнными в именах символами (: / \) и перекодировать, если используешь.

Код fxsaber тоже использую, но не для строк, а для других простых данных, и даже массивов.

тоже пришла такая мысль. можно пример привести? 
https://www.mql5.com/ru/forum/477193#comment_55234499 здесь как раз думал но проблем че то с чтением директория 

TERMINAL_DATA_PATH
TERMINAL_DATA_PATH
  • 2024.11.26
  • Yerkin Sagandykov
  • www.mql5.com
Всем привет ! почему пишет ошибку...
 
Edgar Akhmadeev #:

мысль использовать несколько подряд глобалок хороша.

но циклы чтение/запись не атомарны и это потенциально такой БАГ который потом фик поймаешь.

один раз редко но метко - часть переменных поменялась, а часть нет. Но читатель прочёл всё, от чего и рухнул (или начал чё-нить торговать не дай бог). 

тогда надо ещё одну переменную заводить как семафор ..и тщательно следить за её целостностью/корректностью, если кто-то упал или завершился не освободив, то семафор станет невалидным 

получается чрезмерная сложность. Тогда надёжнее и проще через ресурсы или sqlite. Заодно и код более очевиден и его меньше

Кто может себе позволить DLL - тот вообще таких проблем не знает.  :-)

 
Yerkin Sagandykov #:

тоже пришла такая мысль. можно пример привести? 
https://www.mql5.com/ru/forum/477193#comment_55234499 здесь как раз думал но проблем че то с чтением директория 

// return value and date set (after _)
bool CommonVariableGet(string folder, string name, string& value, datetime& dt) {
        //value = "";
        static string fileName;
        static string s;
        s = folder + name + "=*.var";
        long find = FileFindFirst(s, fileName, FILE_COMMON);
        int LE = GetLastError();
        if (find < 0) {
                // Print error here
                return false;
        }

        static string s2;
        if (FileFindNext(find, s2) && s2 != NULL) {
                // Print error here
                return false;
        }
        FileFindClose(find);
        
        int len = StringFind(fileName, ".var");
        s = StringSubstr(fileName, 0, len);
        static string buffer[2];
        if (StringSplit(s, '=', buffer) != 2) {
                // Print error here
                return false;
        }

        dt = 0; 
        if (StringSplit(buffer[1], '_', buffer) == 2)
                dt = (datetime)StringToInteger(buffer[1]);
        value = buffer[0];
        return true;
}



bool CommonVariableGet(string folder, string name, int& value, datetime& dt) {
        static string v;
        if (!CommonVariableGet(folder, name, v, dt)) {
                value = 0;
                return false;
        }

        value = (int)StringToInteger(v);
        return true;
}



bool CommonVariableGet(string folder, string name, bool& value, datetime& dt) {
        static string v;
        if (!CommonVariableGet(folder, name, v, dt)) {
                value = 0;
                return false;
        }

        value = (bool)StringToInteger(v);
        return true;
}



bool CommonVariableGet(string folder, string  name, double& value, datetime& dt) {
        static string v;
        if (!CommonVariableGet(folder, name, v, dt)) {
                value = 0;
                return false;
        }

        value = StringToDouble(v);
        return true;
}



bool CommonVariableSet(string folder, string name, string value) {
        // Delete all var instances
        bool exists = false;
        static string s;
        s = folder + name + "=*.var";
        static string fileName;
        long find = FileFindFirst(s, fileName, FILE_COMMON);
        int LE = GetLastError();
        if (find < 0) {
                // не нашли переменную
                //datetime dt = TimeCurrent();
                s = StringFormat("%s%s=%s_%i.var", folder, name, value, tick.time);
                int h = FileOpen(s, FILE_WRITE|FILE_COMMON);
                if (h < 0) {
                        // Print error here
                        return false;
                }
                
                FileClose(h);
                return true;
        }

        static string s2;
        if (FileFindNext(find, s2)) {
                // Print error here
                return false;
        }
        FileFindClose(find);

        // нашли переменную
        int len = StringFind(fileName, ".var");
        s = StringSubstr(fileName, 0, len);
        static string buffer[2];
        if (StringSplit(s, '=', buffer) != 2) {
                // Print error here
                return false;
        }
        
        s = buffer[1];

        /*
        datetime t = 0;
        if (StringSplit(s, '_', buffer) > 1)
                t = (datetime)StringToInteger(buffer[1]);
        */
        StringSplit(s, '_', buffer);

        if (value == buffer[0])
                // Значение совпадает, игнорируем
                return true;

        // Значение не совпадает, меняем
        s = StringFormat("%s%s=%s_%i.var", folder, name, value, tick.time);
        if (!FileMove(folder + fileName, FILE_COMMON, s, FILE_COMMON)) {
                // Print error here
                return false;
        }
        
        return true;
}



bool CommonVariableSet(string folder, string name, int value) {
        return CommonVariableSet(folder, name, IntegerToString(value));
}



bool CommonVariableSet(string folder, string name, bool value) {
        return CommonVariableSet(folder, name, IntegerToString(value));
}



bool CommonVariableSet(string folder, string name, double value, int precision=8) {
        return CommonVariableSet(folder, name, DoubleToString(value, precision));
}



void CommonVariableClear(string folder, string name, bool mask=true) {
        // Delete all var instances
        static string fileName;
        const string m = mask? "*=*.var" : "=*.var";
        long find = FileFindFirst(folder + name + m, fileName, FILE_COMMON);
        if (find < 0)
                return;

        do {
                if (!FileDelete(folder + fileName, FILE_COMMON)) {
                        // Print error here
                        Sleep(1000);
                        continue;
                }
        } while (FileFindNext(find, fileName) && !IsStopped());

        FileFindClose(find);
}
 
Maxim Kuznetsov #:

мысль использовать несколько подряд глобалок хороша.

но циклы чтение/запись не атомарны и это потенциально такой БАГ который потом фик поймаешь.

один раз редко но метко - часть переменных поменялась, а часть нет. Но читатель прочёл всё, от чего и рухнул (или начал чё-нить торговать не дай бог). 

тогда надо ещё одну переменную заводить как семафор ..и тщательно следить за её целостностью/корректностью, если кто-то упал или завершился не освободив, то семафор станет невалидным 

получается чрезмерная сложность. Тогда надёжнее и проще через ресурсы или sqlite. Заодно и код более очевиден и его меньше

Кто может себе позволить DLL - тот вообще таких проблем не знает.  :-)

Код не релизного состояния. При желании можно доводить. Но я его не стал использовать.

Ресурсы не пробовал, а идея с sqlite мне нравится.
 
Maxim Kuznetsov #:

мысль использовать несколько подряд глобалок хороша.

но циклы чтение/запись не атомарны и это потенциально такой БАГ который потом фик поймаешь.

один раз редко но метко - часть переменных поменялась, а часть нет. Но читатель прочёл всё, от чего и рухнул (или начал чё-нить торговать не дай бог). 

тогда надо ещё одну переменную заводить как семафор ..и тщательно следить за её целостностью/корректностью, если кто-то упал или завершился не освободив, то семафор станет невалидным 

получается чрезмерная сложность. Тогда надёжнее и проще через ресурсы или sqlite. Заодно и код более очевиден и его меньше

Кто может себе позволить DLL - тот вообще таких проблем не знает.  :-)

PS: Многокомпонентные глобальные переменные не надо использовать между экспертами, Вы правы. Только для хранения. И то...

Здесь такая цель не ставилась.

А для передачи нужны быстрые методы, например, через pipe/memory. Но это другая тема.

Я для передачи строковых сообщений между экспертами применил описанный выше CommonVariableSet, не потому, что это идеальный способ, мне было проще реализовать "на коленке". Для моей разовой цели подошло и ладно. Никаких проблем с синхронизацией нет - несколько писателей и один читатель. И скорости достаточно для моих целей.

 
Edgar Akhmadeev #:

Спасибо  друже  !

 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Удаление отложенных ордеров

Yerkin Sagandykov, 2024.11.08 23:32

Всем привет !
с МТ4 перехожу на 5 - не  подскажете как удалить все отложенные ордера  с Magic и Symbol у которых время установки более 10  секунд ?

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Удаление отложенных ордеров

Alexey Viktorov, 2024.11.09 07:24

В цикле определяя разницу текущего времени и 

ORDER_TIME_SETUP

Время постановки ордера

datetime


 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Telegram

Yerkin Sagandykov, 2024.11.08 21:15

Всем привет !
в MetaTrader 5 возможно в коде напрямую отслеживать, включен ли сайт Telegram в разрешенные через код торговой платформы ? без отпаврки   HTTP-запросов

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Telegram

Andrey Khatimlianskii, 2024.11.10 16:54

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


 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

отчет по сделкам- выравнивание

Yerkin Sagandykov, 2024.11.14 10:56

Всем привет !

как в отчете выровнять цифры по одной вертикальной  линии ? всякие варианты пробовал - пляшут цифры. Вообще есть готовые библиотеки  для отчетов ?

string summaryMess = StringFormat("Отчет сформирован: %s\nНачальный баланс на начало недели: %.2f\n"
                                     "За текущую неделю:\nКоличество прибыльных сделок: %d\nОбщая прибыль от сделок: %.2f\n"
                                     "Количество убыточных сделок: %d\nОбщие убытки: %.2f\nОбъем лотов: %.2f\n"
                                     "Итоговый баланс на конец недели: %.2f\nЧистая прибыль за неделю: %.2f",
                                     TimeToString(current_time, TIME_DATE | TIME_MINUTES),
                                     initialDeposit, totalProfitTrades, totalProfitAmount,
                                     totalLossTrades, totalLossAmount, totalVolume, finalBalance, netProfit);