If there aren't many options, you can get by with ifs and swipes.
The point is in the work which needs to be done to compress in code solutions of a huge number of tasks. The matter is about universalization of the code, where any additional syntax and shells are simply destructive. It's hard work, but it gets rid of everything superfluous and allows you to evolve, reaching new heights all the time.
Реter Konow: 1. Дело в работе которую нужно провести чтобы сжать в коде решения огромного количества задач.
2. The point is to universalise the code, in which any additional syntax techniques and shells are simply destructive. It's hard work, but it gets rid of everything superfluous and allows you to evolve all the time reaching new heights.
1. Why do the work when you can make it easy and simple? Why make it difficult when you can make it easy?
2. If you use OOP, universalization is not destructive, but becomes a natural possibility not burdening anything.
1. Why do the work when it can be done easily and easily? Why do something that can be done easily when it is difficult?
2. If you use OOP, then universalisation is not ruinous, but becomes a natural possibility not burdening anything.
We can go on with this argument for a long time. Using the example of a 100-trailing task, I showed my attitude to this solution method. I believe that stupid tasks should not be solved but fixed. If OOP helps those who are weaker in setting tasks correctly and solving them effectively - let it continue helping them. But for people who optimize tasks before they start solving them, OOP may simply not be needed.
We could go on and on with this argument. Using the example of a 100-trailing task, I showed my attitude to this solution method. I believe that stupid tasks should not be solved but fixed. If OOP helps those, who are weaker in raising and solving tasks correctly, let it help them. But for people who optimize tasks before they start solving them, OOP may simply not be needed.
You haven't coded much (probably), OOP is like a breath of air.
Most people code not for interest or self-development, it's their job, and it's the result that counts.
It is not near as convenient, but in terms of speed capabilities, you can get by with pointers alone.
And convenience is a relative concept.
Dmitry, of course using OOP reduces performance a bit. But it is fractions of a percent.
But how OOP increases a programmer's performance!
Here's a small example from one of my projects, it is cutted for perception, but actually there are a lot of other things taken into account.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
For example, let's take .NET, as all the API's consist of classes.
I like the .NET paradigm very much. By the way, there is a great terminal cAlgo, you can write directly in Visual Studio in C#
It's clear that any task can be solved both in OOP-style, with allocation of interfaces, building inheritance hierarchy, declaration of virtual functions, and in pure procedural style - you can even stick everything in one huge function.
The question is in the convenience and efficiency of support.
In MT - the most OOP-appropriate place is the order system. Personally, I have virtual interfaces for "position" and "position components". "Position" is a set of orders in MT4 or a set of positions in MT5. "Position component" is an individual order or an individual MT5 position (hedge or netting).
Here's the actual interface file(Retag Konow, you can appreciate the number of comments compared to the amount of code, and I periodically add them there when I encounter that I don't remember some subtleties. For example, I regularly forget which real objects constitute a "position component". I just don't need to remember it - the Expert Advisor works with components according to the interface, and what's behind that interface in reality doesn't matter. But, I have to return to it during modification - that's why I need the first comment in this file very often):
// СTradePositionI переносимый интерфейс торговой позиции // Позиция состоит из компонент-наследников интерфейса CTradePosComponentI// // Реально для МТ4 имплементацией интерфейса является объект CMT4PositionInfo, для МТ5 - объект CMT5PositionInfo// CMT4PositionInfo представляет из себя массив объектов CMT4OrderInfo, наследников интерфейса CTradePosComponentI.// Фактически это массив МТ4-ордеров.// CMT5PositionInfo представляет из себя массив объектов CMT5PositionInfoCore, наследников интерфейса CTradePosComponentI.// Объект CMT5PositionInfoCore не имеет прямого аналога в МТ5-терминах, это два массива ордеров и сделок, а также структура данных,// имеющуая идентификатор позиции (m_lPosID или POSITION_IDENTIFIER), тикет магик, вид позиции, и так далее, по аналогии с МТ4-ордером,// фактически, массивы ордеров и сделок - это аналоги ордеров и сделок обычной неттинговой МТ5-позиции, а структура данных - относится// к хеджевой позиции, и имеет аналог МТ4-ордера. //// Реально при запросе у позиции компоненты CTradePosComponentI в МТ4 мы получаем указатель на ордер (класс CMT4OrderInfo),// а в МТ5 - на ядро позиции (класс CMT5PositionInfoCore) #include <MyLib\DebugOrRelease\DebugSupport.mqh>
#include <MyLib\Common\MyObject.mqh>
#include <MyLib\Common\CurSymEnum.mq5>
#include <MyLib\Common\TrendEnums.mqh>
#include <MyLib\Trade\TradePosComponentI.mqh>
class CTradePositionI: public CMyObject
{
public:
void CTradePositionI() { SetMyObjectType(MOT_TRADE_POSITION_I); };
virtualvoid ~CTradePositionI() {};
// Выбор существующей позиции. // Указывается магик и символ, по которому выбираются действующие ордера.// Если ulMagic = 0 - выбираются все позиции по всем магикам.// Если ECurrencySymbol = CS_UNKNOWN - выбираются все позиции по всем символам// Если ECurrencySymbol = CS_CURRENT - запрашивается функция Symbol(), и выбираются все позиции по этому символу// Возвращает число компонент позиции внутри позиции (может быть нулевым если позиции нет) или WRONG_VALUE в случае ошибок// Каждая фабрика (наследник CEAPartsFactoryT) имеет одну позицию, которая на каждом CEAPartsFactoryT::OnRefresh()// обновляется в соответствии с магиком и рабочим символом фабрики. virtualint Select(ulong ulMagic = 0,ECurrencySymbol csSymbol = CS_CURRENT) = 0;
virtualuint GetTotalComponents() const = 0; // Получение общего числа компонентvirtualuint GetNumOfComponentsOnDirection(ENUM_POSITION_TYPE etDirection) const = 0; // Получение числа компонент указанного направления (если tdDirection = TD_FLAT - то всех компонент) и интерфейс отдельной компонентыvirtual CTradePosComponentI* GetComponent(uint uiComponentIdx) const = 0;
// Расширенный интерфейс// Функция исследует позицию, и возвращает ее направление:// Если все компоненты - лонги, то вверх.// Если все компоненты - шорты, то вниз.// Если компонент нет - то флет. // Если компоненты обоих типов, то смотрим на флаг bFlatIfBoth. // Если этот флаг установлен - то возвращаем флет.// Если этот флаг сброшен - то смотрим на флаг bConsiderVolume.// Если этот флаг установлен - то сравниваем общие объемы лонгов и шортов. Если сброшен - сравниваем количество лонгов и шортов.// Каких позиций (или объемов) больше - то направление и возвращаем. // Если позиций (или объемов) одинаково - возвращаем флет.// NOTE !!! Функция не проверяет магик и символ компонент !virtual ETrendDirection GetDirection(bool bFlatIfBoth = true,bool bConsiderVolume = true) const = 0;
// Функция ищет внутри позиции компоненту с указанным тикетом. // В случае, если ее нет - возвращается false.// Если компонента найдена - возвращается true, и uiComponentIdx устанавливается на индекс компоненты внутри позиции.virtualbool FindComponentByTicket(long lTicket,uint &uiComponentIdx) const = 0;
};
The file for the trade component interface is as follows (I've already given it above, but I'll repeat it:
// СTradePositionComponentI переносимый интерфейс компоненты торговой позиции #include <MyLib\DebugOrRelease\DebugSupport.mqh>
#include <MyLib\Common\MyObject.mqh>
#include <MyLib\Common\CurSymEnum.mq5>
#include <MyLib\Common\EnumsMT5ForMT4.mqh>
// CTradePosComponentI - компонента позиции. Имеет определенный магик, определенный символ, определенный тикет. // Для МТ4 компонента позиции - это МТ4-ордер.// Для МТ5 компонента позиции - это МТ5-позиция (одна для каждого символа при неттинге, и много для каждого символа при хедже).class CTradePosComponentI: public CMyObject
{
public:
void CTradePosComponentI() { SetMyObjectType(MOT_TRADEPOS_COMPONENT_I); };
virtualvoid ~CTradePosComponentI() {};
// Основной интерфейсvirtuallong GetTPCTicket() const = 0;
virtuallong GetTPCMagic() const = 0;
virtual ECurrencySymbol GetTPCSymbol() const = 0;
virtualENUM_POSITION_TYPE GetTPCType() const = 0;
virtualdatetime GetTPCOpenTime() const = 0;
virtualdouble GetTPCVolume() const = 0;
virtualdouble GetTPCOpenPrice() const = 0;
virtualdouble GetTPCStopLoss() const = 0;
virtualdouble GetTPCTakeProfit() const = 0;
virtualstring GetTPCCommentary() const = 0;
virtualbool IsTPCInUnloss() const { if(GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE) return(false); if(GetTPCType() == POSITION_TYPE_BUY) { if(GetTPCStopLoss() >= GetTPCOpenPrice()) return(true); } else { if(GetTPCStopLoss() <= GetTPCOpenPrice())return(true); }; return (false); };
virtualdouble GetTPDistance() const { if(GetTPCTakeProfit() == 0 || GetTPCTakeProfit() == EMPTY_VALUE) return(EMPTY_VALUE); if(GetTPCType() == POSITION_TYPE_BUY) return(GetTPCTakeProfit() - GetTPCOpenPrice()); return(GetTPCOpenPrice() - GetTPCTakeProfit()); };
virtualdouble GetSLDistance() const { if(GetTPCStopLoss() == 0 || GetTPCStopLoss() == EMPTY_VALUE) return(EMPTY_VALUE); if(GetTPCType() == POSITION_TYPE_BUY) return(GetTPCOpenPrice()- GetTPCStopLoss()); return(GetTPCStopLoss() - GetTPCOpenPrice()); };
};
class CHistoryPosComponentI: public CTradePosComponentI
{
public:
void CHistoryPosComponentI() { SetMyObjectType(MOT_HISTORYPOS_COMPONENT_I); };
virtualvoid ~CHistoryPosComponentI() {};
virtualdatetime GetTPCCloseTime() const = 0;
virtualdouble GetTPCClosePrice() const = 0;
virtualdouble GetTPCProfit() const = 0; // Возвращает профит по исторической позицииvirtualbool IsProfitClosePrice() const = 0; // Возвращает true, если цена зарытия отличается от цены открытия в прибыльную сторону // Возвращает профит исторической позиции для случая, когда бы ход цены (в сторону профита) был бы равен dPriceMove, а лот был бы единичным.// Функция используется для расчета лота для такой же позиции с нужным ходом цены // Рекомендуется отнимать от цены двойной спред.virtualdouble CalculateOneLotProfit(double dPriceMove) const = 0;
};
According to these interfaces - I have both MT4 and MT5 order system implemented for both real and historical orders.
The Expert Advisor requesting a position receives this interface and does not have to take into account the difference between MT4 and MT5 orders. And if a new order type is added or the order of working with them is changed - nothing will change for the Expert Advisor, only the new order type class will be added, and it will also support this interface.
The system made a lot of sense when hedged accounts were introduced. The experts have not changed at all.
Reg Konow, how do you deal with the difference in order types in MT4 and MT5 ?
If a new account type is introduced (in addition to hedge and netting) - what changes will need to be made, and in the same place ?
My opinion is that if you remember all your code to a letter, and you can easily tell why this or that line in your code was written a year ago - then it's true, all these OOP-enhancers are just unnecessary gestures.
OOP is necessary exactly when you do not remember everything when modifying the code - OOP allows to isolate blocks from each other, limit the set of entities available at any given moment to a particular place in the program.
1. It's clear that any task can be solved both in OOP-style, with allocation of interfaces, building inheritance hierarchy, declaration of virtual functions, and in pure procedural style - we can even put everything into one huge function.
The question is in the convenience and efficiency of support.
2. In MT - the most OOP-appropriate place is the order system. Personally, I have virtual interfaces "positions" and "position components". "Position" is a set of orders in MT4 or a set of positions in MT5. "Position component" is an individual order or an individual MT5 position (hedged or netting).
3. Here's the actual interface file(Retag Konow, you can appreciate the number of comments compared to the amount of code, and I periodically add them there when I encounter that I don't remember some subtleties. For example, I regularly forget which real objects constitute a "position component". I just don't need to remember it - the Expert Advisor works with components according to the interface, and what's behind that interface in reality doesn't matter. But, I have to return to it during modification - that's why I need the first comment in this file very often):
The file for the trade component interface is as follows (I've already given it above, but I'll repeat it:
According to these interfaces - I have both MT4 and MT5 order system implemented for both real and historical orders.
The Expert Advisor requesting a position receives this interface and does not have to take into account the difference between MT4 and MT5 orders. And if a new order type is added or the order of working with them is changed - nothing will change for the Expert Advisor, only a new order type will be added, and it will also support this interface.
The system proved to be very reasonable, when hedging accounts were introduced. The experts have not changed at all from that.
4. Reg Konow, how do you deal with the difference in order types in MT4 and MT5 ?
If a new account type is introduced (in addition to hedge and netting) - what changes will need to be made, and in the same place ?
I think that if you remember all your code to a letter, and you can easily tell why this or that line was written in your code a year ago - then all these OOP-enhancers are just unnecessary gestures.
OOP is necessary precisely when you do not remember everything when modifying code - OOP allows you to isolate blocks from each other to limit the set of entities available at any given moment to a particular place in the program.
1. 1. I absolutely agree. The only difference is in the effectiveness of solving tasks in one way or another.
2. I have not really worked with the order system and cannot see any technical problems in its construction. Perhaps there are, but we need a concrete task and then it will become clear how effectively I can solve it without the OOP.
3. From my point of view, the given code sample is simply awful from the readability point of view. No wonder so many comments are required and why you forget its content. Sorry, but that's my subjective first impression. It's just creepy.
Here is an example of readability of my code - the function that defines colour of a control's item:
As you can see, comments are almost unnecessary here. All my code is written in this style. So I know it perfectly well and remember it no matter what size it is.
In my opinion, there is some defect in your problem solving system. The problem itself should be crystal clear and precise, and hence its solution too. If the solution is cloudy and defined by the words "The system proved to be very reasonable" (how can it be reasonable in 270 Kb of code?!), it means that the author has a rough understanding of how his system works. And it's terrible syntax contrivances and superfluous entities in the solution which prevent him from understanding it to the end.
For a solution to be effective, unnecessary entities must be cut off, and the problem must be seen perfectly clearly.
Allow the use of cookies to log in to the MQL5.com website.
Please enable the necessary setting in your browser, otherwise you will not be able to log in.
You are signed in. Two-factor authentication has been disabled. Set it up again and scan a new QR code, or continue with two-factor authentication disabled.
Yes, these units have both. But trust me - they are compressed to the max and versatile, because they solve a wide range of problems.
If there aren't many options, you can get by with ifs and swipes.
Why hasn't anyone decided to argue about "procedural programming with function pointers vs. procedural programming without function pointers"?
If there aren't many options, you can get by with ifs and swipes.
Реter Konow:
1. Дело в работе которую нужно провести чтобы сжать в коде решения огромного количества задач.
2. The point is to universalise the code, in which any additional syntax techniques and shells are simply destructive. It's hard work, but it gets rid of everything superfluous and allows you to evolve all the time reaching new heights.
1. Why do the work when you can make it easy and simple? Why make it difficult when you can make it easy?
2. If you use OOP, universalization is not destructive, but becomes a natural possibility not burdening anything.
1. Why do the work when it can be done easily and easily? Why do something that can be done easily when it is difficult?
2. If you use OOP, then universalisation is not ruinous, but becomes a natural possibility not burdening anything.
We can go on with this argument for a long time. Using the example of a 100-trailing task, I showed my attitude to this solution method. I believe that stupid tasks should not be solved but fixed. If OOP helps those who are weaker in setting tasks correctly and solving them effectively - let it continue helping them. But for people who optimize tasks before they start solving them, OOP may simply not be needed.
We could go on and on with this argument. Using the example of a 100-trailing task, I showed my attitude to this solution method. I believe that stupid tasks should not be solved but fixed. If OOP helps those, who are weaker in raising and solving tasks correctly, let it help them. But for people who optimize tasks before they start solving them, OOP may simply not be needed.
You haven't coded much (probably), OOP is like a breath of air.
Most people code not for interest or self-development, it's their job, and it's the result that counts.
It is not near as convenient, but in terms of speed capabilities, you can get by with pointers alone.
And convenience is a relative concept.
Dmitry, of course using OOP reduces performance a bit. But it is fractions of a percent.
But how OOP increases a programmer's performance!
Here's a small example from one of my projects, it is cutted for perception, but actually there are a lot of other things taken into account.
For example, let's take .NET, as all the API's consist of classes.
I like the .NET paradigm very much. By the way, there is a great terminal cAlgo, you can write directly in Visual Studio in C#
Dimitri, of course using OOP reduces performance a bit. But it's fractions of a percent.
If the number of variants is small, it will slow it down, but if there are too many variants, it will be an advantage.
What's most important, the number of variants in OOP doesn't affect the performance. And in procedural programming, there is a ceiling over your head.
Well, you've made a mess of it...
It's clear that any task can be solved both in OOP-style, with allocation of interfaces, building inheritance hierarchy, declaration of virtual functions, and in pure procedural style - you can even stick everything in one huge function.
The question is in the convenience and efficiency of support.
In MT - the most OOP-appropriate place is the order system. Personally, I have virtual interfaces for "position" and "position components". "Position" is a set of orders in MT4 or a set of positions in MT5. "Position component" is an individual order or an individual MT5 position (hedge or netting).
Here's the actual interface file(Retag Konow, you can appreciate the number of comments compared to the amount of code, and I periodically add them there when I encounter that I don't remember some subtleties. For example, I regularly forget which real objects constitute a "position component". I just don't need to remember it - the Expert Advisor works with components according to the interface, and what's behind that interface in reality doesn't matter. But, I have to return to it during modification - that's why I need the first comment in this file very often):
The file for the trade component interface is as follows (I've already given it above, but I'll repeat it:
According to these interfaces - I have both MT4 and MT5 order system implemented for both real and historical orders.
The Expert Advisor requesting a position receives this interface and does not have to take into account the difference between MT4 and MT5 orders. And if a new order type is added or the order of working with them is changed - nothing will change for the Expert Advisor, only the new order type class will be added, and it will also support this interface.
The system made a lot of sense when hedged accounts were introduced. The experts have not changed at all.
Reg Konow, how do you deal with the difference in order types in MT4 and MT5 ?
If a new account type is introduced (in addition to hedge and netting) - what changes will need to be made, and in the same place ?
My opinion is that if you remember all your code to a letter, and you can easily tell why this or that line in your code was written a year ago - then it's true, all these OOP-enhancers are just unnecessary gestures.
OOP is necessary exactly when you do not remember everything when modifying the code - OOP allows to isolate blocks from each other, limit the set of entities available at any given moment to a particular place in the program.
Well, you've made a mess of it...
1. It's clear that any task can be solved both in OOP-style, with allocation of interfaces, building inheritance hierarchy, declaration of virtual functions, and in pure procedural style - we can even put everything into one huge function.
The question is in the convenience and efficiency of support.
2. In MT - the most OOP-appropriate place is the order system. Personally, I have virtual interfaces "positions" and "position components". "Position" is a set of orders in MT4 or a set of positions in MT5. "Position component" is an individual order or an individual MT5 position (hedged or netting).
3. Here's the actual interface file(Retag Konow, you can appreciate the number of comments compared to the amount of code, and I periodically add them there when I encounter that I don't remember some subtleties. For example, I regularly forget which real objects constitute a "position component". I just don't need to remember it - the Expert Advisor works with components according to the interface, and what's behind that interface in reality doesn't matter. But, I have to return to it during modification - that's why I need the first comment in this file very often):
The file for the trade component interface is as follows (I've already given it above, but I'll repeat it:
According to these interfaces - I have both MT4 and MT5 order system implemented for both real and historical orders.
The Expert Advisor requesting a position receives this interface and does not have to take into account the difference between MT4 and MT5 orders. And if a new order type is added or the order of working with them is changed - nothing will change for the Expert Advisor, only a new order type will be added, and it will also support this interface.
The system proved to be very reasonable, when hedging accounts were introduced. The experts have not changed at all from that.
4. Reg Konow, how do you deal with the difference in order types in MT4 and MT5 ?
If a new account type is introduced (in addition to hedge and netting) - what changes will need to be made, and in the same place ?
I think that if you remember all your code to a letter, and you can easily tell why this or that line was written in your code a year ago - then all these OOP-enhancers are just unnecessary gestures.
OOP is necessary precisely when you do not remember everything when modifying code - OOP allows you to isolate blocks from each other to limit the set of entities available at any given moment to a particular place in the program.
1. 1. I absolutely agree. The only difference is in the effectiveness of solving tasks in one way or another.
2. I have not really worked with the order system and cannot see any technical problems in its construction. Perhaps there are, but we need a concrete task and then it will become clear how effectively I can solve it without the OOP.
3. From my point of view, the given code sample is simply awful from the readability point of view. No wonder so many comments are required and why you forget its content. Sorry, but that's my subjective first impression. It's just creepy.
Here is an example of readability of my code - the function that defines colour of a control's item:
As you can see, comments are almost unnecessary here. All my code is written in this style. So I know it perfectly well and remember it no matter what size it is.
In my opinion, there is some defect in your problem solving system. The problem itself should be crystal clear and precise, and hence its solution too. If the solution is cloudy and defined by the words "The system proved to be very reasonable" (how can it be reasonable in 270 Kb of code?!), it means that the author has a rough understanding of how his system works. And it's terrible syntax contrivances and superfluous entities in the solution which prevent him from understanding it to the end.
For a solution to be effective, unnecessary entities must be cut off, and the problem must be seen perfectly clearly.