Getlasterror mql4 коды ошибок

3.0 Программируем простой MQL4 советник по системе «Монетка»

обучение mql4

Если вы задавались вопросом «Как написать советник на языке программирования MQL4», то данный пост создан именно для вас. Сегодня мы будем создавать самый простой из всевозможных советников для МТ4, который будет определять незамысловатое условие на вход, открывать ордер и модифицировать его цели.

Алгоритм программирования советника на MQL4

Выше представлена схема процесса работы торгового робота, который мы планируем написать. Любой советник должен иметь как минимум три функции обработки событий:

OnInit()

Она генерируется только один раз за время работы советника в самом начале. Нужна, чтобы внутри нее определить, рассчитать и задать те переменные и массивы данных, которые не нуждаются в дальнейшей корректировке по мере обновления тиков. То же самое касается и графических объектов. В советнике раздел OnInit выполняет ту же роль, что мы проходили в теме создания первого индикатора.

OnDeinit()

Функция вызывается советником только один раз перед непосредственным удалением его с графика. Она используется также и в индикаторах. Раздел OnDeinit нужен, чтобы подчистить график после советника, обнулить глобальные переменные и выдать окончательный расчет или текст пользователю. Более подробно мы ее проходили при создании первого индикатора.

OnTick()

Данная функция новая в наших уроках. Раздел OnTick генерирует события исключительно для экспертов и не может быть вызвана в индикаторах или скриптах. Ее тип данных void и набор параметров отсутствует. По своей логике работы она схожа с функцией для индикаторов OnCalculate, только она не возвращает никакого значения после завершения. Задача у нее одна — запускаться каждый новый тик и проходить циклом весь написанный код в ней от начала до конца. Так как любой советник должен проверять условия для входа/выхода из рынка, считать количество открытых ордеров и выполнять их сопровождение, то можно уверенно сказать, что функция OnTick является самой важной в коде любого эксперта.

Продолжим разбирать алгоритм работы. Вначале советник инициализируется. Далее запускается функция OnTick, в которой выполняются все дальнейшие действия. Для данного советника сначала необходимо проверить наличие уже открытых им ордеров. Если они есть — дальнейший расчет и поиск условия на вход не выполняются, потому что в рынке у нас должен быть только один ордер за раз. Если же открытых сделок нет, то идет определение направления будущей позиции. В зависимости от него запускается пользовательская функция на открытие Buy или Sell ордера. Если по какой-то причине сделка не смогла открыться, расчет возвращается назад в функцию OnTick, чтобы попробовать выставить ордер снова. Если же ордер открылся, то он модифицируется (выставляется Тейк-Профит и Стоп-Лосс). На этом алгоритм заканчивает свою работу по работе с ордерами, потому что счетчик новых ордеров уже будет учитывать этот открывшийся ордер, делая проверку каждый тик. И только после того, как ордер закроется по достижению своей цели (ТП или СЛ), цикл проверки условия на открытие ордера запустится снова. Функция OnDeinit запустится только тогда, когда вы удалите советник с графика.

Наш код, конечно, не будет выглядеть точь-в-точь как эта схема, но думаю, что принцип его написания вам понятен.

Торговая система «Монетка»

форекс тс монетка

Когда перед нами стоит вопрос «как создать Форекс советник», то в первую очередь в голову приходит мысль о торговой системе, заложенной в нем, логике открытия ордеров. Так как в этом уроке не стоит цель создать так называемый на сленге «Грааль», то для получения опыта в написании первого эксперта мы возьмем на вооружение самую простую ТС, которую только можно выдумать.

Период советника установим М15. Мы будем входить в рынок по воле случая, или, если хотите, удачи. Мы начнем условно подкидывать монетку и смотреть на результат этого несложного действия. Орел или Решка — только два исхода событий будет у советника. Вариант «ребро» в данном случае не рассматривается ?

Зачем использовать такую простую систему? Чтобы понять, что произойдет в результате этого эксперимента и ответить себе на вопрос: можно ли заработать на Форекс входя в рынок наобум? Получится ли прибыльно торговать не имея четко спланированной торговой системы?

Проверка советника на ошибки: GetLastError()

При написании советника (как и при его использовании) очень важно следить за возможными ошибками в коде. Речь идет не об ошибках компиляции, их вы можете увидеть во вкладке «Ошибки» окна «Инструменты». Разговор о скрытых ошибках, которые проявляют себя во время тестирования или работы советника на реальном счете. Проверку на эти ошибки нужно делать как минимум один раз за тик в функции обработки событий OnTick. Как максимум — в каждой вашей пользовательской функции.

Чтобы получить номер возможной ошибки, нужно вызвать функцию GetLastError(). Она имеет тип int и возвращает целое число, значение системной переменной _LastError. Тут нужно обратить внимание, что на языке MQL4 после вызова функции GetLastError ее значение обнуляется и повторный вызов ее в том же месте кода вернет значение 0, поэтому ее значение нужно сохранять в отдельную переменную.

Язык MQL различает как минимум 150 разных ошибок. Соответственно каждый возвращаемый номер имеет свою расшифровку. Ноль значит это ошибки нет и все отлично, 134 значит, что недостаточно денег на счете и т. д.

Ordersend error 130 как исправить

Очень много подобных вопросов мне приходит. Поэтому публикую таблицу кодов ошибок. Например посмотрев вышеописанную ошибку error 130 становится понятно, что функция OrderModify пытается изменить стоп-лосс или тейк-профит слишком близко к текущей цене.

Коды ошибок

GetLastError() — функция, возвращающая коды ошибок. Кодовые константы ошибок определены в файле stderror. mqh. Для вывода текстовых сообщений следует использовать функцию ErrorDescription(), определенную в файле stdlib. mqh.

Коды ошибок, возвращаемые торговым сервером или клиентским терминалом:

Значение Описание
Нет ошибки
1 Нет ошибки, но результат неизвестен
2 Общая ошибка
3 Неправильные параметры
4 Торговый сервер занят
5 Старая версия клиентского терминала
6 Нет связи с торговым сервером
7 Недостаточно прав
8 Слишком частые запросы
9 Недопустимая операция нарушающая функционирование сервера
64 Счет заблокирован
65 Неправильный номер счета
128 Истек срок ожидания совершения сделки
129 Неправильная цена
130 Неправильные стопы
131 Неправильный объем
132 Рынок закрыт
133 Торговля запрещена
134 Недостаточно денег для совершения операции
135 Цена изменилась
136 Нет цен
137 Брокер занят
138 Новые цены
139 Ордер заблокирован и уже обрабатывается
140 Разрешена только покупка
141 Слишком много запросов
145 Модификация запрещена, так как ордер слишком близок к рынку
146 Подсистема торговли занята
147 Использование даты истечения ордера запрещено брокером
148 Количество открытых и отложенных ордеров достигло предела, установленного брокером.

Коды ошибок выполнения MQL4 программы:

GetLastError() — функция, возвращающая коды ошибок. Кодовые константы ошибок определены в файле stderror. mqh. Для вывода текстовых сообщений следует использовать функцию ErrorDescription(), определенную в файле stdlib. mqh.

Коды ошибок, возвращаемые торговым сервером или клиентским терминалом:

Я пытаюсь вставить takeprofit и stoploss аргумент в моей SendOrder() функции, но я получаю следующее сообщение об ошибке:

A) Полностью соответствуют MQL4 OrderSend() требованиям синтаксиса

B) Ошибка 130: == "недействительная остановка"

Вы должны проверить с вашим брокером несколько деталей:

C) Хорошая практика не назначать в extern итераторных-переменных

Getlasterror mql4 коды ошибок

Will I be able to display error messages in different languages.

void PASCAL wfc_get_error_string( DWORD error_code, CString& error_string )

I often wrap it in another function that looks more like:

I will try to be brief

Re: Your points 1. and 2: MyFunction (Vanilla version) does not return locally declared CWin32Error but its copy.

Correctitude: In C++, user-defined types ought to be treated at par with built-in types. Remember: If you return an int variable, you are still asking the compiler to produce code to copy four bytes. For CPoint : eight bytes. For const char* allocated on the heap (and not locally declared): four bytes—plus other code you are bound to write to check its lifetime elsewhere in the program to avoid runtime failures. For CWin32Error : four bytes plus just a few inlined code steps involving just one call to InterlockedIncrement(). InterlockedIncrement(), handled right in the Win32 subsystem rather than after a contex switchover to kernel mode, is very fast.

No function returns are ever free—for user-defined types or built-in types. But, overall, the cost involved in returning CWin32Error object by value, rather than an int value, carries so small an extracost that it can be even smaller than the overhead of stack-frame maintenance code introduced due to an extra function you write elsewhere to check the health of an on-the-heap or a static object.

So, there always is cost. The issue is: how do you organize it. CWin32Error urges to exploit the C++ language features and so lets you organize in the cleanest way with no extra overheads.

Re: Your concerns in 3. and 4.: That’s why CWin32Error copy constructor and assignment operators do not call GetLastError(). Please see the class comments and documentation for further details.

CWin32Error guaruntees—I repeat guaruntees—never to throw an error when everything is OK. Two interpretations of this statement: (i) It never calls an extra GetLastError(). If at all necessary (which I doubt), you can always use CWin32Error::ReGetLastError member function. (ii) To be accurate, you throw CWin32Error. CWin32Error does not raise any exception on its own (which is something that some other people may not like )

Re: Your point 5: The sample usage is just that: sample. It does not cover every usage scenario. For the case you write about, the code would look something like:

Hope this clarifies.

Bottomline: CWin32Error can be used without hesitation in all cases.

Good points, Sardurkar. Tells me you are seriously thinking of using CWin32Error—which is very welcom. Feel free to voice your other concerns about CWin32Error too.

Microsoft’s already ahead of you there, with the Compiler COM Support’s _com_error class.

It’s OK to use _com_error even if you aren’t writing COM software. Essentially, it takes any error you would normally call GetLastError() on, or any HRESULT from a COM call, and will give you the text equiv. of the error, all with just one call.

It works like this:

DWORD dwLastError = ::SomeSDKFunction(. );

That’s it. The class can be used just by #including <comerror. h> in your STDAFX. H file, and it can also be thrown in an exception.

CWin32Error compared with _com_error

Absent method calls, the CWin32Error code looks prettier to my eyes.

Beauty is in. Analysis

Analysis

1. Time Cost

To repeat: CWin32Error is faster.

1.2. To be fair: After commenting out the szDesc2 and szDesc3 defining lines in the above test, both classes
are almost equally fast
(differing by less than 1% in actual execution tests in the release build).

1.3 The real determinant of the execution time appears to be the number of times FormatMessage is called.

Algorithmic Rationale of Time Cost

3. Space Cost

4. Conclusion of Cost Analysis

5. The Road Behind

5.0 The main purpose—and hence the class design—differs.

6. An Exercise Ahead

Special thanks to Briant Hart for galvanizing me into analysis. I wouldn’t have done it myself!

Ajit Jadhav

«Can we still be friends?»

Your project today is your great-grandchildrens’ «ancestor clock.»

First let me say I love classes like CWin32Error. Simplifying the little things that we encounter constantly is great. But there are a couple issues with how your using it.

For example given your second function:

CWin32Error MyFunction( void );

Yes your class is much more efficient than _com_error the best choice of all is still going to be:

Also, in general you never want to catch exceptions by value. Yes it’ll happen when throwing/catching simple types but your class is *not* a simple type nor a replacement for one. So when catching CWin32Errors you’d still want to:

Thanks for posting your code! CWin32Error has some very nice features.

Thanks for your thoughtful comments! I really appreciated your comment.

2. Let me reply on your second point first (ie. catching by ref). This is an issue independent of CWin32Error, and really requires a separate discussion of catching, throwing, and especially, rethrowing. Yes, I agree completely that catching by ref involves much less cost, especially as long as intermediate throw s too have passed the reference to the original object. But this is really at the discretion of the programmer, and so, a somewhat separate issue.

The sample scenario in CWin32Error is just an advertisement to show that even a novice programmer can’t incur too many costs with CWin32Error—smart copying will kick in.

2. About your first point (i. e. the heap usage in normal times (no-error) at runtime). Good observation! The point is well taken.

Soon after posting, I started thinking of an upgrade to further improve runtime conditions precisely on the lines you mentioned. But I realized it only after posting the code. (That always happens!!). Please wait a few days time to see the planned upgrade.

If interested here’s the descriptive preview of what it will have.

Warning: Being descriptive, it’s a bit lengthy. Also very tentative. (I am not sure I really need the extra static variable I mention in the following description). Anyway, check out the CWin32Error page within a week for the upgrade.

The specific solution I am currently thinking is to introduce a class static member variable to hold the error code in normal times (error == 0). Then, there can be hungry capture of only the numeric code in construction or in ReGetLastError(). The fallout (after such upgrade) will be:

On the Plus side:
—————-
(i) For Normal Execution (member error == 0 ) at Runtime: CWin32Error will then aovid hitting the heap altogether.

Thus, CWin32Error will be costlier to calling ::GetLastError() only by an extra if condition, testing only equality of int variables. For a program that run completely normally, this would mean, (a) no new[], (b) no delete[], (c) not even a single InterlockedXXX() call introduced by CWin32Error during the entire program execution!

On the Minus Side:
——————
An extra space cost of a static member variable of unsigned int type. That is, 4 static bytes (only). Being static, the space cost will be constant, irrespective of the # of CWin32Error objects at runtime.

It seems to me that the plus side far outweighs the minus side. So, please check out the CWin32Error page later this week for the above upgrade.

Ok catching exceptions is hardly what your post is about so I’ll leave off any lengthy discussion of it but.. I will go out on a limb and say there is no reason to catch anything, other than a simple type, by value. It’ll only lead to problems. So it’s at the discretion of the programmer only because the compiler allows it.

Almost all my work related programming involves multi-threaded server applications so I cringe anytime anyone mentions statics. It takes a lot of work to make a class with read/write static variables thread safe and efficient.

More than that however just make sure you’ve thought out how your class is going to be used. It’s tempting to envision using CWin32Error as you did in your second example:

if( AlertUser(dwErr))
<
AfxMessageBox(CWin32Error(dwErr));
>

// doing something in a loop that fails.

if( AlertUser(dwErr))
<
AfxMessageBox(CWin32Error(«failed during %d try at doing Foo»,loop, dwErr));
>

Another thought would be to provide a way to extract error messages without hitting the heap at all. Something like:

Anyway, the point is to avoid trying to add to many bells an whistles. Think about how you’ll use the class most effectively and design it to maximize that core functionality with a minimal interface. You’ll end up with an effective, useful class, that you return to time and time again.

A few comments right here. More, later. Perhaps offline discussion by email??

— The core idea behind this class: CWin32Error objects as first-class entities indicating runtime status. (Perhaps the class-name is a misnomer, but I wanted to keep it associated with ::GetLastError to spread usage.)

By core idea, CWin32Error is not just a DWORD number, not just a TCHAR string, not just a conversion functionality, but an integration of them all. A status-indicating thing. I just happened to take the view that the Win32 API seems to artificially separate the two (to maintain C-compatibility); and that in C++ programming, a char* string should be as easily available as the DWORD is (without losing the convenience and the small runtime cost of the DWORD). That was the core idea. Perhaps not always possible cost-wise. But worth getting as close to DWORD usage as is possible.

So, whatever you think of doing with a DWORD, it should be possible to do the same with the object. For example, TRACEing, returning, throwing exceptions, as a member variable in the class, as true state-indicating objects (using app-private FACILITY codes) in a state-transition map, anything else.

That in turn meant making the class time-efficient in terms of FormatMessage calls it makes, and space-efficient in terms of its sizeof value and avoiding multiple string buffers as far as possible. Hence, the rest of the class code involving smart copying and meta-mem management.

But to think of a member function returning a char* given a DWORD would be somewhat off the core of the C++ idea—it will be closer to the C-way of thinking, not C++.

Actually, any DWORD => char* conversion should be seen as only a part of the class. Per core idea: you have this error/status object, and you probe it for whatever reason, and it will return what it knows about the status and/or health of the program in that context. You can be a user (returns a human readable, standard string message) or a programmer (returns a variable-address that is TRACE-compatible) or the program at run-time (captures and returns error-code numbers with negligible overheads).

— The Received Opinion varies a lot for throwing user-defined types in addition to built-in types. For example, the standard C++ includes «exception» class, and Stroustrup advocates thinking exception first. On the other hand, there can be situations where exception frames and unwinding cost and/or semantics is not most desirable. In these later cases, CWin32Error can be used in the simple object sense.

— Ditto for retvals. A lot of folks in quite a few projects I worked on seemed to require something like returning status-strings! Returning status strings seems like a natural thing to think for many programmers—and not all of them are recent converts from VB. If they can have smart-copies.

— About multi-threading and static member variables. Yes of course. Any static members, if at all introduced, will be purely readonly.

Looks like statics (a small array of them, in fact), will be inevitable under the constraints: viz. that CWin32Error will not raise exceptions on its own. Here, I am aware that memory for exception frames and objects is guarunteed by the C++ language. But many may deliberately disable exception-handling support in the code generation (e. g. ATL COM projects.)

Mem allocation, and even FormatMessage can fail internal to the class. Yet, by core-idea, the user-programmer will not check on DWORD before using the const char* conversion. Now, rather than introduce static allocation into the program from back-door via macro substitution:
if (msg string is not available) return _TEXT(«class internal error message»)
it would be better to introduce static readonly variables explicitly. There seems to be no other choice when memory allocation the internal buffers fail, and yet the user-programmer has fully relied on the const char** operator in his code.

— Hiding copy ctor, = operator : Interesting idea.

— Extracting into user-providing buffer. This is a v. good way of looking at the class, and might increase its practical appeal. Sure will include this functionality.

2B in this case: Supporting printf-style format strings turns out to be a desirable revision but a big one. Variable sized args, preproc defines and format string interpretation (UNICODE/OLE2ANSI. ), processing failure possibilities, MC-compiled message resources and their DLL hInstance, etc. Perhaps this is better served by a small cluster of classes than a single class. TBD: in future.

— About minimal i/face: Yes. I am reminded that famous quote (don’t remember who said it): Interface design attains perfection not when there is nothing else left to add, but when there is nothing else left to take away.

Thanks again for your interest. Unbelievably, writing this smallest of classes turns out to be such a big-time headache! Thoughtful comments like yours help a lot! And I seem unable to refrain from writing loooong messages!

But the Win32 status value really is just a DWORD. Worse than that it’s actually just a DWORD *sized* value. In some instances it’s an int, in some a long. And to further complicate matters it’s not always associated with ::GetLastError(). The registry functions for exmaple don’t set ::GetLastError() instead they directly return their error value. (as a long).

I would argue that it’s much more desirable in the C++ modeling world to separate the two simply because they do completly different things. The status value allows us to alter program logic and respond to error conditions, the explanatory text allows us to format nice error messages.

I’m not sure what you mean by a status string. Do you mean they want you to return an LPCTSTR that they’re going to parse to determine if the function succeeded or failed? If so just take them by the hand and lead them to the padded room for shock therapy.

Would you ever routinly format an error message before being certain there was an error? I can’t think of a single scenario.

1. About CWin32Error and DWORD:

* CWin32Error-defined DWORD conversion adequately provides for all DWORD usages, including the registry API that has been mentioned on this article a couple of times. The usage is so simple I actually left out discussing it in the main article.

I wonder how people miss it except may be by deliberate overlooking. If that, neither argument nor better C++ code is going to help, anyway. Barring that, here’s an example:

What permits this? The fact that ERROR_SUCCESS and ERROR_MORE_DATA and all the other ret vals are all basically defined in the same file: WinError. h (or Error. h). Irrespective of whether they set thread variable or not.

* int, long, DWORD. Gosh! I am talking Win32 here! Neither Win3.1 nor IA64!

* You can use CWin32Error to alter status logic. Obvious. If not, pl. let me know.

2. The thing preceding shock therapy ( )
* No, they seriously entertain the idea that in big multi-location, multi-teams projects, it’s easier to fix the source of error, blame, not to mention bugs, if the source-code itself carried the ability to show status. If the feature is built right down to the class-level granularity. But at no appreciable extra cost. They stand to benefit by using a class like CWin32Error. Whether they will choose to use it or not takes us to a completely different realm.

3. Parsing-related apprehensions:
* Parsing is not necessary.
* Think again about app-private FACILITY. It’s there. People simply don’t use it (Just like MC-dlls. People don’t even know about it, except as in localization issues).

4. Pattern:
Thanks for the tip. I seem only dimly aware of the book. I read Gang of Four (also have the CD). But not the one you mention.

I have virtually lost all my enthusiasm about both patterns and UML—for that matter, anything to do with large-scale architectural thinking. The trouble is, I am a contract software engineer, and people don’t always (i) use patterns or (ii) incorporate a contractor’s suggestion when it impinges at the architectural level. I do get a lot of freedom at the class implementation level, but should not expect more. So, through first hand experience I have learnt how to operate at sub-pattern level. This being America, I anticipate this thing to go on until my residency status changes, or people change, whichever is earlier, if possible! (Yep, there seems to be a lot of parsing going on in here!)

So, for the time being, if you would like to see external polymorphism applied to CWin32Error, I am afraid, you will have to present pseudo-code/code-fragments that show how to do it.

(BTW, which geographical area are you in? How’s the market for contractors currently in there?)

Relax I’m not deliberately overlooking the DWORD conversion, in fact I’m not overlooking it at all. You where talking about how the status value and text where «artificially separate.» This lead me to believe you where trying to model ( in a C++ object sense of the word ) a Win32 status value. I was trying to show that from a conceptual stand point Win32 doesn’t have a single clean error reporting paradigm.

Again, with regards to ‘status logic’ and status reporting I’m trying to touch upon how the separation of the two concepts in the Win32 API could affect how you develop a C++ object model. Here’s a more concrete example of what I mean. Pardon the length..

Источники:

https://www. davinci-fx. com/mql-first-ea/

https://teh-fed. ru/ordersend-error-130-kak-ispravit/

https://www. codeproject. com/Articles/1025/Do-Not-Call-GetLastError

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: