Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Я, откровенно говоря, не совсем понял о чем Вы говорите? Мне не нравится «разношертность» не платформ, а неряшливые отличия в языке MQL.
Ну чем они неряшливые-то ? Они просто разные. Можно так, можно иначе. Может появиться и еще какой-то вариант.
Чтобы не зависеть от данных особенностей конкретной версии языка - существуют стандартные интерфейсы. По идее, Стандартная Библиотека - это именно такой набор классов и интерфейсов (уж очень она мне напоминает библиотеку MS MFC). Но, увы, в СБ идея стандартизации интерфейсов не доведена до логического завершения, в МТ4 и МТ5 - многие классы существенно различны. Поэтому, на мой взгляд, у каждого программиста должны существовать свои шаблоны интерфейсов, с которыми он и работает. В том числе и "обертки" для функций объединения строк, раз уж они в разных версиях разные.
Для примера, вот мой класс-интерфейс торговой позиции:
class CTradePositionI: public CMyObject
{
public:
// Возвращает число компонент позиции внутри позиции (может быть нулевым если позиции нет) или WRONG_VALUE в случае ошибок
virtual int Select(ulong ulMagic = 0,ECurrencySymbol csSymbol = CS_CURRENT) = 0;
// Получение числа компонент и интерфейс отдельной компоненты
virtual uint GetComponentNum() = 0;
virtual CTradePosComponentI* GetComponent(uint uiComponentIdx) = 0;
};
Моя библиотека возвращает только чисто виртуальные интерфейсы, одинаково работающие (с точки зрения советника) во всех платформах. Конкретная реализация спрятана за виртуальными функциями.
Вы запрашиваете позицию по указанному символу и магику, получаете интерфейс CTradePositionI. У этого интерфейса можете запросить число компонент, и перебрать эти компоненты. При запросе компоненты - вы опять же, получаете чисто виртуальный интерфейс CTradePosComponentI, у которого можете запросить объем, цену открытия, ТП-СЛ, и все остальное. Компонента позиции в конечном итоге эквивалентна ордеру на МТ4, и отдельной позиции на МТ5 - но для логики советника это не играет роли, он отдает торговые приказы через такой же чисто виртуальный интерфейс - и совершенно не зависит от конкретной платформы. В дальнейшем у меня есть задумка использовать WLD, и С# - весь написанный код должен будет нормально работать и там, добавятся только соответствующие классы-обертки, согласовывающие вот этот мой виртуальный интерфейс с реальным интерфейсом WLD
на самом деле очень мало отличий кроме работы с ордерами - работы на 30 минут через поиск и автозамену с кодом в 4к строк, изи, лениво покуривая
а строки вообще просто сложить можно, и вообще использовать приведение типов а не стринг то дабл и проч.
Я еще раз повторюсь.
Торговое окружение платформ накладывает определенные требования/ограничения, о чем говорилось в первом посте. И Ваш подход по решению проблем совместимости понятен, и думаю, что правильный.
Однако, я о другом - согласитесь, что функции поиска почему то разные:
const void& array[], // массив для поиска
int start=0, // с какого индекса начинаем поиск
int count=WHOLE_ARRAY // количество проверяемых
);
const void& array[], // массив для поиска
int count=WHOLE_ARRAY, // количество проверяемых
int start=0 // с какого индекса начинаем поиск
);
Не знаю, как подобные «мины»\различия можно чем то разумным объяснить.
Я еще раз повторюсь.
Торговое окружение платформ накладывает определенные требования/ограничения, о чем говорилось в первом посте. И Ваш подход по решению проблем совместимости понятен, и думаю, что правильный.
Однако, я о другом - согласитесь, что функции поиска почему то разные:
Не знаю, как подобные «мины»\различия можно чем то разумным объяснить.
Не знаю, как подобные «мины»\различия можно чем то разумным объяснить.
#ifdef __MQL5__
template <typename T>
int MT4ArrayMaximum(
const T& array[], // массив для поиска
int count=WHOLE_ARRAY, // количество проверяемых
int start=0 // с какого индекса начинаем поиск
)
{
return(ArrayMaximum(array, start, count));
}
#define ArrayMaximum MT4ArrayMaximum
#endif
void OnStart()
{
int Array[] = {5, 4, 3, 2, 7};
Print(ArrayMaximum(Array, 3));
return;
}
Ну чем они неряшливые-то ? Они просто разные. Можно так, можно иначе. Может появиться и еще какой-то вариант.
Чтобы не зависеть от данных особенностей конкретной версии языка - существуют стандартные интерфейсы. По идее, Стандартная Библиотека - это именно такой набор классов и интерфейсов (уж очень она мне напоминает библиотеку MS MFC). Но, увы, в СБ идея стандартизации интерфейсов не доведена до логического завершения, в МТ4 и МТ5 - многие классы существенно различны. Поэтому, на мой взгляд, у каждого программиста должны существовать свои шаблоны интерфейсов, с которыми он и работает. В том числе и "обертки" для функций объединения строк, раз уж они в разных версиях разные.
СБ во многих местах - это нечто странное. Иногда возникает чувство, что ее писали, лишь бы начальник отвязался. Пример: COrderInfo. Для получения информации об ордере используется метод COrderInfo::StoreState(void), она заполняет поля, лежащие в секции protected
{
protected:
ulong m_ticket;
ENUM_ORDER_TYPE m_type;
ENUM_ORDER_STATE m_state;
datetime m_expiration;
double m_volume_curr;
double m_price_open;
double m_stop_loss;
double m_take_profit;
public:
// далее методы доступа к данным и др..
};
//+------------------------------------------------------------------+
//| Stored order's current state |
//+------------------------------------------------------------------+
void COrderInfo::StoreState(void)
{
m_type =OrderType();
m_state =State();
m_expiration =TimeExpiration();
m_volume_curr=VolumeCurrent();
m_price_open =PriceOpen();
m_stop_loss =StopLoss();
m_take_profit=TakeProfit();
}
А теперь угадайте, что происходит при вызове метода для чтения значения? Думаете, оно берется из заполненного заранее поля? Нет, оно заново читается, а поля m_**** вообще в классе никак не используются!!
//| Get the property value "ORDER_SL" |
//+------------------------------------------------------------------+
double COrderInfo::StopLoss(void) const
{
return(OrderGetDouble(ORDER_SL));
}
//+------------------------------------------------------------------+
//| Get the property value "ORDER_TP" |
//+------------------------------------------------------------------+
double COrderInfo::TakeProfit(void) const
{
return(OrderGetDouble(ORDER_TP));
}
//+------------------------------------------------------------------+
***
СБ во многих местах - это нечто странное. Иногда возникает чувство, что ее писали, лишь бы начальник отвязался. Пример: COrderInfo. Для получения информации об ордере используется метод COrderInfo::StoreState(void), она заполняет поля, лежащие в секции protected.
...
А теперь угадайте, что происходит при вызове метода для чтения значения? Думаете, оно берется из заполненного заранее поля? Нет, оно заново читается, а поля m_**** вообще в классе никак не используются!!
Да, Алексей, как я понимаю, данная нелогичность, видимо, объясняется тем, что классы разрабатывались не одновременно, разными людьми, причем, в основном трейдерами, а не программистами.
Но, многие принципы, заложенные в СБ - очень даже правильные. Более того, я, скажем, практически никогда не использовал в своем коде непосредственно массивы - в первую очередь из-за отсутствия указателей и ссылок на них. Мне гораздо удобнее использовать классы-наследники CArray.
А насчет разности платформ - до введения условной компиляции приходилось мудрить со включаемыми файлами, но сейчас - никаких проблем уже нет, fxsaber совершенно верно привел иллюстрацию (правда, только половину, код МТ4 он не привел).
Однако, я о другом - согласитесь, что функции поиска почему то разные:
Не знаю, как подобные «мины»\различия можно чем то разумным объяснить.
Неожиданная для меня, но видимо очевидная для авторов доктрины неожиданного применения "терминального нуля" или реакции на его наличие в string, мина различного поведения в MT4 и 5 "подорвала" мое время на поиски. Проиллюстрирую ее кодом.
Результат выполнения в МТ5 ожидаем и, на мой взгляд, верный:
2021.10.03 22:45:14.506 BugAdd_zero (EURUSD,M1) ------------ txt
2021.10.03 22:45:14.506 BugAdd_zero (EURUSD,M1) Txt ='MetaQuotes Software Corp.' Len=25 SizeArray=25
2021.10.03 22:45:14.506 BugAdd_zero (EURUSD,M1) Txt ='MetaQuotes Software Corp.' Len=35 SizeArray=35
2021.10.03 22:45:14.506 BugAdd_zero (EURUSD,M1) Txt ='MetaQuotes Software Corp.' Len=50 SizeArray=50
2021.10.03 22:45:14.506 BugAdd_zero (EURUSD,M1) ------------ txt+'0x00'
2021.10.03 22:45:14.506 BugAdd_zero (EURUSD,M1) Txt0 ='MetaQuotes Software Corp.' Len=26 SizeArray=26
2021.10.03 22:45:14.506 BugAdd_zero (EURUSD,M1) Txt0 ='MetaQuotes Software Corp.' Len=36 SizeArray=36
2021.10.03 22:45:14.506 BugAdd_zero (EURUSD,M1) Txt0 ='MetaQuotes Software Corp.' Len=51 SizeArray=51
MT4 настойчиво убежден при использовании StringToCharArray, что терминальный ноль должен присутствовать только в конце string.
StringLen при этом так не считает... )
2021.10.03 22:46:32.442 Script BugAdd_zero EURGBP,M1: removed
2021.10.03 22:46:32.426 BugAdd_zero EURGBP,M1: uninit reason 0
2021.10.03 22:46:32.426 BugAdd_zero EURGBP,M1: Txt0 ='MetaQuotes Software Corp.' Len=51 SizeArray=26
2021.10.03 22:46:32.426 BugAdd_zero EURGBP,M1: Txt0 ='MetaQuotes Software Corp.' Len=36 SizeArray=26
2021.10.03 22:46:32.426 BugAdd_zero EURGBP,M1: Txt0 ='MetaQuotes Software Corp.' Len=26 SizeArray=26
2021.10.03 22:46:32.426 BugAdd_zero EURGBP,M1: ------------ txt+'0x00'
2021.10.03 22:46:32.426 BugAdd_zero EURGBP,M1: Txt ='MetaQuotes Software Corp.' Len=50 SizeArray=26
2021.10.03 22:46:32.426 BugAdd_zero EURGBP,M1: Txt ='MetaQuotes Software Corp.' Len=35 SizeArray=26
2021.10.03 22:46:32.426 BugAdd_zero EURGBP,M1: Txt ='MetaQuotes Software Corp.' Len=25 SizeArray=25
2021.10.03 22:46:32.426 BugAdd_zero EURGBP,M1: ------------ txt
2021.10.03 22:46:32.426 BugAdd_zero EURGBP,M1: initialized
2021.10.03 22:46:32.411 Script testbug\BugAdd_zero EURGBP,M1: loaded successfully
Это баг или так спроектировано?
Это баг или так спроектировано?
в MQL5 поведение StringToCharArray относительно \0 только относительно недавно поменяли