Что лучше использовать? - страница 2

 
Dmitry Fedoseev:
Дык глобальных переменных может быть несколько к одному ордеру привязано.

Дмитрий, я давно заметил твою любовь к GV, но не все к ним относятся так-же.

Только представь сколько надо переменных и каждой из них уникальное имя, да ещё и в имя засунуть какие-то дополнительные признаки. А потом ещё и разобраться какая переменная к чему относится.

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

А в GV, даже если убрать расчётные значения, которые можно пересчитать каждый раз выбрав ордер, останется 4-5 необходимых на 10 ордеров то получится 40-50 переменных. Замучаешься их тусовать перед выбором нужного.

 

Вот как раз тусовать надо будет массив, даже если он из структур, в поисках нужного тикета. С глобалками префикс подготовил в ините, еще можно класс сделать, и не вспоминать о префиксе.

Если нравится грызть кактус, грызите кактус, не возражаю. 

 
Ну так нет-же разницы, что перебирать массив с тикетами ордеров, что перебирать сами ордера. Но в дополнение к этому надо либо прочесть параметры из структуры, либо как-то разобраться какое имя GV надо прочесть.
 
Alexey Viktorov:

Так для этого и решил писать в файл, чтобы не пропали. Можно конечно использовать массив структур и писать их в файл только при выходе, но надо предусмотреть аварийный выход и соответственно писать не только при выходе. А раз так то и теряется смысл в массиве.

А GV не нравится тем-же, чем не получается в этом случае использовать магик.

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

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

 
Dmitry Fedoseev:

Почему это комментарий не вариант?

Напр для бинарных опционов или при частичном закрытии ордеров

 

Alexey Viktorov:

А GV не нравится тем-же, чем не получается в этом случае использовать магик.

Имена глобальных много удобнее - недавно обнаружил, что туда даже путь к файлу со слэшами и пробелами можно вписать. Если хотите, покажу образец кодирования/раскодирования имён глобальных. Но скорей всего у вас просто глаз замылилсо - обычно достаточно одного/двух идентификаторов для ордера, а всё остальное (уровни и лоты) можно восстановить по ним, свойствам ордера и пользовательским настройкам. Согласен с Vasiliy Sokolov - не хранить и сверять, а пересчитывать каждый раз, используя для этого класс или структуры

 
Vasiliy Sokolov:

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

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

Думаю я был не правильно понят. В файле структура, со значениями в которой сверяется открытый или закрывшийся ордер. Таким образом я определяю что ордер активировался, то-есть был тип OP_BUYSTOP а стал OP_BUY... исправил структуру и записал её, при следующем переборе ордеров он уже обрабатывается как позиция. Если вдруг ордер закрылся по тейку или стопу, то из структуры определяются остальные ордера группы и сов закрывает их, затем к ордерам этой группы больше не возвращается. Я не храню в файле открытые ордера, просто сравниваю его текущее состояние с предыдущим. В цикле перебираются только те ордера которые были живы до текущего перебора. По моему, даже если ордер закроется в момент выполнения кода, то когда ордер будет выбран по тикету, то он сразу будет определён как закрытый.
 
Alexander Puzanov:

Напр для бинарных опционов или при частичном закрытии ордеров

 

Имена глобальных много удобнее - недавно обнаружил, что туда даже путь к файлу со слэшами и пробелами можно вписать. Если хотите, покажу образец кодирования/раскодирования имён глобальных. Но скорей всего у вас просто глаз замылилсо - обычно достаточно одного/двух идентификаторов для ордера, а всё остальное (уровни и лоты) можно восстановить по ним, свойствам ордера и пользовательским настройкам. Согласен с Vasiliy Sokolov - не хранить и сверять, а пересчитывать каждый раз, используя для этого класс или структуры

Вот о том что в имя GV можно вписать спец символы я не знал, да и проверять не стал-бы. Спасибо за полезную информацию.

Вот тоже не могу понять "...не хранить и сверять, а пересчитывать каждый раз, используя для этого класс или структуры" ведь для того чтобы сверять надо структуру хранить. Иначе с чем сверять? И как понять "пересчитывать используя для этого класс или структуры", ну в классе понятно могут быть вычисления, а в структуре? Разве не только хранение переменных пользовательского типа? Если я правильно выразился...

 
Alexey Viktorov:

Вот тоже не могу понять "...не хранить и сверять, а пересчитывать каждый раз, используя для этого класс или структуры" ведь для того чтобы сверять надо структуру хранить. Иначе с чем сверять?

История операций - та же база данных, там же есть ~90% того что надо. И работать с ней удобно как с БД, делая выборки. Напр, запомнил время последнего тика, при след тике сделал выборку из истории на предмет "какие ордера закрылись начиная со времени последнего тика", из глобальной с номером тикета закрытого ордера прочёл идентификатор группы, к котор он относится, закрыл группу и поубивал все её глобальные

И как понять "пересчитывать используя для этого класс или структуры", ну в классе понятно могут быть вычисления, а в структуре? Разве не только хранение переменных пользовательского типа?

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

struct DAY_SESSIONS {
        int             ia_Start_Seconds[];
        int             ia_Stop_Seconds[];
        int             i_Sessions_Count;
        
        void    DAY_SESSIONS() {
                i_Sessions_Count = 0;
                ArrayResize(ia_Start_Seconds, i_Sessions_Count);
                ArrayResize(ia_Stop_Seconds, i_Sessions_Count);
        }
        
        int fi_Current_Session_Num() {
                int
                        i_Day_Second = int(TimeCurrent() % 86400),
                        i_Session = EMPTY
                ;
                while(++i_Session < i_Sessions_Count) {
                        if(ia_Start_Seconds[i_Session] < ia_Stop_Seconds[i_Session]) {
                                if(i_Day_Second >= ia_Start_Seconds[i_Session] && i_Day_Second <= ia_Stop_Seconds[i_Session])
                                        return(i_Session + 1);
                        } else if(ia_Start_Seconds[i_Session] > ia_Stop_Seconds[i_Session]) {
                                if(i_Day_Second >= ia_Start_Seconds[i_Session] || i_Day_Second <= ia_Stop_Seconds[i_Session])
                                        return(i_Session + 1);
                        }
                }
                return(i_Session + 1);
        }
        
        void f_Add_Session(string s_Session_Times) {
                string
                        s_Timetable = StringTrimLeft(StringTrimRight(s_Session_Times)),
                        sa_Start_Stop[2],
                        sa_Time[2]
                ;
                ushort
                        i_Minutes_Separator = StringGetCharacter(":", 0),
                        i_Hours_Separator = StringGetCharacter("-", 0)
                ;
                
                if(StringSplit(s_Timetable, i_Hours_Separator, sa_Start_Stop) < 2) return;
                
                ArrayResize(ia_Start_Seconds, i_Sessions_Count + 1);
                ArrayResize(ia_Stop_Seconds, i_Sessions_Count + 1);
                
                StringSplit(StringTrimLeft(StringTrimRight(sa_Start_Stop[0])), i_Minutes_Separator, sa_Time);
                ia_Start_Seconds[i_Sessions_Count] = int(StringToInteger(sa_Time[0]) * 3600 + StringToInteger(sa_Time[1]) * 60);
                
                StringSplit(StringTrimLeft(StringTrimRight(sa_Start_Stop[1])), i_Minutes_Separator, sa_Time);
                ia_Stop_Seconds[i_Sessions_Count++] = int(StringToInteger(sa_Time[0]) * 3600 + StringToInteger(sa_Time[1]) * 60);
        }
};
DAY_SESSIONS go_Weekday_Sessions[7];

И образец обращения к функции этой структуры

        if(go_Weekday_Sessions[DayOfWeek()].fi_Current_Session_Num() == EMPTY) {
                GlobalVariableDel(gs_Prefix + "WinSequence");
                GlobalVariableDel(gs_Prefix + "WinPauseEnd");
                GlobalVariableDel(gs_Prefix + "TradesCounter");
                return;
        }

.

 

Интересно. Я программист без спец. образования, то-есть самоучка. Так чем-же отличается такая структура от класса? Какой смысл класс называть структурой, если в документации есть чёткие примеры структур, например

struct MqlDateTime 
  { 
   int year;           // год 
   int mon;            // месяц 
   int day;            // день 
   int hour;           // час 
   int min;            // минуты 
   int sec;            // секунды 
   int day_of_week;    // день недели (0-воскресенье, 1-понедельник, ... ,6-суббота) 
   int day_of_year;    // порядковый номер в году (1 января имеет номер 0) 
  };
struct MqlTick 
  { 
   datetime     time;          // Время последнего обновления цен 
   double       bid;           // Текущая цена Bid 
   double       ask;           // Текущая цена Ask 
   double       last;          // Текущая цена последней сделки (Last) 
   ulong        volume;        // Объем для текущей цены Last 
  };

и соответствующие способы их использования.


Александр, я прекрасно понимаю что история операций та-же база данных, но размер базы несравнимо больше чем необходимо для работы. Ну представь что в истории набралось 10000 ордеров и вдруг, как уже было, поменяли направление сортировки и/или доступности ордеров в зависимости от настроек закладки "История Счёта". Перебирать все ордера? Пока не офигеешь?

 
Alexey Viktorov:

Александр, я прекрасно понимаю что история операций та-же база данных, но размер базы несравнимо больше чем необходимо для работы. Ну представь что в истории набралось 10000 ордеров и вдруг, как уже было, поменяли направление сортировки и/или доступности ордеров в зависимости от настроек закладки "История Счёта". Перебирать все ордера? Пока не офигеешь?

Ну да, один раз придёццо посидеть, сочинить функцию с нужным набором выборок из этой БД. Но потом она вставляется за 5 сек в режиме "копипаст" и никакого офигевания, бо от порядка сортировки ничего не зависит. Гридер с 2мя динамическими сетками и сложными взаимоотношениями, эти 2 строки

Get_Orders_Data(o_Upward_Grid, Magic, ORD_ALL, "*up*", _Symbol, t_Start_Time - 1);
Get_Orders_Data(o_Downward_Grid, Magic, ORD_ALL, "*down*", _Symbol, t_Start_Time - 1);

Заполняют 2 структуры-справочника 2х наборов ордеров такого содержания:

        double          d_Lots_Total;       // сумма лотов
        double          d_Profit_Total;     // суммарная прибыль
        double          d_BreakEven_Price;  // уровень б/у
        double          d_One_Point_Price;  // прибыль одного пункта
        datetime        t_Data_Collected;   // время последнего обновления данных
        int             i_Orders_Total;     // кол-во ордеров
        bool            b_Changed;          // была операция после последнего обновления данных?
        ORDERS_GROUP    o_Buy;              // сводка данных ордеров Buy
        ORDERS_GROUP    o_Sell;             // сводка данных ордеров Sell
        ORDERS_GROUP    o_Buy_Stop;         // сводка данных ордеров BuyStop
        ORDERS_GROUP    o_Sell_Stop;        // сводка данных ордеров SellStop
        ORDERS_GROUP    o_Buy_Limit;        // сводка данных ордеров BuyLimit
        ORDERS_GROUP    o_Sell_Limit;       // сводка данных ордеров SellLimit
        ORDERS_GROUP    o_Market;           // сводка данных рыночных ордеров
        ORDERS_GROUP    o_Pendings;         // сводка данных отложенных ордеров

Где "сводки данных" отдельных типов ордеров включают

        double  d_Lots_Total;           // сумма лотов
        double  d_Profit_Total;         // суммарная прибыль
        double  d_BreakEven_Price;      // уровень б/у
        double  d_One_Point_Price;      // прибыль одного пункта
        double  d_Highest_SL;           // самый высокий SL
        double  d_Lowest_SL;            // самый низкий SL
        double  d_Highest_TP;           // самый высокий TP
        double  d_Lowest_TP;            // самый низкий TP
        ORDER   o_Lowest;               // параметры нижнего ордера
        ORDER   o_Highest;              // параметры верхнего ордера
        ORDER   o_Oldest;               // параметры старейшего ордера
        ORDER   o_Newest;               // параметры новейшего ордера
        int     i_Orders_Total;         // кол-во ордеров

Этот справочник сочинил года 2 тому, код кончено сильно изменился, но проблем из-за большого кол-ва ордеров или наоборот ограничения не было ни разу