100% found this document useful (3 votes)
2K views1,665 pages

MQL 4

This document provides an overview and summary of the MQL4 programming language and features: - MQL4 is a built-in programming language for creating automated trading strategies and Expert Advisors in MetaTrader trading platforms. It allows for automated trading management and implementation of trading strategies. - The document describes the different types of programs that can be created with MQL4 - Expert Advisors, indicators, scripts, libraries and include files - and their purposes and storage locations. - It provides a brief guide to MQL4 functions, operations, reserved words and other language elements to help users learn and use the language.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (3 votes)
2K views1,665 pages

MQL 4

This document provides an overview and summary of the MQL4 programming language and features: - MQL4 is a built-in programming language for creating automated trading strategies and Expert Advisors in MetaTrader trading platforms. It allows for automated trading management and implementation of trading strategies. - The document describes the different types of programs that can be created with MQL4 - Expert Advisors, indicators, scripts, libraries and include files - and their purposes and storage locations. - It provides a brief guide to MQL4 functions, operations, reserved words and other language elements to help users learn and use the language.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

MQL4 Reference

MQL4 Reference
MetaQuotes Language 4 (MQL4) is a built-in language for
programming trading strategies. This language is
developed by MetaQuotes Software Corp. based on their
long experience in the creation of online trading
platforms. Using this language, you can create your own
Expert Advisors that make trading management
automated and are perfectly suitable for implementing
your own trading strategies. Besides, using MQL4 you can
create your own technical indicators (custom indicators),
scripts and libraries.
MQL4 contains a large number of functions necessary for
analyzing current and previously received quotes, and has
built-in basic indicators and functions for managing trade
orders and controlling them. The MetaEditor (text editor)
that highlights different constructions of MQL4 language is
used for writing the program code. It helps users to
orientate themselves in the expert system text quite
easily.
The brief guide contains functions, operations, reserved
words, and other language constructions divided into
categories, and allows finding the description of every
used element of the language.
Programs written in MetaQuotes Language 4 have
different features and purposes:
Expert Advisor is a mechanical trading system linked
up to a certain chart. An Expert Advisor starts to run
when an event happens that can be handled by it:
events of initialization and deinitialization, event of a
new tick receipt, a timer event, depth of market
changing event, chart event and custom events. An
Expert Advisor can both inform you about a possibility
to trade and automatically trade on an account sending
orders directly to a trade server. Expert Advisors are
stored in terminal_directory\MQL4\Experts.
Custom Indicator is a technical indicator written
independently in addition to those already integrated
into the client terminal. Like built-in indicators, they
cannot trade automatically and are intended for
implementing of analytical functions only.
Custom indicators are stored in
terminal_directory\MQL4\Indicators
Script is a program intended for a single execution of
some actions. Unlike Expert Advisors, scripts do not
process any actions, except for the start event (this
requires the OnStart handler function in a script).
Scripts are stored in terminal_directory\MQL4\Scripts
Library is a set of custom functions intended for
storing and distributing frequently used blocks of
custom programs. Libraries cannot start executing by
themselves.
Libraries are stored in
terminal_directory\MQL4\Libraries
Include File is a source text of the most frequently
used blocks of custom programs. Such files can be
included into the source texts of Expert Advisors,
scripts, custom indicators, and libraries at the
compiling stage. The use of included files is more
preferable than the use of libraries because of
additional burden occurring at calling library functions.
Include files can be stored in the same directory as a
source file - in this case the #include directive with
double quotes is used. Another place to store include
files is terminal_directory\MQL4\Include, in this case
the #include directive is used with angle brackets.
 
© 2000-2023, MetaQuotes Ltd
MQL4 Reference / MQL5 features

New MQL5 language features


The current version of the trading platform is most well-
known among traders thanks to its user-friendly interface, a
variety of technical analysis tools and the integrated MQL4
language. In the fourth version, MQL4 received the С
language syntax allowing users to develop professional-level
algorithmic trading programs. At the same time, transition
to the new language did not require much effort from
traders allowing MQL4 to gain world leadership in terms of
the amount of developed indicators and trading robots.
Let us congratulate you on your excellent choice and offer
you a brief tour on the MQL5 fifth generation language:
Manage price charts directly from an MQL5 program
adjust colors, develop control panels, display custom
symbols and move charts beyond the terminal.
Try indicators featuring 12 new drawing styles, 512
buffers and direct calculation of values with indexation
from past to future.
Debug Expert Advisors not only on charts but also in the
multi-currency tester. Now the tester's trading logic
matches that of online trading allowing you to test a
combined strategy on all the necessary currency pairs
simultaneously in one pass.
 
High speed of MQL5 language
The MQL5 execution speed is comparable to that of С++
applications, while MQL5 programs work up to 20 times
faster than MQL4 ones. This is proved by the execution
results of standard tests on MQL4, MQL5 and C++. The lower
the bar, the less time (in milliseconds) spent on execution
and the better the result. The tests have been conducted on
Windows 10 (build 17763) x64, Xeon  E5-2630 v4 @ 2.20GHz,
Memory: 65457 Mb.

The new asynchronous trading operations provide you with


algorithmic trading features that were previously available
only to a handful of professional traders. If you develop
MQL5 robots, you do not need third-party connections to
exchange protocols. Besides, you do not need to place your
terminals as close to a broker as possible. Simply rent a
built-in VPS and send your EA to trade there directly from
the terminal. Low network costs, high Depth of Market
refresh rates and asynchronous order sending accelerate
trading operations dozens of times. Such acceleration can be
a key factor in intraday trading.
Event-based trading robots
The MQL5 language has become completely event-driven.
The entire trading logic can now entirely be based on
handling incoming events. The OnTick() handler allows you
to analyze the tick flow for any symbol, receive an entry
signal and send an asynchronous trading request. After a
fraction of a millisecond, the program execution continues,
and you are ready to conduct a deal on another symbol. You
waste no time waiting for the operation result since data on
trading operations are received and handled in another
handler OnTradeTransaction(). This allows you to write
trading algorithms with maximum reliability and efficiency.
Events are used not only for trading, but also for other
tasks:
receiving the Depth of Market updates, analyzing
price/volume changes in trade requests and trading
based on analysis results;
creating auxiliary analytical tools and control panels for
MQL5 programs;
managing optimization and visualization of obtained data
in real time.
Testing multi-currency EAs
MQL5 allows you not only to develop EAs that trade on
multiple symbols simultaneously, but also to test them in
the strategy tester. The Sleep() function, timer events and
special events for working in the optimization mode are
handled correctly while working in the tester. EAs can be
debugged and profiled in visual mode.
Explore MQL5 language features and develop game-changing
algorithmic trading programs!
MQL4 Reference / MQL5 features / Charts

MQL5 charts
The new generation platform has two times more
timeframes (21 vs 9), as well as the precise time scale. Now
graphical objects are not necessarily linked to bars. Object
anchors can be placed in any position between the chart
bars. Moreover, when switching between timeframes, the
accurate positioning of the control points of the object is
preserved. New built-in indicators and analytical tools have
also been added.
The new OBJ_CHART graphical object is most notable in
terms of the complex technical analysis. It allows creating
an unlimited number of nested charts, set all the necessary
properties (color scheme, timeframe, symbol) and even
impose indicators on them. Thus, a usual price chart can be
turned into a complex analytical tool by quickly switching
between symbols and timeframes in a single mouse click.
If you use several monitors for trading, then you will
certainly appreciate another advantage of the new platform
floating chart windows. Any symbol chart can now be
detached from the terminal window and moved to the
necessary monitor. An example of such a chart is shown in
the image. Add indicators and an EA with the graphical
panel to a floating chart to get a real trading control center.
Floating windows can also be moved and resized from MQL5
programs using the chart properties (CHART_IS_DOCKED and
others).
The third distinctive feature of the fifth generation platform
is the ability to create custom symbols or synthetic indices.
To do that, simply enter the calculation formula or
download files with minute bars or tick history. You can also
work with custom symbols using MQL5 language. The
appropriate functions allow you to automate collecting and
preparing history data, open charts and update them in real
time, as well as test your EAs in the strategy tester using
custom symbols.
Explore MQL5 language features and take your programming
skills to the next level.
MQL4 Reference / MQL5 features / Indicators

MQL5 indicators
In the new terminal, the number of built-in technical
indicators has been increased from 30 to 38, while the
number of drawing styles of custom indicators has been
increased 3 times from 6 to 18. Now custom indicators are
able to use up to 512 indicator buffers. A separate color on
each bar can be specified for color styles.

The MQL5 functions allow setting colors and display of


individual chart elements, adding the Chart object
(OBJ_CHART) to a symbol chart from any other
symbol/timeframe and imposing other indicators on it. In
order to create a user interface, you can also draw on the
canvas, manage an indicator using the keyboard and mouse,
and much more.
Thus, with МQL5, the possibilities for developing indicators
and any technical analysis tools are endless.
MQL4 Reference / MQL5 features / Expert Advisors

MQL5 Expert Advisors


The new platform allows testing Expert Advisors (EAs) on
real ticks, while entire trading environment is reproduced as
accurately as possible and ticks are synchronized across all
used instruments up to milliseconds. The strategy tester is
multi-threaded, which means you can use all local computer
CPU cores, local network agents and MQL5 Cloud Network
speeding up the development and debugging of trading
strategies dozens and hundreds of times.

The new tester is also a multi-asset tool, which means that


you are able to test strategies working on multiple financial
instruments simultaneously. When running multi-currency
testing, all necessary history for all used symbols is
automatically downloaded from the trade server, while the
timer events and the Sleep() function calls are handled
correctly. Thus, you develop the same code both for testing
and for real trading. There are no restrictions on the part of
the tester, and you do not have to test each multi-currency
EA instrument separately.
The fifth generation platform accelerates trading: MQL5
compiler aggressively optimizes the obtained EX5 executable
code, the OrderSendAsync asynchronous function is
executed in fractions of a millisecond, orders are processed
on a trade server in no time, while price and Depth of
Market updates are delivered to the terminal without delay.
In order to trade on exchange symbols, you will need tick
functions and access to the Depth of Market.
The MQL5 language is now as fast as С++, while MQL5
programs work up to 20 times faster than MQL4 ones since
all functions of the new language are developed taking into
account the capabilities of modern processors and code
profiling results. If necessary, you can further accelerate the
calculations using OpenCL functions. The MetaEditor
development environment supports the OpenCL interface for
using the power of modern video cards.
 
MQL4 Reference / MQL5 features / MQL5 functions

List of MQL5 language functions


All MQL5 functions by sections
Section Description
Common Functions General functions not
included into any of the
specialized groups
Array Functions Functions for working with
arrays. Four-dimensional
arrays are allowed at most
Conversion Functions Functions for converting
data from one format to
another
Math Functions A set of mathematical and
trigonometric functions
String Functions Functions for working with
string type data
Date and Time Functions for working with
datetime data (an integer
representing the number of
seconds elapsed since 00:00,
January 1, 1970)
Account Information Functions for receiving data
on the current trading
account
Checkup Functions for receiving the
current state of the client
terminal
Section Description
Event Handling Functions for handling
predefined MQL5 events
Market Info Functions for receiving
market status data
Economic Calendar Functions for working with
economic calendar events
Timeseries and Indicators Functions for working with
Access timeseries and indicators.
Elements in the timeseries
are indexed from the most
recent to the oldest data
Custom Symbols Functions for creating and
editing the custom symbol
properties
Chart Operations Functions for working with
charts. Chart property
changes are implemented
along with handling of the
events queue of this chart
Trade Functions Functions for conducting
trading operations and
receiving data on orders,
positions and deals
Trade Signals Functions for managing
trading signals
Network Functions Functions for working with
emails, FTP, push
notifications, HTTP requests
and remote servers
Section Description
Global Variables of the Terminal Functions for working with
global variables of the client
terminal
File Functions Functions for working with
files and "named channels"
Custom Indicators Functions for setting
properties in custom
indicators
Object Functions Functions for working with
graphical objects related to
a specified chart
Technical Indicators Functions for creating a
technical indicator and
getting its handle. If the
indicator already exists, no
new copy is created
Working with Optimization Functions for handling
Results optimization results in the
strategy tester
Working with Events Functions for working with
user and timer events
Working with OpenCL Functions for working with
OpenCL programs

 
MQL4 Reference / MQL5 features / MQL5 functions / Common
Functions

Common Functions
General-purpose functions not included into any
specialized group are listed here.
Function Action
Displays a message in a separate
Alert
window
CheckPointer Returns the type of the object pointer
Outputs a comment in the left top
Comment
corner of the chart
Transforms the data from array with
CryptEncode
the specified method
Performs the inverse transformation of
CryptDecode
the data from array
DebugBreak Program breakpoint in debugging
Stops Expert Advisor and unloads it
ExpertRemove
from the chart
GetPointer Returns the object pointer
Returns the number of milliseconds
GetTickCount that have elapsed since the system was
started
Returns the number of microseconds
GetMicrosecondCount that have elapsed since the start of
MQL5 program
Creates, displays a message box and
MessageBox
manages it
Function Action
Returns the number of seconds in the
PeriodSeconds
period
PlaySound Plays a sound file
Print Displays a message in the log
Formats and prints the sets of symbols
PrintFormat and values in a log file in accordance
with a preset format
Sets the value of a predetermined
ResetLastError
variable _LastError to zero
Creates an image resource based on a
ResourceCreate
data set
Deletes dynamically created resource
ResourceFree
(freeing the memory allocated for it)
Reads data from the graphical resource
ResourceReadImage created by ResourceCreate() function
or saved in EX5 file during compilation
ResourceSave Saves a resource into the specified file
Sets the predefined variable _LastError
SetUserError into the value equal to
ERR_USER_ERROR_FIRST + user_error
Sets the code that returns the terminal
SetReturnError process when completing the
operation.
Suspends execution of the current
Sleep Expert Advisor or script within a
specified interval
Commands the terminal to complete
TerminalClose
operation
Function Action
Sets the mode of displaying/hiding
TesterHideIndicators
indicators used in an EA
It returns the value of a specified
TesterStatistics statistic calculated based on testing
results
Gives program operation completion
TesterStop
command when testing
Emulates the operation of money
TesterWithdrawal
withdrawal in the process of testing
Returns a Unicode character by a
TranslateKey
virtual key code
Resets a variable passed to it by
reference. The variable can be of any
ZeroMemory
type, except for classes and structures
that have constructors.

 
MQL4 Reference / MQL5 features / MQL5 functions / Array Functions

Group of Functions for Working with Arrays


Arrays are allowed to be maximum four-dimensional. Each
dimension is indexed from 0 to dimension_size-1. In a
particular case of a one-dimensional array of 50 elements,
calling of the first element will appear as array[0], of the
last one - as array[49].
Function Action
ArrayBsearch Returns index of the first found element in
the first array dimension
ArrayCopy Copies one array into another
ArrayCompare Returns the result of comparing two arrays
of simple types or custom structures
without complex objects
ArrayFree Frees up buffer of any dynamic array and
sets the size of the zero dimension in 0.
ArrayGetAsSeries Checks direction of array indexing
ArrayInitialize Sets all elements of a numeric array into a
single value
ArrayFill Fills an array with the specified value
ArrayIsSeries Checks whether an array is a timeseries
ArrayIsDynamic Checks whether an array is dynamic
ArrayMaximum Search for an element with the maximal
value
ArrayMinimum Search for an element with the minimal
value
Function Action
ArrayPrint Prints an array of a simple type or a simple
structure into journal
ArrayRange Returns the number of elements in the
specified dimension of the array
ArrayResize Sets the new size in the first dimension of
the array
ArrayInsert Inserts the specified number of elements
from a source array to a receiving one
starting from a specified index
ArrayRemove Removes the specified number of elements
from the array starting with a specified
index
ArrayReverse Reverses the specified number of elements
in the array starting with a specified index
ArraySetAsSeries Sets the direction of array indexing
ArraySize Returns the number of elements in the
array
ArraySort Sorting of numeric arrays by the first
dimension
ArraySwap Swaps the contents of two dynamic arrays
of the same type
MQL4 Reference / MQL5 features / MQL5 functions / Conversion
Functions

Conversion Functions
This is a group of functions that provide conversion of
data from one format into another.
Function Action
Converting a symbol code into a one-
CharToString
character string
Converting a numeric value to a text
DoubleToString
line with a specified accuracy
Converting an enumeration value of any
EnumToString
type to string
Rounding of a floating point number to
NormalizeDouble
a specified accuracy
Converting a string containing a symbol
StringToDouble representation of number into number
of double type
Converting a string containing a symbol
StringToInteger representation of number into number
of int type
Converting a string containing time or
StringToTime date in "[Link] [hh:mi]" format
into datetime type
Converting a value containing time in
TimeToString seconds elapsed since 01.01.1970 into a
string of "[Link] hh:mi" format
Converting int into a string of preset
IntegerToString
length
Function Action
Converting symbol code (unicode) into
ShortToString
one-symbol string
ShortArrayToString Copying array part into a string
Symbol-wise copying a string to a
StringToShortArray
selected part of array of ushort type
Converting symbol code (ansi) into one-
CharArrayToString
symbol array
Symbol-wise copying a string converted
StringToCharArray from Unicode to ANSI, to a selected
place of array of uchar type
CharArrayToStruct Copy uchar type array to POD structure
StructToCharArray Copy POD structure to uchar type array
Converting color type to uint type to
ColorToARGB receive ARGB representation of the
color.
Converting color value into string as
ColorToString
"R,G,B"
Converting "R,G,B" string or string with
StringToColor
color name into color type value
Converting number into string
StringFormat
according to preset format

 
MQL4 Reference / MQL5 features / MQL5 functions / Math Functions

Mathematical Functions
A set of mathematical and trigonometric functions.
Function Action
MathAbs Returns absolute value (modulus) of the
specified numeric value
MathArccos Returns the arc cosine of x in radians
MathArcsin Returns the arc sine of x in radians
MathArctan Returns the arc tangent of x in radians
MathCeil Returns integer numeric value closest
from above
MathCos Returns the cosine of a number
MathExp Returns exponent of a number
MathFloor Returns integer numeric value closest
from below
MathLog Returns natural logarithm
MathLog10 Returns the logarithm of a number by
base 10
MathMax Returns the maximal value of the two
numeric values
MathMin Returns the minimal value of the two
numeric values
MathMod Returns the real remainder after the
division of two numbers
MathPow Raises the base to the specified power
Function Action
MathRand Returns a pseudorandom value within
the range of 0 to 32767
MathRound Rounds of a value to the nearest
integer
MathSin Returns the sine of a number
MathSqrt Returns a square root
MathSrand Sets the starting point for generating a
series of pseudorandom integers
MathTan Returns the tangent of a number
MathIsValidNumber Checks the correctness of a real
number
MathExpm1 Returns the value of the expression
MathExp(x)-1
MathLog1p Returns the value of the expression
MathLog(1+x)
MathArccosh Returns the hyperbolic arccosine
MathArcsinh Returns the hyperbolic arcsine
MathArctanh Returns the hyperbolic arctangent
MathCosh Returns the hyperbolic cosine
MathSinh Returns the hyperbolic sine
MathTanh Returns the hyperbolic tangent
MathSwap Change the order of bytes in the
ushort/uint/ushort types value
MQL4 Reference / MQL5 features / MQL5 functions / String Functions

String Functions
This is a group of functions intended for working with data
of the string type.
Function Action
StringAdd Adds a string to the end of another
string
StringBufferLen Returns the size of buffer allocated for
the string
StringCompare Compares two strings and returns 1 if
the first string is greater than the
second; 0 - if the strings are equal; -1
(minus 1) - if the first string is less than
the second one
StringConcatenate Forms a string of parameters passed
StringFill Fills out a specified string by selected
symbols
StringFind Search for a substring in a string
StringGetCharacter Returns the value of a number located
in the specified string position
StringInit Initializes string by specified symbols
and provides the specified string length
StringLen Returns the number of symbols in a
string
StringSetLength Sets a specified length (in characters)
for a string
Function Action
StringReplace Replaces all the found substrings of a
string by a set sequence of symbols
StringReserve Reserves the buffer of a specified size
for a string in memory.
StringSetCharacter Returns a copy of a string with a
changed value of a symbol in a
specified position
StringSplit Gets substrings by a specified separator
from the specified string, returns the
number of substrings obtained
StringSubstr Extracts a substring from a text string
starting from a specified position
StringToLower Transforms all symbols of a selected
string to lowercase
StringToUpper Transforms all symbols of a selected
string into capitals
StringTrimLeft Cuts line feed characters, spaces and
tabs in the left part of the string
StringTrimRight Cuts line feed characters, spaces and
tabs in the right part of the string
MQL4 Reference / MQL5 features / MQL5 functions / Date and Time

Date and Time


This is the group of functions for working with data of
datetime type (an integer that represents the number of
seconds elapsed from 0 hours of January 1, 1970).
Function Action
TimeCurrent Returns the last known server time
(time of the last quote receipt) in the
datetime format
TimeTradeServer Returns the current calculation time of
the trade server
TimeLocal Returns the local computer time in
datetime format
TimeGMT Returns GMT in datetime format with
the Daylight Saving Time by local time
of the computer, where the client
terminal is running
TimeDaylightSavings Returns the sign of Daylight Saving Time
switch
TimeGMTOffset Returns the current difference between
GMT time and the local computer time
in seconds, taking into account DST
switch
TimeToStruct Converts a datetime value into a
variable of MqlDateTime structure type
StructToTime Converts a variable of MqlDateTime
structure type into a datetime value
MQL4 Reference / MQL5 features / MQL5 functions / Account
Information

Account Information
Functions that return parameters of the current account.
Function Action
AccountInfoDouble Returns a value of double type of the
corresponding account property
AccountInfoInteger Returns a value of integer type (bool,
int or long) of the corresponding
account property
AccountInfoString Returns a value string type
corresponding account property
MQL4 Reference / MQL5 features / MQL5 functions / Checkup

State Checking
Functions that return parameters of the current state of
the client terminal
Function Action
GetLastError Returns the last error
IsStopped Returns true, if an mql5 program has
been commanded to stop its operation
UninitializeReason Returns the code of the reason for
deinitialization
TerminalInfoInteger Returns an integer value of a
corresponding property of the mql5
program environment
TerminalInfoDouble Returns a double value of a
corresponding property of the mql5
program environment
TerminalInfoString Returns a string value of a
corresponding property of the mql5
program environment
MQLInfoInteger Returns an integer value of a
corresponding property of a running
mql5 program
MQLInfoString Returns a string value of a
corresponding property of a running
mql5 program
Symbol Returns the name of a symbol of the
current chart
Function Action
Period Returns the current chart timeframe
Digits Returns the number of decimal digits
determining the accuracy of the price
value of the current chart symbol
Point Returns the point size of the current
symbol in the quote currency
MQL4 Reference / MQL5 features / MQL5 functions / Event Handling

Event Handling
The MQL5 language provides handling of certain
predefined events. The functions for handling these
events should be defined in an MQL5 program: function
name, return type, a set of parameters (if any) and their
types should strictly correspond to the description of an
event handling function.
The client terminal event handler uses the return and
parameter types to identify functions processing an event.
If a certain function has some parameters or a return type
not corresponding to the descriptions below, such a
function cannot be used for handling an event.
Function Action
The function is called when the Start
OnStart event occurs to perform actions set in
the script
The function is called in indicators and
OnInit EAs when the Init event occurs to
initialize a launched MQL5 program
The function is called in indicators and
OnDeinit EAs when the Deinit event occurs to de-
initialize a launched MQL5 program
The function is called in EAs when the
OnTick NewTick event occurs to handle a new
quote
Function Action
The function is called in indicators
OnCalculate when the Calculate event occurs to
handle price data changes
The function is called in indicators and
EAs during the Timer periodic event
OnTimer
generated by the terminal at fixed time
intervals
The function is called in EAs during the
OnTrade Trade event generated at the end of a
trading operation on a trade server
The function is called in EAs when the
TradeTransaction event occurs to
OnTradeTransaction
process a trade request execution
results
The function is called in EAs when the
OnBookEvent BookEvent event occurs to process
changes in the market depth
The function is called in indicators and
EAs when the ChartEvent event occurs
OnChartEvent
to process chart changes made by a
user or an MQL5 program
The function is called in EAs when the
Tester event occurs to perform
OnTester
necessary actions after testing an EA on
history data
The function is called in EAs when the
TesterInit event occurs to perform
OnTesterInit
necessary actions before optimization
in the strategy tester
Function Action
The function is called in EAs when the
OnTesterDeinit TesterDeinit event occurs after EA
optimization in the strategy tester
The function is called in EAs when the
TesterPass even occurs to handle an
OnTesterPass
arrival of a new data frame during EA
optimization in the strategy tester

The client terminal sends incoming events to


corresponding open charts. Also, events may be generated
by charts (chart events) or mql5 programs (custom
events). Generating graphical object creation/deletion
events can be enabled/disabled by setting the
CHART_EVENT_OBJECT_CREATE and
CHART_EVENT_OBJECT_DELETE chart properties. Each
mql5 application and chart have their own queue of
events where all newly arrived events are placed.
A program gets events only from the chart it is running
on. All events are handled one after another in the order
of their receipt. If the queue already contains the
NewTick event or this event is in the processing stage,
then the new NewTick event is not added to mql5
application queue. Similarly, if the ChartEvent is already
in an mql5 program queue or such an event is being
handled, then a new event of this type is not placed into
a queue. Timer event handling is processed in the same
way if the Timer event is already in the queue or is being
handled, no new timer event is set into a queue.
Event queues have a limited but sufficient size, so the
queue overflow is unlikely for a correctly developed
program. When the queue overflows, new events are
discarded without being set into a queue.
It is strongly recommended not to use infinite loops to
handle events. Possible exceptions are scripts handling a
single Start event.
Libraries do not handle any events.
MQL4 Reference / MQL5 features / MQL5 functions / Market Info

Getting Market Information


These are functions intended for receiving information
about the market state.
Function Action
Returns the number of available
SymbolsTotal (selected in Market Watch or all)
symbols
Checks if a symbol with a specified
SymbolExist
name exists
Returns the name of a specified
SymbolName
symbol
Selects a symbol in the Market
SymbolSelect Watch window or removes a symbol
from the window
Checks whether data of a selected
symbol in the terminal are
SymbolIsSynchronized
synchronized with data on the trade
server
Returns the double value of the
SymbolInfoDouble symbol for the corresponding
property
Returns a value of an integer type
(long, datetime, int or bool) of a
SymbolInfoInteger
specified symbol for the
corresponding property
Function Action
Returns a value of the string type of
SymbolInfoString a specified symbol for the
corresponding property
Returns the margin rates depending
SymbolInfoMarginRate
on the order type and direction
Returns the current prices for the
SymbolInfoTick specified symbol in a variable of the
MqlTick type
Allows receiving time of beginning
and end of the specified quoting
SymbolInfoSessionQuote
sessions for a specified symbol and
day of week.
Allows receiving time of beginning
and end of the specified trading
SymbolInfoSessionTrade
sessions for a specified symbol and
day of week.
Provides opening of Depth of Market
for a selected symbol, and
MarketBookAdd
subscribes for receiving notifications
of the DOM changes
Provides closing of Depth of Market
for a selected symbol, and cancels
MarketBookRelease
the subscription for receiving
notifications of the DOM changes
Returns a structure array
MqlBookInfo containing records of
MarketBookGet
the Depth of Market of a specified
symbol

 
MQL4 Reference / MQL5 features / MQL5 functions / Economic
Calendar

Economic calendar functions


This section describes the functions for working with the
economic calendar available directly in the MetaTrader
platform. The economic calendar is a ready-made
encyclopedia featuring descriptions of macroeconomic
indicators, their release dates and degrees of importance.
Relevant values of macroeconomic indicators are sent to
the MetaTrader platform right at the moment of
publication and are displayed on a chart as tags allowing
you to visually track the required indicators by countries,
currencies and importance.
Economic calendar functions allow conducting the auto
analysis of incoming events according to custom
importance criteria from a perspective of necessary
countries/currencies.
Function Action
CalendarCountryById Get a country description by its
ID
CalendarEventById Get an event description by its
ID
CalendarValueById Get an event value description
by its ID
CalendarCountries Get the array of country names
available in the calendar
Function Action
CalendarEventByCountry Get the array of descriptions of
all events available in the
calendar by a specified country
code
CalendarEventByCurrency Get the array of descriptions of
all events available in the
calendar by a specified
currency
CalendarValueHistoryByEvent Get the array of values for all
events in a specified time range
by an event ID
CalendarValueHistory Get the array of values for all
events in a specified time range
with the ability to sort by
country and/or currency
CalendarValueLastByEvent Get the array of event values
by its ID since the calendar
database status with a
specified change_id
CalendarValueLast Get the array of values for all
events with the ability to sort
by country and/or currency
since the calendar database
status with a specified
change_id
MQL4 Reference / MQL5 features / MQL5 functions / Timeseries and
Indicators Access

Access to Timeseries and Indicator Data


These are functions for working with timeseries and
indicators. A timeseries differs from the usual data array
by its reverse ordering - elements of timeseries are
indexed from the end of an array to its begin (from the
most recent data to the oldest ones). To copy the time-
series values and indicator data, it's recommended to use
dynamic arrays only, because copying functions are
designed to allocate the necessary size of arrays that
receive values.
Function Action
Returns information about the state of
SeriesInfoInteger
historical data
Returns the number of bars count in
Bars the history for a specified symbol and
period
Returns the number of calculated data
in an indicator buffer or -1 in the case
BarsCalculated
of error (data hasn't been calculated
yet)
Returns the handle to the specified
IndicatorCreate technical indicator created by an array
of MqlParam type parameters
Based on the specified handle, returns
the number of input parameters of the
IndicatorParameters
indicator, as well as the values and
types of the parameters
Function Action
Removes an indicator handle and
IndicatorRelease releases the calculation block of the
indicator, if it's not used by anyone else
Gets data of a specified buffer from a
CopyBuffer
specified indicator into an array
Gets history data of the Rates structure
CopyRates for a specified symbol and period into
an array
Gets history data on bar opening time
CopyTime for a specified symbol and period into
an array
Gets history data on bar opening price
CopyOpen for a specified symbol and period into
an array
Gets history data on maximal bar price
CopyHigh for a specified symbol and period into
an array
Gets history data on minimal bar price
CopyLow for a specified symbol and period into
an array
Gets history data on bar closing price
CopyClose for a specified symbol and period into
an array
Gets history data on tick volumes for a
CopyTickVolume specified symbol and period into an
array
Gets history data on trade volumes for
CopyRealVolume a specified symbol and period into an
array
Function Action
Gets history data on spreads for a
CopySpread specified symbol and period into an
array
Gets ticks in the MqlTick format into
CopyTicks
ticks_array
Gets ticks in the MqlTick format within
CopyTicksRange
the specified date range to ticks_array
Returns the number of bars of a
iBars corresponding symbol and period,
available in history
Returns the index of the bar
iBarShift
corresponding to the specified time
Returns the Close price of the bar
iClose (indicated by the 'shift' parameter) on
the corresponding chart
Returns the High price of the bar
iHigh (indicated by the 'shift' parameter) on
the corresponding chart
Returns the index of the highest value
iHighest found on the corresponding chart (shift
relative to the current bar)
Returns the Low price of the bar
iLow (indicated by the 'shift' parameter) on
the corresponding chart
Returns the index of the smallest value
iLowest found on the corresponding chart (shift
relative to the current bar)
Function Action
Returns the Open price of the bar
iOpen (indicated by the 'shift' parameter) on
the corresponding chart
Returns the opening time of the bar
iTime (indicated by the 'shift' parameter) on
the corresponding chart
Returns the tick volume of the bar
iTickVolume (indicated by the 'shift' parameter) on
the corresponding chart
Returns the real volume of the bar
iRealVolume (indicated by the 'shift' parameter) on
the corresponding chart
Returns the tick volume of the bar
iVolume (indicated by the 'shift' parameter) on
the corresponding chart
Returns the spread value of the bar
iSpread (indicated by the 'shift' parameter) on
the corresponding chart

 
MQL4 Reference / MQL5 features / MQL5 functions / Custom Symbols

Custom symbols
Functions for creating and editing the custom symbol
properties.
When connecting the terminal to a certain trade server, a
user is able to work with time series of the financial
symbols provided by a broker. Available financial symbols
are displayed as a list in the Market Watch window. A
separate group of functions allows receiving data on the
symbol properties, trading sessions and market depth
updates.
The group of functions described in this section allows
creating custom symbols. To do this, users are able to
apply the trade server's existing symbols, text files or
external data sources.
Function Action
Create a custom symbol with
CustomSymbolCreate the specified name in the
specified group
Delete a custom symbol with
CustomSymbolDelete
the specified name
Set the integer type property
CustomSymbolSetInteger
value for a custom symbol
Set the real type property
CustomSymbolSetDouble
value for a custom symbol
Set the string type property
CustomSymbolSetString
value for a custom symbol
Function Action
Set the margin rates
depending on the order type
CustomSymbolSetMarginRate
and direction for a custom
symbol
Set the start and end time of
the specified quotation
CustomSymbolSetSessionQuote
session for the specified
symbol and week day
Set the start and end time of
the specified trading session
CustomSymbolSetSessionTrade
for the specified symbol and
week day
Delete all bars from the price
CustomRatesDelete history of the custom symbol
in the specified time interval
Fully replace the price history
of the custom symbol within
CustomRatesReplace the specified time interval
with the data from
the MqlRates type array
Add missing bars to the
custom symbol history and
CustomRatesUpdate replace existing data with the
ones from the  MqlRates type
array
Adds data from an array of
the MqlTick type to the price
history of a custom symbol.
CustomTicksAdd
The custom symbol must be
selected in the Market Watch
window
Function Action
Delete all ticks from the price
CustomTicksDelete history of the custom symbol
in the specified time interval
Fully replace the price history
of the custom symbol within
CustomTicksReplace the specified time interval
with the data from
the MqlTick type array
Passes the status of the Depth
CustomBookAdd
of Market for a custom symbol

 
MQL4 Reference / MQL5 features / MQL5 functions / Chart
Operations

Chart Operations
Functions for setting chart properties (ChartSetInteger,
ChartSetDouble, ChartSetString) are asynchronous and are
used for sending update commands to a chart. If these
functions are executed successfully, the command is
included in the common queue of the chart events. Chart
property changes are implemented along with handling of
the events queue of this chart.
Function Action
Applies a specific template from a
ChartApplyTemplate
specified file to the chart
Saves current chart settings in a
ChartSaveTemplate
template with a specified name
Returns the number of a subwindow
ChartWindowFind
where an indicator is drawn
Converts the coordinates of a chart
ChartTimePriceToXY from the time/price representation to
the X and Y coordinates
Converts the X and Y coordinates on a
ChartXYToTimePrice
chart to the time and price values
Opens a new chart with the specified
ChartOpen
symbol and period
ChartClose Closes the specified chart
Returns the ID of the first chart of the
ChartFirst
client terminal
Function Action
Returns the chart ID of the chart next
ChartNext
to the specified one
Returns the symbol name of the
ChartSymbol
specified chart
Returns the period value of the
ChartPeriod
specified chart
Calls a forced redrawing of a specified
ChartRedraw
chart
Sets the double value for a
ChartSetDouble corresponding property of the
specified chart
Sets the integer value (datetime, int,
color, bool or char) for a
ChartSetInteger
corresponding property of the
specified chart
Sets the string value for a
ChartSetString corresponding property of the
specified chart
Returns the double value property of
ChartGetDouble
the specified chart
Returns the integer value property of
ChartGetInteger
the specified chart
Returns the string value property of
ChartGetString
the specified chart
Performs shift of the specified chart
by the specified number of bars
ChartNavigate
relative to the specified position in
the chart
ChartID Returns the ID of the current chart
Function Action
Adds an indicator with the specified
ChartIndicatorAdd
handle into a specified chart window
Removes an indicator with a specified
ChartIndicatorDelete
name from the specified chart window
Returns the handle of the indicator
ChartIndicatorGet with the specified short name in the
specified chart window
Returns the short name of the
indicator by the number in the
ChartIndicatorName
indicators list on the specified chart
window
Returns the number of all indicators
ChartIndicatorsTotal
applied to the specified chart window.
Returns the number (index) of the
ChartWindowOnDropped chart subwindow the Expert Advisor or
script has been dropped to
Returns the price coordinate of the
ChartPriceOnDropped chart point the Expert Advisor or
script has been dropped to
Returns the time coordinate of the
ChartTimeOnDropped chart point the Expert Advisor or
script has been dropped to
Returns the X coordinate of the chart
ChartXOnDropped point the Expert Advisor or script has
been dropped to
Returns the Y coordinate of the chart
ChartYOnDropped point the Expert Advisor or script has
been dropped to
Function Action
Changes the symbol value and a
ChartSetSymbolPeriod
period of the specified chart
Provides a screenshot of the chart of
its current state in a GIF, PNG or BMP
ChartScreenShot
format depending on specified
extension

 
MQL4 Reference / MQL5 features / MQL5 functions / Trade Functions

Trade Functions
This is the group of functions intended for managing
trading activities. Trading functions can be called only if
in the properties of the Expert Advisor or script the "Allow
live trading" checkbox is enabled.
Trading can be allowed or prohibited depending on various
factors described in the Trade Permission section.
Function Action
Calculates the margin required for
OrderCalcMargin the specified order type, in the
deposit currency
Calculates the profit based on the
OrderCalcProfit parameters passed, in the deposit
currency
Checks if there are enough funds to
OrderCheck execute the required trade
operation.
OrderSend Sends trade requests to a server
Asynchronously sends trade requests
OrderSendAsync without waiting for the trade
response of the trade server
PositionsTotal Returns the number of open positions
Returns the symbol corresponding to
PositionGetSymbol
the open position
Chooses an open position for further
PositionSelect
working with it
Function Action
Selects a position to work with by the
PositionSelectByTicket
ticket number specified in it
Returns the requested property of an
PositionGetDouble
open position (double)
Returns the requested property of an
PositionGetInteger
open position (datetime or int)
Returns the requested property of an
PositionGetString
open position (string)
Returns the ticket of the position
PositionGetTicket with the specified index in the list of
open positions
OrdersTotal Returns the number of orders
Return the ticket of a corresponding
OrderGetTicket
order
Selects a order for further working
OrderSelect
with it
Returns the requested property of
OrderGetDouble
the order (double)
Returns the requested property of
OrderGetInteger
the order (datetime or int)
Returns the requested property of
OrderGetString
the order (string)
Retrieves the history of transactions
HistorySelect and orders for the specified period of
the server time
Requests the history of deals with a
HistorySelectByPosition
specified position identifier.
Function Action
Selects an order in the history for
HistoryOrderSelect
further working with it
Returns the number of orders in the
HistoryOrdersTotal
history
Return order ticket of a
HistoryOrderGetTicket
corresponding order in the history
Returns the requested property of an
HistoryOrderGetDouble
order in the history (double)
Returns the requested property of an
HistoryOrderGetInteger
order in the history (datetime or int)
Returns the requested property of an
HistoryOrderGetString
order in the history (string)
Selects a deal in the history for
HistoryDealSelect further calling it through appropriate
functions
Returns the number of deals in the
HistoryDealsTotal
history
Returns a ticket of a corresponding
HistoryDealGetTicket
deal in the history
Returns the requested property of a
HistoryDealGetDouble
deal in the history (double)
Returns the requested property of a
HistoryDealGetInteger
deal in the history (datetime or int)
Returns the requested property of a
HistoryDealGetString
deal in the history (string)

 
MQL4 Reference / MQL5 features / MQL5 functions / Trade Signals

Trade Signals
This is the group of functions intended for managing trade
signals. The functions allow:
get information about trade signals, available for
copying,
get and set the signal copy settings,
subscribe and unsubscribe to the signal copying using
MQL5 language functions.
Function Action
SignalBaseGetDouble Returns the value of double type
property for selected signal
SignalBaseGetInteger Returns the value of integer type
property for selected signal
SignalBaseGetString Returns the value of string type
property for selected signal
SignalBaseSelect Selects a signal from signals, available
in terminal for further working with it
SignalBaseTotal Returns the total amount of signals,
available in terminal
SignalInfoGetDouble Returns the value of double type
property of signal copy settings
SignalInfoGetInteger Returns the value of integer type
property of signal copy settings
SignalInfoGetString Returns the value of string type
property of signal copy settings
Function Action
SignalInfoSetDouble Sets the value of double type property
of signal copy settings
SignalInfoSetInteger Sets the value of integer type property
of signal copy settings
SignalSubscribe Subscribes to the trading signal
SignalUnsubscribe Cancels subscription

 
MQL4 Reference / MQL5 features / MQL5 functions / Network
Functions

Network functions
MQL5 programs can exchange data with remote servers,
as well as send push notifications, emails and data via
FTP.
Add an explicit message to the MQL5 program to notify a
user of the need for additional configuration. You can do
that via #property description, Alert or Print.
Function Action
Create a socket with specified flags
SocketCreate
and return its handle
SocketClose Close a socket
Connect to the server with timeout
SocketConnect
control
Checks if the socket is currently
SocketIsConnected
connected
Get a number of bytes that can be
SocketIsReadable
read from a socket
Check whether data can be written
SocketIsWritable
to a socket at the current time
Set timeouts for receiving and
SocketTimeouts sending data for a socket system
object
SocketRead Read data from a socket
SocketSend Write data to a socket
Function Action
Initiate secure TLS (SSL) connection
SocketTlsHandshake to a specified host via TLS Handshake
protocol
Get data on the certificate used to
SocketTlsCertificate
secure network connection
Read data from secure TLS
SocketTlsRead
connection
Read all available data from secure
SocketTlsReadAvailable
TLS connection
SocketTlsSend Send data via secure TLS connection
Send an HTTP request to a specified
WebRequest
server
Send a file to an address specified on
SendFTP
the FTP tab
Send an email to an address specified
SendMail in the Email tab of the options
window
Send push notifications to mobile
SendNotification terminals whose MetaQuotes IDs are
specified in the Notifications tab

 
 
MQL4 Reference / MQL5 features / MQL5 functions / Global Variables
of the Terminal

Global Variables of the Client Terminal


There is a group set of functions for working with global
variables.
Global variables of the client terminal are accessible
simultaneously from all mql5 programs launched in the
client terminal.
Function Action
GlobalVariableCheck Checks the existence of a
global variable with the
specified name
GlobalVariableTime Returns time of the last
accessing the global variable
GlobalVariableDel Deletes a global variable
GlobalVariableGet Returns the value of a global
variable
GlobalVariableName Returns the name of a global
variable by its ordinal number
in the list of global variables
GlobalVariableSet Sets the new value to a global
variable
GlobalVariablesFlush Forcibly saves contents of all
global variables to a disk
GlobalVariableTemp Sets the new value to a global
variable, that exists only in the
current session of the terminal
Function Action
GlobalVariableSetOnCondition Sets the new value of the
existing global variable by
condition
GlobalVariablesDeleteAll Deletes global variables with
the specified prefix in their
names
GlobalVariablesTotal Returns the total number of
global variables
MQL4 Reference / MQL5 features / MQL5 functions / File Functions

File Functions
This is a group of functions for working with files. File
functions allow working with so-called "named pipes". To
do this, simply call FileOpen() function with appropriate
parameters.
Function Action
Starts the search of files in a directory
FileFindFirst
in accordance with the specified filter
Continues the search started by the
FileFindNext
FileFindFirst() function
FileFindClose Closes search handle
Opens a file with a specified name and
FileOpen
flag
FileDelete Deletes a specified file
Writes to a disk all data remaining in
FileFlush
the input/output file buffer
FileGetInteger Gets an integer property of a file
Defines the end of a file in the process
FileIsEnding
of reading
Defines the end of a line in a text file
FileIsLineEnding
in the process of reading
FileClose Closes a previously opened file
FileIsExist Checks the existence of a file
Copies the original file from a local or
FileCopy
shared folder to another file
Function Action
FileMove Moves or renames a file
Reads arrays of any type except for
FileReadArray
string from the file of the BIN type
Reads from the file of the CSV type a
string from the current position till a
FileReadBool delimiter (or till the end of a text line)
and converts the read string to a value
of bool type
Reads from the file of the CSV type a
string of one of the formats:
FileReadDatetime "[Link] HH:MM:SS", "[Link]"
or "HH:MM:SS" - and converts it into a
datetime value
Reads a double value from the current
FileReadDouble
position of the file pointer
Reads a float value from the current
FileReadFloat
position of the file pointer
Reads int, short or char value from the
FileReadInteger
current position of the file pointer
Reads a long type value from the
FileReadLong
current position of the file pointer
Reads from the file of the CSV type a
string from the current position till a
FileReadNumber delimiter (or til the end of a text line)
and converts the read string into
double value
Reads a string from the current position
FileReadString
of a file pointer from a file
Function Action
Reads the contents from a binary file
 into a structure passed as a parameter,
FileReadStruct
from the current position of the file
pointer
Moves the position of the file pointer
FileSeek by a specified number of bytes relative
to the specified position
Returns the size of a corresponding
FileSize
open file
Returns the current position of the file
FileTell
pointer of a corresponding open file
FileWrite Writes data to a file of CSV or TXT type
Writes arrays of any type except for
FileWriteArray
string into a file of BIN type
Writes value of the double type from
FileWriteDouble the current position of a file pointer
into a binary file
Writes value of the float type from the
FileWriteFloat current position of a file pointer into a
binary file
Writes value of the int type from the
FileWriteInteger current position of a file pointer into a
binary file
Writes value of the long type from the
FileWriteLong current position of a file pointer into a
binary file
Writes the value of a string parameter
FileWriteString into a BIN or TXT file starting from the
current position of the file pointer
Function Action
Writes the contents of a structure
passed as a parameter into a binary
FileWriteStruct
file, starting from the current position
of the file pointer
Reads all data of a specified binary file
FileLoad into a passed array of numeric types or
simple structures
Writes to a binary file all elements of
FileSave
an array passed as a parameter
FolderCreate Creates a folder in the Files directory
Removes a selected directory. If the
FolderDelete folder is not empty, then it can't be
removed
FolderClean Deletes all files in the specified folder

If the file is opened for writing using FileOpen(), all


subfolders specified in the path will be created if there
are no such ones.
MQL4 Reference / MQL5 features / MQL5 functions / Custom
Indicators

Custom Indicators
This is the group functions used in the creation of custom
indicators. These functions can't be used when writing
Expert Advisors and Scripts.
Function Action
SetIndexBuffer Binds the specified indicator buffer with
one-dimensional dynamic array of the
double type
IndicatorSetDouble Sets the value of an indicator property
of the double type
IndicatorSetInteger Sets the value of an indicator property
of the int type
IndicatorSetString Sets the value of an indicator property
of the string type
PlotIndexSetDouble Sets the value of an indicator line
property of the type double
PlotIndexSetInteger Sets the value of an indicator line
property of the int type
PlotIndexSetString Sets the value of an indicator line
property of the string type
PlotIndexGetInteger Returns the value of an indicator line
property of the integer type

Indicator properties can be set using the compiler


directives or using functions. To better understand this, it
is recommended that you study indicator styles in
examples.
MQL4 Reference / MQL5 features / MQL5 functions / Object
Functions

Object Functions
This is the group of functions intended for working with
graphic objects relating to any specified chart.
The functions defining the properties of graphical objects,
as well as ObjectCreate() and ObjectMove() operations for
creating and moving objects along the chart are actually
used for sending commands to the chart. If these
functions are executed successfully, the command is
included in the common queue of the chart events. Visual
changes in the properties of graphical objects are
implemented when handling the queue of the chart
events.
Thus, do not expect an immediate visual update of
graphical objects after calling these functions. Generally,
the graphical objects on the chart are updated
automatically by the terminal following the change events
- a new quote arrival, resizing the chart window, etc. Use
ChartRedraw() function to forcefully update the graphical
objects.
Function Action
Creates an object of the specified
ObjectCreate
type in a specified chart
Returns the name of an object of the
ObjectName corresponding type in the specified
chart (specified chart subwindow)
Function Action
Removes the object with the
specified name from the specified
ObjectDelete
chart (from the specified chart
subwindow)
Removes all objects of the specified
ObjectsDeleteAll type from the specified chart (from
the specified chart subwindow)
Searches for an object with the
ObjectFind
specified ID by the name
Returns the time value for the
ObjectGetTimeByValue
specified object price value
Returns the price value of an object
ObjectGetValueByTime
for the specified time
Changes the coordinates of the
ObjectMove
specified object anchor point
Returns the number of objects of the
ObjectsTotal specified type in the specified chart
(specified chart subwindow)
Returns the double value of the
ObjectGetDouble
corresponding object property
Returns the integer value of the
ObjectGetInteger
corresponding object property
Returns the string value of the
ObjectGetString
corresponding object property
Sets the value of the corresponding
ObjectSetDouble
object property
Sets the value of the corresponding
ObjectSetInteger
object property
Function Action
Sets the value of the corresponding
ObjectSetString
object property
Sets the font for displaying the text
TextSetFont using drawing methods (Arial 20 used
by default)
Transfers the text to the custom array
TextOut (buffer) designed for creation of a
graphical resource
Returns the string's width and height
TextGetSize
at the current font settings

Every graphical object should have a name unique within


one chart, including its subwindows. Changing of a name
of a graphic object generates two events: event of
deletion of an object with the old name, and event of
creation of an object with a new name.
After an object is created or an object property is
modified it is recommended to call the ChartRedraw()
function, which commands the client terminal to forcibly
draw a chart (and all visible objects in it).
 
MQL4 Reference / MQL5 features / MQL5 functions / Technical
Indicators

Technical Indicator Functions


All functions like iMA, iAC, iMACD, iIchimoku etc. create a
copy of the corresponding technical indicator in the global
cache of the client terminal. If a copy of the indicator
with such parameters already exists, the new copy is not
created, and the counter of references to the existing
copy increases.
These functions return the handle of the appropriate copy
of the indicator. Further, using this handle, you can
receive data calculated by the corresponding indicator.
The corresponding buffer data (technical indicators
contain calculated data in their internal buffers, which
can vary from 1 to 5, depending on the indicator) can be
copied to a mql5-program using the CopyBuffer()
function.
All indicator functions have at least 2 parameters - symbol
and period. The NULL value of the symbol means the
current symbol, the 0 value of the period means the
current timeframe.
Function Action
iAC Accelerator Oscillator
iAD Accumulation/Distribution
iADX Average Directional Index
Average Directional Index by Welles
iADXWilder
Wilder
Function Action
iAlligator Alligator
iAMA Adaptive Moving Average
iAO Awesome Oscillator
iATR Average True Range
iBearsPower Bears Power
iBands Bollinger Bands®
iBullsPower Bulls Power
iCCI Commodity Channel Index
iChaikin Chaikin Oscillator
iCustom Custom indicator
iDEMA Double Exponential Moving Average
iDeMarker DeMarker
iEnvelopes Envelopes
iForce Force Index
iFractals Fractals
iFrAMA Fractal Adaptive Moving Average
iGator Gator Oscillator
iIchimoku Ichimoku Kinko Hyo
Market Facilitation Index by Bill
iBWMFI
Williams
iMomentum Momentum
iMFI Money Flow Index
iMA Moving Average
Function Action
Moving Average of Oscillator (MACD
iOsMA
histogram)
Moving Averages Convergence-
iMACD
Divergence
iOBV On Balance Volume
iSAR Parabolic Stop And Reverse System
iRSI Relative Strength Index
iRVI Relative Vigor Index
iStdDev Standard Deviation
iStochastic Stochastic Oscillator
iTEMA Triple Exponential Moving Average
Triple Exponential Moving Averages
iTriX
Oscillator
iWPR Williams' Percent Range
iVIDyA Variable Index Dynamic Average
iVolumes Volumes

 
MQL4 Reference / MQL5 features / MQL5 functions / Working with
Optimization Results

Working with Optimization Results


Functions for organizing custom processing of the
optimization results in the strategy tester. They can be
called during optimization in testing agents, as well as
locally in Expert Advisors and scripts.
When you run an Expert Advisor in the strategy tester, you
can create your own data array based on the simple types
or simple structures (they do not contain strings, class
objects or objects of dynamic arrays). This data set can
be saved using the FrameAdd() function in a special
structure called a frame. During the optimization of an
Expert Advisor, each agent can send a series of frames to
the terminal. All the received frames are written in the
*.MQD file named as the Expert Advisor in the
terminal_directory\MQL5\Files\Tester folder. They are
written in the order they are received from the agents.
Receipt of a frame in the client terminal from a testing
agent generates the TesterPass event.
Frames can be stored in the computer memory and in a
file with the specified name. The MQL5 language sets no
limitations on the number of frames.
Function Action
Moves a pointer of frame reading to the
FrameFirst beginning and resets the previously set
filter
Sets the frame reading filter and moves
FrameFilter
the pointer to the beginning
Function Action
Reads a frame and moves the pointer to
FrameNext
the next one
Receives input parameters, on which
FrameInputs
the frame is formed
FrameAdd Adds a frame with data
Receives data on the values range and
the change step for an input variable
ParameterGetRange
when optimizing an Expert Advisor in
the Strategy Tester
Specifies the use of input variable when
optimizing an Expert Advisor in the
ParameterSetRange
Strategy Tester: value, change step,
initial and final values
MQL4 Reference / MQL5 features / MQL5 functions / Working with
Events

Event Functions
This group contains functions for working with custom
events and timer events. Besides this group, there are
special functions for handling predefined events.
Function Action
EventSetMillisecondTimer Launches event generator of the
high-resolution timer with a period
less than 1 second for the current
chart
EventSetTimer Starts the timer event generator
with the specified periodicity for
the current chart
EventKillTimer Stops the generation of events by
the timer in the current chart
EventChartCustom Generates a custom event for the
specified chart

 
MQL4 Reference / MQL5 features / MQL5 functions / Working with
OpenCL

Working with OpenCL


OpenCL programs are used for performing computations
on video cards that support OpenCL 1.1 or higher. Modern
video cards contain hundreds of small specialized
processors that can simultaneously perform simple
mathematical operations with incoming data streams. The
OpenCL language organizes parallel computing and
provides greater speed for a certain class of tasks.
It is recommended to write the source code for OpenCL in
separate CL files, which can later be included in the MQL5
program using the resource variables.
Function Action
CLHandleType Returns the type of an OpenCL
handle as a value of the
ENUM_OPENCL_HANDLE_TYPE
enumeration
CLGetInfoInteger Returns the value of an integer
property for an OpenCL object or
device
CLGetInfoString Creates an OpenCL context
CLContextCreate Removes an OpenCL context
CLContextFree Receives device property from
OpenCL driver
CLGetDeviceInfo Creates an OpenCL program from a
source code
CLProgramCreate Removes an OpenCL program
Function Action
CLProgramFree Creates an OpenCL start function
CLKernelCreate Removes an OpenCL start function
CLKernelFree Sets a parameter for the OpenCL
function
CLSetKernelArg Sets an OpenCL buffer as a
parameter of the OpenCL function
CLSetKernelArgMem Sets the local buffer as an
argument of the kernel function
CLSetKernelArgMemLocal Creates an OpenCL buffer
CLBufferCreate Deletes an OpenCL buffer
CLBufferFree Writes an array into an OpenCL
buffer
CLBufferWrite Reads an OpenCL buffer into an
array
CLBufferRead Runs an OpenCL program
CLExecute Returns the OpenCL program
execution status
CLExecutionStatus Returns the OpenCL program
execution status

 
MQL4 Reference / Language Basics

Language Basics
The MetaQuotes Language 4 (MQL4) is an object-oriented
high-level programming language intended for writing
automated trading strategies, custom technical indicators
for the analysis of various financial markets. It allows not
only to write a variety of expert systems, designed to
operate in real time, but also create their own graphical
tools to help you make trade decisions.
MQL4 is based on the concept of the popular programming
language C++. The language has enumerations, structures,
classes and event handling. By increasing the number of
embedded main types, the interaction of executable
programs in MQL4 with other applications through dll is
now as easy as possible. MQL4 syntax is similar to the
syntax of C++, and this makes it easy to translate into it
programs from modern programming languages.
To help you study the MQL4 language, all topics are
grouped into the following sections:
Syntax
Data Types
Operations and Expressions
Operators
Functions
Variables
Preprocessor
Object-Oriented Programming
Updated MQL4
MQL4 Reference / Language Basics / Syntax

Syntax
As to the syntax, THE MQL4 language for programming
trading strategies is very much similar to the C++
programming language, except for some features:
no address arithmetic;
no goto operator;
an anonymous enumeration can't be declared;
no multiple inheritance.
See also
Enumerations, Structures and Classes, Inheritance
MQL4 Reference / Language Basics / Syntax / Comments

Comments
Multi-line comments start with the /* pair of symbols and
end with the */ one. Such kind of comments cannot be
nested. Single-line comments begin with the // pair of
symbols and end with the newline character, they can be
nested in other multi-line comments. Comments are
allowed everywhere where the spaces are allowed, they
can have any number of spaces in them.
Examples:
//--- Single-line comment /* Multi-
line // Nested single-line comment
comment
*/
MQL4 Reference / Language Basics / Syntax / Identifiers

Identifiers
Identifiers are used as names of variables and functions.
The length of the identifier can not exceed 63 characters.
Characters allowed to be written in an identifier: figures
0-9, the Latin uppercase and lowercase letters a-z and A-
Z, recognized as different characters, the underscore
character (_).The first character can not be a digit.
The identifier must not coincide with reserved word.
Examples:
NAME1 namel Total_5 Paper

See also
Variables, Functions
MQL4 Reference / Language Basics / Syntax / Reserved Words

Reserved Words
The following identifiers are recorded as reserved words,
each of them corresponds to a certain action, and cannot
be used in another meaning:
Data Types
bool enum struct
char float uchar
class int uint
color long ulong
datetime short ushort
double string void

 
Access Specificators
const private protected
public virtual  
 
Memory Classes
extern input static

 
Operators
break dynamic_cast return
case else sizeof
break dynamic_cast return
continue for switch
default if while
delete new  
do operator  

 
Other
false #define #property
this #import template
true #include typename
strict    

 
 
MQL4 Reference / Language Basics / Data Types

Data Types
Any program operates with data. Data can be of different
types depending on their purposes. For example, integer
data are used to access to array components. Price data
belong to those of double precision with floating point.
This is related to the fact that no special data type for
price data is provided in MQL4.
Data of different types are processed with different rates.
Integer data are processed at the fastest. To process the
double precision data, a special co-processor is used.
However, because of complexity of internal
representation of data with floating point, they are
processed slower than the integer ones.
String data are processed at the longest because of
dynamic computer memory allocation/reallocation.
The basic data types are:
integers (char, short, int, long, uchar, ushort, uint,
ulong);
logical (bool);
literals (ushort);
strings (string);
floating-point numbers (double, float);
color (color);
date and time (datetime);
enumerations (enum).
Complex data types are:
structures;
classes.
In terms of OOP complex data types are called abstract
data types.
The color and datetime types make sense only to
facilitate visualization and input of parameters defined
from outside - from the table of Expert Advisor or custom
indicator properties (the Inputs tab). Data of color and
datetime types are represented as integers. Integer types
and floating-point types are called arithmetic (numeric)
types.
Only implicit type casting is used in expressions, unless
the explicit casting is specified.
See also
Typecasting
MQL4 Reference / Language Basics / Data Types / Integer Types

Integer Types
In MQL4 integers are represented by eleven types. Some
types can be used together with other ones, if required by
the program logic, but in this case it's necessary to
remember the rules of typecasting.
The table below lists the characteristics of each type.
Besides, the last column features a type in C++
corresponding to each type.
Type Size Minimum Maximum Value C++
in Value Analog
Bytes
char 1 -128 127 char
uchar 1 0 255 unsigned
char, BYTE
bool 1 0(false) 1(true) bool
short 2 -32 768 32 767 short,
wchar_t
ushort 2 0 65 535 unsigned
short,
WORD
int 4 - 2 147 483 2 147 483 647 int
648
uint 4 0 4 294 967 295 unsigned
int,
DWORD
Type Size Minimum Maximum Value C++
in Value Analog
Bytes
color 4 -1 16 777 215 int,
COLORREF
long 8 -9 223 372 9 223 372 036 __int64
036 854 775 854 775 807
808
ulong 8 0 18 446 744 073 unsigned
709 551 615 __int64
datetime 8 0 32 535 244 799 __time64_t
(1970.01.01 (3000.12.31
[Link]) [Link])

Integer type values can also be presented as numeric


constants, color literals, date-time literals, character
constants and enumerations.
See also
Conversion Functions, Numeric Type Constants
MQL4 Reference / Language Basics / Data Types / Integer Types / Char,
Short, Int and Long Types

Char, Short, Int and Long Types


char
The char type takes 1 byte of memory (8 bits) and allows
expressing in the binary notation 2^8=256 values. The char
type can contain both positive and negative values. The
range of values is from -128 to 127.

uchar
The uchar integer type also occupies 1 byte of memory, as
well as the char type, but unlike it uchar is intended only for
positive values. The minimum value is zero, the maximum
value is 255. The first letter u in the name of the uchar type
is the abbreviation for unsigned.

short
The size of the short type is 2 bytes (16 bits) and,
accordingly, it allows expressing the range of values equal to
2 to the power 16: 2^16 = 65 [Link] the short type is a
signed one, and contains both positive and negative values,
the range of values is between -32 768 and 32 767.

ushort
The unsigned short type is the type ushort, which also has a
size of 2 bytes. The minimum value is 0, the maximum value
is 65 535.

int
The size of the int type is 4 bytes (32 bits). The minimal
value is -2 147 483 648, the maximal one is 2 147 483 647.
uint
The unsigned integer type is uint. It takes 4 bytes of memory
and allows expressing integers from 0 to 4 294 967 295.

long
The size of the long type is 8 bytes (64 bits). The minimum
value is -9 223 372 036 854 775 808, the maximum value is 9
223 372 036 854 775 807.

ulong
The ulong type also occupies 8 bytes and can store values
from 0 to 18 446 744 073 709 551 615.
Examples:
char ch=12; short sh=-5000;
int in=2445777;

Since the unsigned integer types are not designed for storing
negative values, the attempt to set a negative value can lead
to unexpected consequences. Such a simple script will lead
to an infinite loop:
//--- Infinite loop
void OnStart()
{
uchar u_ch;

for(char ch=-128;ch<128;ch++)
{
u_ch=ch;
Print("ch = ",ch," u_ch = ",u_ch);
}
}

The correct variant is:


//--- Correct variant
void OnStart()
{
uchar u_ch;

for(char ch=-128;ch<=127;ch++)
{
u_ch=ch;
Print("ch = ",ch," u_ch = ",u_ch);
if(ch==127) break;
}
}

Result:
ch= -128 u_ch= 128
ch= -127 u_ch= 129
ch= -126 u_ch= 130
ch= -125 u_ch= 131
ch= -124 u_ch= 132
ch= -123 u_ch= 133
ch= -122 u_ch= 134
ch= -121 u_ch= 135
ch= -120 u_ch= 136
ch= -119 u_ch= 137
ch= -118 u_ch= 138
ch= -117 u_ch= 139
ch= -116 u_ch= 140
ch= -115 u_ch= 141
ch= -114 u_ch= 142
ch= -113 u_ch= 143
ch= -112 u_ch= 144
ch= -111 u_ch= 145
...

Examples:
//--- Negative values can not be stored in unsigned types
uchar u_ch=-120;
ushort u_sh=-5000;
uint u_in=-401280;

Hexadecimal: numbers 0-9, the letters a-f or A-F for the


values of 10-15; start with 0x or 0X.
Examples:
0x0A, 0x12, 0X12, 0x2f, 0xA3, 0Xa3, 0X7C7

See also
Typecasting
MQL4 Reference / Language Basics / Data Types / Integer Types / Character Constants

Character Constants
Characters as elements of a string in MQL4 are indexes in the Unicode character set.
They are hexadecimal values that can be cast into integers, and that can be manipulated
by integer operations like addition and subtraction.
Any single character in quotation marks or a hexadecimal ASCII code of a character as
'\x10' is a character constant and is of ushort type. For example, a record of '0' type is a
numerical value 30, that corresponds to the index of zero in the table of characters.
Example:
void OnStart() {
//--- define character constants
int symbol_0='0';
int symbol_9=symbol_0+9; // get symbol '9'
//--- output values of constants
printf("In a decimal form: symbol_0 = %d, symbol_9 = %d",symbol_0,symbol_9);
printf("In a hexadecimal form: symbol_0 = 0x%x, symbol_9 = 0x%x",symbol_0,symbol_
//--- enter constants into a string
string test="";
StringSetCharacter(test,0,symbol_0);
StringSetCharacter(test,1,symbol_9);
//--- this is what they look like in a string
Print(test);
}

A backslash is a control character for a compiler when dealing with constant strings and
character constants in a source text of a program. Some symbols, for example a single
quote ('), double quotes ("), backslash (\) and control characters can be represented as a
combination of symbols that start with a backslash (\), according to the below table:
Character name Mnemonic code or Record in Numeric value
image MQL4
new line (line LF '\n' 10
feed)
horizontal tab   HT '\t' 9
carriage return CR '\r' 13
backslash \ '\\' 92
single quote   ' '\'' 39
double quote   " '\"' 34
hexadecimal code hhhh '\xhhhh' 1 to 4 hexadecimal characters
decimal code d '\d' decimal number from 0 to
65535

If a backslash is followed by a character other than those described above, result is


undefined.
Example
void OnStart()
{
//--- declare character constants
int a='A';
int b='$';
int c='©'; // code 0xA9
int d='\xAE'; // code of the symbol ®
//--- output print constants
Print(a,b,c,d);
//--- add a character to the string
string test="";
StringSetCharacter(test,0,a);
Print(test);
//--- replace a character in a string
StringSetCharacter(test,0,b);
Print(test);
//--- replace a character in a string
StringSetCharacter(test,0,c);
Print(test);
//--- replace a character in a string
StringSetCharacter(test,0,d);
Print(test);
//--- represent characters as a number
int a1=65;
int b1=36;
int c1=169;
int d1=174;
//--- add a character to the string
StringSetCharacter(test,1,a1);
Print(test);
//--- add a character to the string
StringSetCharacter(test,1,b1);
Print(test);
//--- add a character to the string
StringSetCharacter(test,1,c1);
Print(test);
//--- add a character to the string
StringSetCharacter(test,1,d1);
Print(test);
}

As it was mentioned above, the value of a character constant (or variable) is an index in
the table of characters. Index being an integer, it can be written in different ways.
void OnStart()
{
//---
int a=0xAE; // the code of ® corresponds to the '\xAE' literal
int b=0x24; // the code of $ corresponds to the '\x24' literal
int c=0xA9; // the code of © corresponds to the '\xA9' literal
int d=0x263A; // the code of ☺ corresponds to the '\x263A' literal
//--- show values
Print(a,b,c,d);
//--- add a character to the string
string test="";
StringSetCharacter(test,0,a);
Print(test);
//--- replace a character in a string
StringSetCharacter(test,0,b);
Print(test);
//--- replace a character in a string
StringSetCharacter(test,0,c);
Print(test);
//--- replace a character in a string
StringSetCharacter(test,0,d);
Print(test);
//--- codes of suits
int a1=0x2660;
int b1=0x2661;
int c1=0x2662;
int d1=0x2663;
//--- add a character of spades
StringSetCharacter(test,1,a1);
Print(test);
//--- add a character of hearts
StringSetCharacter(test,2,b1);
Print(test);
//--- add a character of diamonds
StringSetCharacter(test,3,c1);
Print(test);
//--- add a character of clubs
StringSetCharacter(test,4,d1);
Print(test);
//--- Example of character literals in a string
test="Queen\x2660Ace\x2662";
printf("%s",test);
}

The internal representation of a character literal is the ushort type. Character constants
can accept values from 0 to 65535.
See also
StringSetCharacter(), StringGetCharacter(), ShortToString(), ShortArrayToString(),
StringToShortArray()
MQL4 Reference / Language Basics / Data Types / Integer Types / Datetime Type

Datetime Type
The datetime type is intended for storing the date and time as the number of seconds
elapsed since January 01, 1970. This type occupies 8 bytes of memory.
Constants of the date and time can be represented as a literal string, which consists of 6
parts showing the numerical value of the year, month, day (or day, month, year), hours,
minutes and seconds. The constant is enclosed in single quotation marks and starts with
the D character.
Values range from 1 January, 1970 to 31 December, 3000. Either date (year , month, day)
or time (hours, minutes, seconds), or all together can be omitted.
With literal date specification, it is desirable that you specify year, month and day.
Otherwise the compiler returns a warning about an incomplete entry.  
Examples:
datetime NY=D'2015.01.01 00:00'; // Time of beginning of year 2015 datetime d1=D'1
datetime d2=D'19.07.1980 [Link]'; // Equal to D'1980.07.19 [Link]';
datetime d3=D'19.07.1980 12'; // Equal to D'1980.07.19 [Link]'
datetime d4=D'01.01.2004'; // Equal to D'01.01.2004 [Link]'
datetime compilation_date=__DATE__; // Compilation date
datetime compilation_date_time=__DATETIME__; // Compilation date and time
datetime compilation_time=__DATETIME__-__DATE__;// Compilation time
//--- Examples of declarations after which compiler warnings will be returned
datetime warning1=D'[Link]'; // Equal to D'[date of compilation] [Link]'
datetime warning2=D''; // Equal to __DATETIME__

The string representation of datetime type depends on compilation mode:


datetime date=D'2014.03.05 [Link]';
string str="mydate="+date;
//--- str="mydate=1394034418" - without #property strict
//--- str="mydate=2014.03.05 [Link]" - with #property strict

See also
Structure of the Date Type, Date and Time, TimeToString, StringToTime
MQL4 Reference / Language Basics / Data Types / Integer Types /
Color Type

Color Type
The color type is intended for storing information about
color and occupies 4 bytes in memory. The first byte is
ignored, the remaining 3 bytes contain the RGB-
components.
Color constants can be represented in three ways:
literally, by integers, or by name (for named Web-colors
only).
Literal representation consists of three parts representing
numerical rate values of the three main color
components: red, green, blue. The constant starts with C
and is enclosed in single quotes. Numerical rate values of
a color component lie in the range from 0 to 255.
Integer-valued representation is written in a form of
hexadecimal or a decimal number. A hexadecimal number
looks like 0x00BBGGRR, where RR is the rate of the red
color component, GG - of the green one, and BB - of the
blue one. Decimal constants are not directly reflected in
the RGB. They represent a decimal value of the
hexadecimal integer representation.
Specific colors reflect the so-called Web-colors set.
Examples:
//--- Literals C'128,128,128' // Gray
C'0x00,0x00,0xFF' // Blue
//color names
clrRed // Red
clrYellow // Yellow
clrBlack // Black
//--- Integral representations
0xFFFFFF // White
16777215 // White
0x008000 // Green
32768 // Green

See also
Web Colors, ColorToString, StringToColor, Typecasting
MQL4 Reference / Language Basics / Data Types / Integer Types /
Bool Type

Bool Type
The bool type is intended to store the logical values of
true or false, numeric representation of them is 1 or 0,
respectively.
Examples:
bool a = true; bool b = false;
bool c = 1;

The internal representation is a whole number 1 byte


large. It should be noted that in logical expressions you
can use other integer or real types or expressions of these
types - the compiler will not generate any error. In this
case, the zero value will be interpreted as false, and all
other values - as true.
Examples:
int i=5;
double d=-2.5;
if(i) Print("i = ",i," and is set to true");
else Print("i = ",i," and is set to false");

if(d) Print("d = ",d," and has the true value");


else Print("d = ",d," and has the false value");

i=0;
if(i) Print("i = ",i," and has the true value");
else Print("i = ",i," and has the false value");

d=0.0;
if(d) Print("d = ",d," and has the true value");
else Print("d = ",d," and has the false value");

//--- Execution results


// i= 5 and has the true value
// d= -2.5 and has the true value
// i= 0 and has the false value
// d= 0 and has the false value

See also
Boolean Operations, Precedence Rules
MQL4 Reference / Language Basics / Data Types / Integer Types /
Enumerations

Enumerations
Data of the enum type belong to a certain limited set of
data. Defining the enumeration type:
enum name of enumerable type {
list of values
};

The list of values is a list of identifiers of named constants


separated by commas.
Example:
enum months // enumeration of named constants
{
January,
February,
March,
April,
May,
June,
July,
August,
September,
October,
November,
December
};

After the enumeration is declared, a new integer-valued


4-byte data type appears. Declaration of the new data
type allows the compiler to strictly control types of
passed parameters, because enumeration introduces new
named constants. In the above example, the January
named constant has the value of 0, February - 1,
December - 11.
Rule: If a certain value is not assigned to a named
constant that is a member of the enumeration, its new
value will be formed automatically. If it is the first
member of the enumeration, the 0 value will be assigned
to it. For all subsequent members, values will be
calculated based on the value of the previous members by
adding one.
Example:
enum intervals // Enumeration of named constants
{
month=1, // Interval of one month
two_months, // Two months
quarter, // Three months - quarter
halfyear=6, // Half a year
year=12, // Year - 12 months
};

Notes
Unlike C++, the size of the internal representation of
the enumerated type in MQL4 is always equal to 4
bytes. That is, sizeof(months) returns the value 4.
Unlike C++, an anonymous enumeration can't be
declared in MQL4. That is, a unique name must be
always specified after the enum keyword.
See also
Typecasting
MQL4 Reference / Language Basics / Data Types / Real Types (double, float)

Real Types (double, float)


Real types (or floating-point types) represent values with a fractional part. In the MQL4
language there are two types for floating point [Link] method of representation
of real numbers in the computer memory is defined by the IEEE 754 standard and is
independent of platforms, operating systems or programming languages.
Type Size in bytes Minimal Positive Value Maximum Value C++ Analog
float 4 1.175494351e-38 3.402823466e+38 float
double 8 2.2250738585072014e-308 1.7976931348623158e+308 double

The double name means that the accuracy of these numbers is twice the accuracy of the
float type numbers. In most cases, the double type is the most convenient one. In many
cases the limited precision of float numbers is not enough. The reason why the float type
is still used is saving the memory (this is important for large arrays of real numbers).
Floating-point constants consist of an integer part, a point (.) and the fractional part.
The integer and fractional parts are sequences of decimal digits.
Examples:
double a=12.111; double b=-956.1007;
float c =0.0001;
float d =16;

There is a scientific way of writing real constants, often this method of recording is more
compact than the traditional one.
Example:
double c1=1.12123515e-25;
double c2=0.000000000000000000000000112123515; // 24 zero after the decimal point

Print("1. c1 =",DoubleToString(c1,16));
// Result: 1. c1 = 0.0000000000000000

Print("2. c1 =",DoubleToString(c1,-16));
// Result: 2. c1 = 1.1212351499999999e-025

Print("3. c2 =",DoubleToString(c2,-16));
// Result: 3. c2 = 1.1212351499999999e-025

It should be remembered that real numbers are stored in memory with some limited
accuracy in the binary system, while generally the decimal notation is used. That's why
many numbers that are precisely represented in the decimal system can be written only
as an infinite fraction in the binary system.
For example, numbers 0.3 and 0.7 are represented in the computer as infinite fractions,
while the number of 0.25 is stored exactly, because it represents the power of two.
In this regard, it is strongly recommended not to compare two real numbers for equality,
because such a comparison is not correct.
Example:
void OnStart()
{
//---
double three=3.0;
double x,y,z;
x=1/three;
y=4/three;
z=5/three;
if(x+y==z) Print("1/3 + 4/3 == 5/3");
else Print("1/3 + 4/3 != 5/3");
// Result: 1/3 + 4/3 != 5/3
}

If you still need to compare the equality of two real numbers, then you can do this in
two different ways. The first way is to compare the difference between two numbers
with some small quantity that specifies the accuracy of comparison.
Example:
bool EqualDoubles(double d1,double d2,double epsilon)
{
if(epsilon<0) epsilon=-epsilon;
//---
if(d1-d2>epsilon) return false;
if(d1-d2<-epsilon) return false;
//---
return true;
}
void OnStart()
{
double d_val=0.7;
float f_val=0.7;
if(EqualDoubles(d_val,f_val,0.000000000000001)) Print(d_val," equals ",f_val);
else Print("Different: d_val = ",DoubleToString(d_val,16),
" f_val = ",DoubleToString(f_val,16));
// Result: Different: d_val= 0.7000000000000000 f_val= 0.6999999880790710
}

Note that the value of epsilon in the above example can not be less than the predefined
constant DBL_EPSILON. The value of this constant is 2.2204460492503131e-016. The
constant corresponding to the float type is FLT_EPSILON = 1.192092896e-07. The
meaning of these values is the following: it is the lowest value that satisfies the
condition   1.0 + DBL_EPSILON! = 1.0 (for numbers of float type 1.0 + FLT_EPSILON! =
1.0).
The second way offers comparing the normalized difference of two real numbers with
zero. It's meaningless to compare the difference of normalized numbers with a zero,
because any mathematical operation with normalized numbers gives a non-normalized
result.
Example:
bool CompareDoubles(double number1,double number2)
{
if(NormalizeDouble(number1-number2,8)==0) return(true);
else return(false);
}
void OnStart()
{
double d_val=0.3;
float f_val=0.3;
if(CompareDoubles(d_val,f_val)) Print(d_val," equals ",f_val);
else Print("Different: d_val = ",DoubleToString(d_val,16),
" f_val = ",DoubleToString(f_val,16));
// Result: Different: d_val= 0.3000000000000000 f_val= 0.3000000119209290
}

Some operations of the mathematical co-processor can result in the invalid real number,
which can't be used in mathematical operations and operations of comparison, because
the result of operations with invalid real numbers is undefined. For example, when
trying to calculate the arcsine of 2, the result is the negative infinity.
Example:
double abnormal = MathArcsin(2.0);
Print("MathArcsin(2.0) =",abnormal);
// Result: MathArcsin(2.0) = -1.#IND

Besides the minus infinity there is the plus infinity and NaN (not a number). To
determine that this number is invalid, you can use MathIsValidNumber(). According to
the IEEE standard, they have a special machine representation. For example, plus
infinity for the double type has the bit representation of 0x7FF0 0000 0000 0000.
Examples:
struct str1
{
double d;
};
struct str2
{
long l;
};

//--- Start
str1 s1;
str2 s2;
//---
s1.d=MathArcsin(2.0); // Get the invalid number -1.#IND
s2=s1;
printf("1. %f %I64X",s1.d,s2.l);
//---
s2.l=0xFFFF000000000000; // invalid number -1.#QNAN
s1=s2;
printf("2. %f %I64X",s1.d,s2.l);
//---
s2.l=0x7FF7000000000000; // greatest non-number SNaN
s1=s2;
printf("3. %f %I64X",s1.d,s2.l);
//---
s2.l=0x7FF8000000000000; // smallest non-number QNaN
s1=s2;
printf("4. %f %I64X",s1.d,s2.l);
//---
s2.l=0x7FFF000000000000; // greatest non-number QNaN
s1=s2;
printf("5. %f %I64X",s1.d,s2.l);
//---
s2.l=0x7FF0000000000000; // Positive infinity 1.#INF and smallest non-number S
s1=s2;
printf("6. %f %I64X",s1.d,s2.l);
//---
s2.l=0xFFF0000000000000; // Negative infinity -1.#INF
s1=s2;
printf("7. %f %I64X",s1.d,s2.l);
//---
s2.l=0x8000000000000000; // Negative zero -0.0
s1=s2;
printf("8. %f %I64X",s1.d,s2.l);
//---
s2.l=0x3FE0000000000000; // 0.5
s1=s2;
printf("9. %f %I64X",s1.d,s2.l);
//---
s2.l=0x3FF0000000000000; // 1.0
s1=s2;
printf("10. %f %I64X",s1.d,s2.l);
//---
s2.l=0x7FEFFFFFFFFFFFFF; // Greatest normalized number (MAX_DBL)
s1=s2;
printf("11. %.16e %I64X",s1.d,s2.l);
//---
s2.l=0x0010000000000000; // Smallest positive normalized (MIN_DBL)
s1=s2;
printf("12. %.16e %.16I64X",s1.d,s2.l);
//---
s1.d=0.7; // Show that the number of 0.7 - endless fraction
s2=s1;
printf("13. %.16e %.16I64X",s1.d,s2.l);
/*
1. -1.#IND00 FFF8000000000000
2. -1.#QNAN0 FFFF000000000000
3. 1.#SNAN0 7FF7000000000000
4. 1.#QNAN0 7FF8000000000000
5. 1.#QNAN0 7FFF000000000000
6. 1.#INF00 7FF0000000000000
7. -1.#INF00 FFF0000000000000
8. -0.000000 8000000000000000
9. 0.500000 3FE0000000000000
10. 1.000000 3FF0000000000000
11. 1.7976931348623157e+308 7FEFFFFFFFFFFFFF
12. 2.2250738585072014e-308 0010000000000000
13. 6.9999999999999996e-001 3FE6666666666666
*/

See also
DoubleToString, NormalizeDouble, Numeric Type Constants
MQL4 Reference / Language Basics / Data Types / String Type

String Type
The string type is used for storing text strings. A text string is a sequence of characters
in the Unicode format with the final zero at the end of it. A string constant can be
assigned to a string variable. A string constant is a sequence of Unicode characters
enclosed in double quotes: "This is a string constant".
If you need to include a double quote (") into a string, the backslash character (\) must
be put before it. Any special character constants can be written in a string, if the
backslash character (\) is typed before them.
Examples:
string svar="This is a character string"; string svar2=StringSubstr(svar,0,4);
Print("Copyright symbol\t\x00A9");
FileWrite(handle,"This string contains a new line symbols \n");
string MT4path="C:\\Program Files\\MetaTrader 4";

To make the source code readable, long constant strings can be split into parts without
addition operation. During compilation, these parts will be combined into one long
string:
//--- Declare a long constant string
string HTML_head="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
" \"[Link]
"<html xmlns=\"[Link]
"<head>\n"
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=u
"<title>Trade Operations Report</title>\n"
"</head>";
//--- Output the constant string into log
Print(HTML_head);
}

Internal representation of the string type is a structure of 12 bytes long:


#pragma pack(push,1)
struct MqlString
{
int size; // 32-bit integer, contains size of the buffer, allocated for
LPWSTR buffer; // 32-bit address of the buffer, containing the string.
int reserved; // 32-bit integer, reserved.
};
#pragma pack(pop,1)

See also
Conversion Functions, String Functions, FileOpen(), FileReadString(), FileWriteString()
MQL4 Reference / Language Basics / Data Types / Structures, Classes and Interfaces

Structures, Classes and Interfaces


Structures
A structure is a set of elements of any type (except for the void type). Thus, the
structure combines logically related data of different types.
Structure Declaration
The structure data type is determined by the following description:
struct structure_name {
elements_description
};

The structure name can't be used as an identifier (name of a variable or function). It


should be noted that in MQL4 structure elements follow one another directly, without
alignment. In C++ such an order is made to the compiler using the following instruction:
#pragma pack(1)

If you want to do another alignment in the structure, use auxiliary members, "fillers" to
the right size.
Example:
struct trade_settings
{
uchar slippage; // value of the permissible slippage-size 1 byte
char reserved1; // skip 1 byte
short reserved2; // skip 2 bytes
int reserved4; // another 4 bytes are skipped. ensure alignment of the bound
double take; // values of the price of profit fixing
double stop; // price value of the protective stop
};

Such a description of aligned structures is necessary only for transferring to imported dll-
functions.
Attention: This example illustrates incorrectly designed data. It would be better first to
declare the take and stop large data of the double type, and then declare the slippage
member of the uchar type. In this case, the internal representation of data will always
be the same regardless of the value specified in #pragma pack().
If a structure contains variables of the string type and/or object of a dynamic array, the
compiler assigns an implicit constructor to such a structure. This constructor resets all
the structure members of string type and correctly initializes objects of the dynamic
array.
Simple Structures
Structures that do not contain strings or objects of dynamic arrays are called simple
structures; variables of such structures can be freely copied to each other, even if they
are different structures. Variables of simple structures, as well as their array can be
passed as parameters to functions imported from DLL.
Access to Structure Members
The name of a structure becomes a new data type, so you can declare variables of this
type. The structure can be declared only once within a project. The structure members
are accessed using thepoint operation (.).
Example:
struct trade_settings
{
double take; // values of the profit fixing price
double stop; // value of the protective stop price
uchar slippage; // value of the acceptable slippage
};
//--- create up and initialize a variable of the trade_settings type
trade_settings my_set={0.0,0.0,5};
if (input_TP>0) my_set.take=input_TP;

Classes
Classes differ from structures in the following:
the keyword class is used in declaration;
by default, all class members have access specifier private, unless otherwise
indicated. Data-members of the structure have the default type of access as public,
unless otherwise indicated;
class objects always have a table of virtual functions, even if there are no virtual
functions declared in the class. Structures cannot have virtual functions;
the new operator can be applied to class objects; this operator cannot be applied to
structures;
classes can be inherited only from classes, structures can be inherited only from
structures.
Classes and structures can have an explicit constructor and destructor. If your
constructor is explicitly defined, the initialization of a structure or class variable using
the initializing sequence is impossible.
Example:
struct trade_settings
{
double take; // values of the profit fixing price
double stop; // value of the protective stop price
uchar slippage; // value of the acceptable slippage
//--- Constructor
trade_settings() { take=0.0; stop=0.0; slippage=5; }
//--- Destructor
~trade_settings() { Print("This is the end"); }
};
//--- Compiler will generate an error message that initialization is impossible
trade_settings my_set={0.0,0.0,5};

Constructors and Destructors


A constructor is a special function, which is called automatically when creating an object
of a structure or class and is usually used to initialize class members. Further we will
talk only about classes, while the same applies to structures, unless otherwise indicated.
The name of a constructor must match the class name. The constructor has no return
type (you can specify the void type).
Defined class members strings, dynamic arrays and objects that require initialization will
be in any case initialized, regardless of whether there is a constructor.
Each class can have multiple constructors, differing by the number of parameters and
the initialization list. A constructor that requires specifying parameters is called a
parametric constructor.
A constructor with no parameters is called a default constructor. If no constructors are
declared in a class, the compiler creates a default constructor during compilation.
//+------------------------------------------------------------------+
//| Class for working with a date |
//+------------------------------------------------------------------+
class MyDateClass
{
private:
int m_year; // Year
int m_month; // Month
int m_day; // Day of the month
int m_hour; // Hour in a day
int m_minute; // Minutes
int m_second; // Seconds
public:
//--- Default constructor
MyDateClass(void);
//--- Parametric constructor
MyDateClass(int h,int m,int s);
};

 
A constructor can be declared in the class description and then its body can be defined.
For example, two constructors of MyDateClass can be defined the following way:
//+------------------------------------------------------------------+
//| Default constructor |
//+------------------------------------------------------------------+
MyDateClass::MyDateClass(void)
{
//---
MqlDateTime mdt;
datetime t=TimeCurrent(mdt);
m_year=[Link];
m_month=[Link];
m_day=[Link];
m_hour=[Link];
m_minute=[Link];
m_second=[Link];
Print(__FUNCTION__);
}
//+------------------------------------------------------------------+
//| Parametric constructor |
//+------------------------------------------------------------------+
MyDateClass::MyDateClass(int h,int m,int s)
{
MqlDateTime mdt;
datetime t=TimeCurrent(mdt);
m_year=[Link];
m_month=[Link];
m_day=[Link];
m_hour=h;
m_minute=m;
m_second=s;
Print(__FUNCTION__);
}

In the default constructor, all members of the class are filled using the TimeCurrent()
function. In the parametric constructor only hour values are filled in. Other members of
the class (m_year, m_month and m_day) will be automatically initialized with the
current date.
The default constructor has a special purpose when initializing an array of objects of its
class. The constructor, all parameters of which have default values, is not a default
constructor. Here is an example:
//+------------------------------------------------------------------+
//| Class with a default constructor |
//+------------------------------------------------------------------+
class CFoo
{
datetime m_call_time; // Time of the last object call
public:
//--- Constructor with a parameter that has a default value is not a default const
CFoo(const datetime t=0){m_call_time=t;};
//--- Copy constructor
CFoo(const CFoo &foo){m_call_time=foo.m_call_time;};

string ToString(){return(TimeToString(m_call_time,TIME_DATE|TIME_SECONDS));};
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
// CFoo foo; // This variant cannot be used - a default constructor is not set
//--- Possible options to create the CFoo object
CFoo foo1(TimeCurrent()); // An explicit call of a parametric constructor
CFoo foo2(); // An explicit call of a parametric constructor with
CFoo foo3=D'2009.09.09'; // An implicit call of a parametric constructor
CFoo foo40(foo1); // An explicit call of a copy constructor
CFoo foo41=foo1; // An implicit call of a copy constructor
CFoo foo5; // An explicit call of a default constructor (if the
// then a parametric constructor with a default valu
//--- Possible options to receive CFoo pointers
CFoo *pfoo6=new CFoo(); // Dynamic creation of an object and receiving of a
CFoo *pfoo7=new CFoo(TimeCurrent());// Another option of dynamic object creation
CFoo *pfoo8=GetPointer(foo1); // Now pfoo8 points to object foo1
CFoo *pfoo9=pfoo7; // pfoo9 and pfoo7 point to one and the same object
// CFoo foo_array[3]; // This option cannot be used - a default constructo
//--- Show the value of m_call_time
Print("foo1.m_call_time=",[Link]());
Print("foo2.m_call_time=",[Link]());
Print("foo3.m_call_time=",[Link]());
Print("foo4.m_call_time=",[Link]());
Print("foo5.m_call_time=",[Link]());
Print("pfoo6.m_call_time=",[Link]());
Print("pfoo7.m_call_time=",[Link]());
Print("pfoo8.m_call_time=",[Link]());
Print("pfoo9.m_call_time=",[Link]());
//--- Delete dynamically created arrays
delete pfoo6;
delete pfoo7;
//delete pfoo8; // You do not need to delete pfoo8 explicitly, since it points to
//delete pfoo9; // You do not need to delete pfoo9 explicitly. since it points to
}

If you uncomment these strings


//CFoo foo_array[3]; // This variant cannot be used - a default constructor is

or
//CFoo foo_dyn_array[]; // This variant cannot be used - a default constructor is

then the compiler will return an error for them "default constructor is not defined".
If a class has a user-defined constructor, the default constructor is not generated by the
compiler. This means that if a parametric constructor is declared in a class, but a default
constructor is not declared, you can not declare the arrays of objects of this class. The
compiler will return an error for this script:
//+------------------------------------------------------------------+
//| Class without a default constructor |
//+------------------------------------------------------------------+
class CFoo
{
string m_name;
public:
CFoo(string name) { m_name=name;}
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- Get the "default constructor is not defined" error during compilation
CFoo badFoo[5];
}

In this example, the CFoo class has a declared parametric constructor - in such cases,
the compiler does not create a default constructor automatically during compilation. At
the same time when you declare an array of objects, it is assumed that all objects
should be created and initialized automatically. During auto-initialization of an object, it
is necessary to call a default constructor, but since the default constructor is not
explicitly declared and not automatically generated by the compiler, it is impossible to
create such an object. For this reason, the compiler generates an error at the
compilation stage.
There is a special syntax to initialize an object using a constructor. Constructor
initializers (special constructions for initialization) for the members of a struct or class
can be specified in the initialization list.
An initialization list is a list of initializers separated by commas, which comes after the
colon after the list of parameters of a constructor and precedes the body (goes before
an opening brace). There are several requirements:
Initialization lists can be used only in constructors;
Parent members cannot be initialized in the initialization list;
The initialization list must be followed by a definition (implementation) of a function.
Here is an example of several constructors for initializing class members.
//+------------------------------------------------------------------+
//| Class for storing the name of a character |
//+------------------------------------------------------------------+
class CPerson
{
string m_first_name; // First name
string m_second_name; // Second name
public:
//--- An empty default constructor
CPerson() {Print(__FUNCTION__);};
//--- A parametric constructor
CPerson(string full_name);
//--- A constructor with an initialization list
CPerson(string surname,string name): m_second_name(surname), m_f
void PrintName(){PrintFormat("Name=%s Surname=%s",m_first_name,m_second_name);};
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CPerson::CPerson(string full_name)
{
int pos=StringFind(full_name," ");
if(pos>=0)
{
m_first_name=StringSubstr(full_name,0,pos);
m_second_name=StringSubstr(full_name,pos+1);
}
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- Get an error "default constructor is not defined"
CPerson people[5];
CPerson Tom="Tom Sawyer"; // Tom Sawyer
CPerson Huck("Huckleberry","Finn"); // Huckleberry Finn
CPerson *Pooh = new CPerson("Winnie","Pooh"); // Winnie the Pooh
//--- Output values
[Link]();
[Link]();
[Link]();

//--- Delete a dynamically created object


delete Pooh;
}

In this case, the CPerson class has three constructors:


1. An explicit default constructor, which allows creating an array of objects of this class;
2. A constructor with one parameter, which gets a full name as a parameter and divides
it to the name and second name according to the found space;
3. A constructor with two parameters that contains an initialization list. Initializers -
m_second_name(surname) and m_first_name(name).
Note that the initialization using a list has replaced an assignment. Individual members
must be initialized as:
class_member (a list of expressions)

In the initialization list, members can go in any order, but all members of the class will
be initialized according to the order of their announcement. This means that in the third
constructor, first the m_first_name member will be initialized, as it is announced first,
and only after it m_second_name is initialized. This should be taken into account in
cases where the initialization of some members of the class depends on the values in
other class members.
If a default constructor is not declared in the base class, and at the same time one or
more constructors with parameters are declared, you should always call one of the base
class constructors in the initialization list. It goes through the comma as ordinary
members of the list and will be called first during object initialization, no matter where
in the initialization list it is located.
//+------------------------------------------------------------------+
//| Base class |
//+------------------------------------------------------------------+
class CFoo
{
string m_name;
public:
//--- A constructor with an initialization list
CFoo(string name) : m_name(name) { Print(m_name);}
};
//+------------------------------------------------------------------+
//| Class derived from CFoo |
//+------------------------------------------------------------------+
class CBar : CFoo
{
CFoo m_member; // A class member is an object of the parent
public:
//--- A default constructor in the initialization list calls the constructor of a
CBar(): m_member(_Symbol), CFoo("CBAR") {Print(__FUNCTION__);}
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
CBar bar;
}

In this example, when creating the bar object, a default constructor CBar() will be
called, in which first a constructor for the parent CFoo is called, and then comes a
constructor for the m_member class member.
A destructor is a special function that is called automatically when a class object is
destroyed. The name of the destructor is written as a class name with a tilde (~).
Strings, dynamic arrays and objects, requiring deinitialization, will be de-initialized
anyway, regardless of the destructor presence or absence. If there is a destructor, these
actions will be performed after calling the destructor.
Destructors are always virtual, regardless of whether they are declared with the virtual
keyword or not.
Defining Class Methods
Class function-methods can be defined both inside the class and outside the class
declaration. If the method is defined within a class, then its body comes right after the
method declaration.
Example:
class CTetrisShape
{
protected:
int m_type;
int m_xpos;
int m_ypos;
int m_xsize;
int m_ysize;
int m_prev_turn;
int m_turn;
int m_right_border;
public:
void CTetrisShape();
void SetRightBorder(int border) { m_right_border=border; }
void SetYPos(int ypos) { m_ypos=ypos; }
void SetXPos(int xpos) { m_xpos=xpos; }
int GetYPos() { return(m_ypos); }
int GetXPos() { return(m_xpos); }
int GetYSize() { return(m_ysize); }
int GetXSize() { return(m_xsize); }
int GetType() { return(m_type); }
void Left() { m_xpos-=SHAPE_SIZE; }
void Right() { m_xpos+=SHAPE_SIZE; }
void Rotate() { m_prev_turn=m_turn; if(++m_turn>3)
virtual void Draw() { return; }
virtual bool CheckDown(int& pad_array[]);
virtual bool CheckLeft(int& side_row[]);
virtual bool CheckRight(int& side_row[]);
};

Functions from SetRightBorder(int border) to Draw() are declared and defined directly
inside the CTetrisShape class.
The CTetrisShape() constructor and methods CheckDown(int& pad_array[]),
CheckLeft(int& side_row[]) and CheckRight(int& side_row[]) are only declared inside the
class, but not defined yet. Definitions of these functions will be further in the code. In
order to define the method outside the class, the scope resolution operator is used, the
class name is used as the scope.
Example:
//+------------------------------------------------------------------+
//| Constructor of the basic class |
//+------------------------------------------------------------------+
void CTetrisShape::CTetrisShape()
{
m_type=0;
m_ypos=0;
m_xpos=0;
m_xsize=SHAPE_SIZE;
m_ysize=SHAPE_SIZE;
m_prev_turn=0;
m_turn=0;
m_right_border=0;
}
//+------------------------------------------------------------------+
//| Checking ability to move down (for the stick and cube) |
//+------------------------------------------------------------------+
bool CTetrisShape::CheckDown(int& pad_array[])
{
int i,xsize=m_xsize/SHAPE_SIZE;
//---
for(i=0; i<xsize; i++)
{
if(m_ypos+m_ysize>=pad_array[i]) return(false);
}
//---
return(true);
}

Public, Protected and Private Access Modifiers


When developing a new class, it is recommended to restrict access to the members from
the outside. For this purpose keywords private or protected are used. In this case,
hidden data can be accessed only from function-methods of the same class. If the
protected keyword is used, hidden data can be accessed also from methods of classes -
inheritors of this class. The same method can be used to restrict the access to functions-
methods of a class.
If you need to completely open access to members and/or methods of a class, use the
keyword public.
Example:
class CTetrisField
{
private:
int m_score; // Score
int m_ypos; // Current position of the f
int m_field[FIELD_HEIGHT][FIELD_WIDTH]; // Matrix of the well
int m_rows[FIELD_HEIGHT]; // Numbering of the well row
int m_last_row; // Last free row
CTetrisShape *m_shape; // Tetris figure
bool m_bover; // Game over
public:
void CTetrisField() { m_shape=NULL; m_bover=false; }
void Init();
void Deinit();
void Down();
void Left();
void Right();
void Rotate();
void Drop();
private:
void NewShape();
void CheckAndDeleteRows();
void LabelOver();
};

Any class members and methods declared after the specifier public: (and before the
next access specifier) are available in any reference to the class object by the program.
In this example these are the following members: functions CTetrisField(), Init(),
Deinit(), Down(), Left(), Right(), Rotate() and Drop().
Any members that are declared after the access specifier to the elements private: (and
before the next access specifier) are available only to members-functions of this class.
Specifiers of access to elements always end with a colon (:) and can appear in the class
definition many times.
Access to the members of the basis class can be redefined during inheritance in derived
classes.
Modifier 'final'
The use of the 'final' modifier during class declaration prohibits further inheritance from
this class. If the class interface requires no further modifications, or modifications are
not allowed for security reasons, declare this class with the 'final' modifier. In addition,
all the members of the class will also be implicitly considered final.
class CFoo final
{
//--- Class body
};

class CBar : public CFoo


{
//--- Class body
};

If you try to inherit form a class with the 'final' modifier as shown in the above example,
the compiler will return an error:
cannot inherit from 'CFoo' as it has been declared as 'final'
see declaration of 'CFoo'

Unions (union)
Union is a special data type consisting of several variables sharing the same memory
area. Therefore, the union provides the ability to interpret the same bit sequence in two
(or more) different ways. Union declaration is similar to structure declaration and starts
with the union keyword.
union LongDouble
{
long long_value;
double double_value;
};

Unlike the structure, various union members belong to the same memory area. In this
example, the union of LongDouble is declared with long and double type values sharing
the same memory area. Please note that it is impossible to make the union store a long
integer value and a double real value simultaneously (unlike a structure), since
long_value and double_value variables overlap (in memory). On the other hand, an MQL5
program is able to process data containing in the union as an integer (long) or real
(double) value at any time. Therefore, the union allows receiving two (or more) options
for representing the same data sequence.
During the union declaration, the compiler automatically allocates the memory area
sufficient to store the largest type (by volume) in the variable union. The same syntax is
used for accessing the union element as for the structures point operator.
union LongDouble
{
long long_value;
double double_value;
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
LongDouble lb;
//--- get and display the invalid -nan(ind) number
lb.double_value=MathArcsin(2.0);
printf("1. double=%f integer=%I64X",lb.double_value,lb.long_value)
//--- largest normalized value (DBL_MAX)
lb.long_value=0x7FEFFFFFFFFFFFFF;
printf("2. double=%.16e integer=%I64X",lb.double_value,lb.long_value);
//--- smallest positive normalized (DBL_MIN)
lb.long_value=0x0010000000000000;
printf("3. double=%.16e integer=%.16I64X",lb.double_value,lb.long_value);
}
/* Execution result
1. double=-nan(ind) integer=FFF8000000000000
2. double=1.7976931348623157e+308 integer=7FEFFFFFFFFFFFFF
3. double=2.2250738585072014e-308 integer=0010000000000000
*/

Since the unions allow the program to interpret the same memory data in different
ways, they are often used when an unusual type conversion is required.
The unions cannot be involved in the inheritance, and they also cannot have static
members due to their very nature. In all other aspects, the union behaves like a
structure with all its members having a zero offset. The following types cannot be the
union members:
dynamic arrays
strings
pointers to objects and functions
class objects
structure objects having constructors or destructors
structure objects having members from the points 1-5
Similar to classes, the union is capable of having constructors and destructors, as well as
methods. By default, the union members are of public access type. In order to create
private elements, use the private keyword. All these possibilities are displayed in the
example illustrating how to convert a color of the color type to ARGB as does the
ColorToARGB() function.
//+------------------------------------------------------------------+
//| Union for color(BGR) conversion to ARGB |
//+------------------------------------------------------------------+
union ARGB
{
uchar argb[4];
color clr;
//--- constructors
ARGB(color col,uchar a=0){Color(col,a);};
~ARGB(){};
//--- public methods
public:
uchar Alpha(){return(argb[3]);};
void Alpha(const uchar alpha){argb[3]=alpha;};
color Color(){ return(color(clr));};
//--- private methods
private:
//+------------------------------------------------------------------+
//| set the alpha channel value and color |
//+------------------------------------------------------------------+
void Color(color col,uchar alpha)
{
//--- set color to clr member
clr=col;
//--- set the Alpha component value - opacity level
argb[3]=alpha;
//--- interchange the bytes of R and B components (Red and Blue)
uchar t=argb[0];argb[0]=argb[2];argb[2]=t;
};
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- 0x55 means 55/255=21.6 % (0% - fully transparent)
uchar alpha=0x55;
//--- color type is represented as 0x00BBGGRR
color test_color=clrDarkOrange;
//--- values of bytes from the ARGB union are accepted here
uchar argb[];
PrintFormat("0x%.8X - here is how the 'color' type look like for %s, BGR=(%s)",
test_color,ColorToString(test_color,true),ColorToString(test_color));
//--- ARGB type is represented as 0x00RRGGBB, RR and BB components are swapped
ARGB argb_color(test_color);
//--- copy the bytes array
ArrayCopy(argb,argb_color.argb);
//--- here is how it looks in ARGB representation
PrintFormat("0x%.8X - ARGB representation with the alpha channel=0x%.2x, ARGB=(%d,
argb_color.clr,argb_color.Alpha(),argb[3],argb[2],argb[1],argb[0]);
//--- add opacity level
argb_color.Alpha(alpha);
//--- try defining ARGB as 'color' type
Print("ARGB as color=(",argb_color.clr,") alpha channel=",argb_color.Alpha());
//--- copy the bytes array
ArrayCopy(argb,argb_color.argb);
//--- here is how it looks in ARGB representation
PrintFormat("0x%.8X - ARGB representation with the alpha channel=0x%.2x, ARGB=(%d,
argb_color.clr,argb_color.Alpha(),argb[3],argb[2],argb[1],argb[0]);
//--- check with the ColorToARGB() function results
PrintFormat("0x%.8X - result of ColorToARGB(%s,0x%.2x)",ColorToARGB(test_color,alp
ColorToString(test_color,true),alpha);
}
/* Execution result
0x00008CFF - here is how the color type looks for clrDarkOrange, BGR=(255,140,0)
0x00FF8C00 - ARGB representation with the alpha channel=0x00, ARGB=(0,255,140,0)
ARGB as color=(0,140,255) alpha channel=85
0x55FF8C00 - ARGB representation with the alpha channel=0x55, ARGB=(85,255,140,0)
0x55FF8C00 - result of ColorToARGB(clrDarkOrange,0x55)
*/

Interfaces
An interface allows determining specific functionality, which a class can then implement.
In fact, an interface is a class that cannot contain any members, and may not have a
constructor and/or a destructor. All methods declared in an interface are purely virtual,
even without an explicit definition.
An interface is defined using the "interface" keyword. Example:
//--- Basic interface for describing animals
interface IAnimal
{
//--- The methods of the interface have public access by default
void Sound(); // The sound produced by the animal
};
//+------------------------------------------------------------------+
//| The CCat class is inherited from the IAnimal interface |
//+------------------------------------------------------------------+
class CCat : public IAnimal
{
public:
CCat() { Print("Cat was born"); }
~CCat() { Print("Cat is dead"); }
//--- Implementing the Sound method of the IAnimal interface
void Sound(){ Print("meou"); }
};
//+------------------------------------------------------------------+
//| The CDog class is inherited from the IAnimal interface |
//+------------------------------------------------------------------+
class CDog : public IAnimal
{
public:
CDog() { Print("Dog was born"); }
~CDog() { Print("Dog is dead"); }
//--- Implementing the Sound method of the IAnimal interface
void Sound(){ Print("guaf"); }
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- An array of pointers to objects of the IAnimal type
IAnimal *animals[2];
//--- Creating child classes of IAnimal and saving pointers to them into an array
animals[0]=new CCat;
animals[1]=new CDog;
//--- Calling the Sound() method of the basic IAnimal interface for each child
for(int i=0;i<ArraySize(animals);++i)
animals[i].Sound();
//--- Deleting objects
for(int i=0;i<ArraySize(animals);++i)
delete animals[i];
//--- Execution result
/*
Cat was born
Dog was born
meou
guaf
Cat is dead
Dog is dead
*/
}
Like with abstract classes, an interface object cannot be created without inheritance.
An interface can only be inherited from other interfaces and can be a parent for a class.
An interface is always publicly visible.
An interface cannot be declared within a class or structure declaration, but a pointer to
the interface can be saved in a variable of type void *. Generally speaking, a pointer to
an object of any class can be saved into a variable of type void *. In order to convert a
void * pointer to a pointer to an object of a particular class, use the dynamic_cast
operator. If conversion is not possible, the result of the dynamic_cast operation will be
NULL.
 
See also
Object-Oriented Programming
MQL4 Reference / Language Basics / Data Types / Dynamic Array Object

Dynamic Array Object


Dynamic Arrays
Maximum 4-dimension array can be declared. When declaring a dynamic array (an array
of unspecified value in the first pair of square brackets), the compiler automatically
creates a variable of the above structure (a dynamic array object) and provides a code
for the correct initialization.
Dynamic arrays are automatically freed when going beyond the visibility area of the
block they are declared in.
Example:
double matrix[][10][20]; // 3-dimensional dynamic array ArrayResize(matrix,5); // Se

Static Arrays
When all significant array dimensions are explicitly specified, the compiler pre-allocates
the necessary memory size. Such an array is called static. Nevertheless, the compiler
allocates additional memory for the object of a dynamic array, which (object) is
associated with the pre-allocated static buffer (memory part for storing the array).
Creating a dynamic array object is due to the possible need to pass this static array as a
parameter to some function.
Examples:
double stat_array[5]; // 1-dimensional static array
some_function(stat_array);
...
bool some_function(double& array[])
{
if(ArrayResize(array,100)<0) return(false);
...
return(true);
}

Arrays in Structures
When a static array is declared as a member of a structure, a dynamic array object is
not created. This is done to ensure compatibility of data structures used in the Windows
API.
However, static arrays that are declared as members of structures can also be passed to
MQL5 functions. In this case, when passing the parameter, a temporary object of a
dynamic array will be created. Such an object is linked with the static array - member of
structure.
See also
Array Functions, Initialization of Variables, Visibility Scope and Lifetime of Variables,
Creating and Deleting Objects
MQL4 Reference / Language Basics / Data Types / Typecasting

Typecasting
Casting Numeric Types
Often a necessity occurs to convert one numeric type into another. Not all numeric types
can be converted into another. Here is the scheme of allowed casting:

Solid lines with arrows indicate changes that are performed almost without any loss of
information. Instead of the char type, the bool type can be used (both take 1 byte of
memory), instead of type int, the color type can be used (4 bytes), instead of the long
type, datetime can be used (take 8 bytes). The four dashed grey lines, also arrowed,
denote conversions, when the loss of precision can occur. For example, the number of
digits in an integer equal to 123456789 (int) is higher than the number of digits that can
be represented by float.
int n=123456789; float f=n; // the content of f is equal to 1.234567892E8
Print("n = ",n," f = ",f);
// result n= 123456789 f= 123456792.00000

A number converted into float has the same order, but is less accurate. Conversions,
contrary to black arrows, can be performed with possible data loss. Conversions between
char and uchar, short and ushort, int and uint, long and ulong (conversions to both
sides), may lead to the loss of data.
As a result of converting floating point values to integer type, the fractional part is
always deleted. If you want to round off a float to the nearest whole number (which in
many cases is more useful), you should use MathRound().
Example:
//--- Gravitational acceleration
double g=9.8;
double round_g=(int)g;
double math_round_g=MathRound(g);
Print("round_g = ",round_g);
Print("math_round_g = ",math_round_g);
/*
Result:
round_g = 9
math_round_g = 10
*/

If two values are combined by a binary operator, before the operation execution the
operand of a lower type is converted to the higher type in accordance with the priority
given in the below scheme:
The data types char, uchar, short, and ushort unconditionally are converted to the int
type.
Examples:
char c1=3;
//--- First example
double d2=c1/2+0.3;
Print("c1/2 + 0.3 = ",d2);
// Result: c1/2+0.3 = 1.3

//--- Second example


d2=c1/2.0+0.3;
Print("c1/2.0 + 0.3 = ",d2);
// Result: c1/2.0+0.3 = 1.8

The calculated expression consists of two operations. In the first example, the variable
c1 of the char type is converted to a temporary variable of the int type, because the
second operand in the division operation, the constant 2, is of the higher type int. As a
result of the integer division 3/2 we get the value 1, which is of the int type.
In the second operation of the first example, the second operand is the constant 0.3,
which is of the double type, so the result of the first operation is converted into a
temporary variable of the double type with a value of 1.0.
In the second example the variable of the char type c1 is converted to a temporary
variable of the double type, because the second operand in the division operation, the
constant 2.0, is of the double type; no further conversions are made.
 
Typecasting of Numeric Types
In the expressions of the MQL4 language both explicit and implicit typecasting can be
used. The explicit typecasting is written as follows:
var_1 = (type)var_2;

An expression or function execution result can be used as the var_2 variable. The
function style notation of the explicit typecasting is also possible:
var_1 = type(var_2);

Let's consider an explicit typecasting on the basis of the first example.


//--- Third example
double d2=(double)c1/2+0.3;
Print("(double)c1/2 + 0.3 = ",d2);
// Result: (double)c1/2+0.3 = 1.80000000

Before the division operation is performed, the c1 variable is explicitly cast to the
double type. Now the integer constant 2 is cast to the value 2.0 of the double type,
because as a result of converting the first operand has taken the double type. In fact,
the explicit typecasting is a unary operation.
Besides, when trying to cast types, the result may go beyond the permissible range. In
this case, the truncation occurs. For example:
char c;
uchar u;
c=400;
u=400;
Print("c = ",c); // Result c=-112
Print("u = ",u); // Result u=144

Before operations (except for the assignment ones) are performed, the data are
converted into the maximum priority type. Before assignment operations are performed,
the data are cast into the target type.
Examples:
int i=1/2; // no types casting, the result is 0
Print("i = 1/2 ",i);

int k=1/2.0; // the expression is cast to the double type,


Print("k = 1/2 ",k); // then is to the target type of int, the result is 0

double d=1.0/2.0; // no types casting, the result is 0.5


Print("d = 1/2.0; ",d);

double e=1/2.0; // the expression is cast to the double type,


Print("e = 1/2.0; ",e);// that is the same as the target type, the result is 0.5

double x=1/2; // the expression of the int type is cast to the double targe
Print("x = 1/2; ",x); // the result is 0.0

When converting  long/ulong type into double, precision may be lost in case the integer
value is greater than 9223372036854774784 or less than -9223372036854774784.
void OnStart()
{
long l_max=LONG_MAX;
long l_min=LONG_MIN+1;
//--- define the highest integer value, which does not lose accuracy when being cast
while(l_max!=long((double)l_max))
l_max--;
//--- define the lowest integer value, which does not lose accuracy when being cast t
while(l_min!=long((double)l_min))
l_min++;
//--- derive the found interval for integer values
PrintFormat("When casting an integer value to double, it must be "
"within [%I64d, %I64d] interval",l_min,l_max);
//--- now, let's see what happens if the value falls out of this interval
PrintFormat("l_max+1=%I64d, double(l_max+1)=%.f, ulong(double(l_max+1))=%I64d",
l_max+1,double(l_max+1),long(double(l_max+1)));
PrintFormat("l_min-1=%I64d, double(l_min-1)=%.f, ulong(double(l_min-1))=%I64d",
l_min-1,double(l_min-1),long(double(l_min-1)));
//--- receive the following result
// When casting an integer value to double, it should be within [-9223372036854774784
// l_max+1=9223372036854774785, double(l_max+1)=9223372036854774800, ulong(double(l_m
// l_min-1=-9223372036854774785, double(l_min-1)=-9223372036854774800, ulong(double(l
}
 
Typecasting for the String Type
The string type has the highest priority among simple types. Therefore, if one of
operands of an operation is of the string type, the second operand will be cast to a string
automatically. Note that for a string, a single dyadic two-place operation of addition is
possible. The explicit casting of string to any numeric type is allowed.
Examples:
string s1=1.0/8; // the expression is cast to the double type,
Print("s1 = 1.0/8; ",s1); // then is to the target type of string,
// result is "0.12500000" (a string containing 10 characters)

string s2=NULL; // string deinitialization


Print("s2 = NULL; ",s2); // the result is an empty string
string s3="Ticket N"+12345; // the expression is cast to the string type
Print("s3 = \"Ticket N\"+12345",s3);

string str1="true";
string str2="0,255,0";
string str3="2009.06.01";
string str4="1.2345e2";
Print(bool(str1));
Print(color(str2));
Print(datetime(str3));
Print(double(str4));

 
Typecasting of Simple Structure Types
Data of the simple structures type can be assigned to each other only if all the members
of both structures are of numeric types. In this case both operands of the assignment
operation (left and right) must be of the structures type. The member-wise casting is not
performed, a simple copying is done. If the structures are of different sizes, the number
of bytes of the smaller size is copied. Thus the absence of union in MQL4 is
compensated.
Examples:
struct str1
{
double d;
};
//---
struct str2
{
long l;
};
//---
struct str3
{
int low_part;
int high_part;
};
//---
struct str4
{
string s;
};
//+------------------------------------------------------------------+
void OnStart()
{
str1 s1;
str2 s2;
str3 s3;
str4 s4;
//---
s1.d=MathArcsin(2.0); // get the invalid number -1. # IND
s2=s1;
printf("1. %f %I64X",s1.d,s2.l);
//---
s3=s2;
printf("2. high part of long %.8X low part of long %.8X",
s3.high_part,s3.low_part);
//---
s4.s="some constant string";
s3=s4;
printf("3. buffer len is %d constant string address is 0x%.8X",
s3.low_part,s3.high_part);
}

Another example illustrates the method of organizing a custom function for receiving
RGB (Red, Green, Blue) representation from the color type. Create two structures of the
same size but with different contents. For convenience, let's add a function returning
the RGB representation of a color as a string.
#property script_show_inputs
input color testColor=clrBlue;// set color for testing
//--- structure for representing color as RGB
struct RGB
{
uchar blue; // blue component of color
uchar green; // green component of color
uchar red; // red component of color
uchar empty; // this byte is not used
string toString(); // function for receiving a string
};
//--- function for showing color as a string
string RGB::toString(void)
{
string out="("+(string)red+":"+(string)green+":"+(string)blue+")";
return out;
}
//--- structure for storing of the built-in color type
struct builtColor
{
color c;
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- a variable for storing in RGB
RGB colorRGB;
//--- variable for storing the color type
builtColor test;
test.c=testColor;
//--- casting two structures by copying contents
colorRGB=test;
Print("color ",test.c,"=",[Link]());
//---
}

 
Typecasting of Base Class Pointers to Pointers of Derivative Classes
Objects of the open generated class can also be viewed as objects of the corresponding
base class. This leads to some interesting consequences. For example, despite the fact
that objects of different classes, generated by a single base class, may differ
significantly from each other, we can create a linked list (List) of them, as we view them
as objects of the base type. But the converse is not true: the base class objects are not
automatically objects of a derived class.
You can use the explicit casting to convert the base class pointers to the pointers of a
derived class. But you must be fully confident in the admissibility of such a
transformation, because otherwise a critical runtime error will occur and the mql4
program will be stopped.
Dynamic typecasting using dynamic_cast operator
Dynamic typecasting is performed using dynamic_cast operator that can be applied only
to pointers to classes. Type validation is performed at runtime. This means that the
compiler does not check the data type applied for typecasting when dynamic_cast
operator is used. If a pointer is converted to a data type which is not the actual type of
an object, the result is NULL.
dynamic_cast <type-id> ( expression )

The type-id parameter in angle brackets should point to a previously defined class type.
Unlike C++, expression operand type can be of any value except for void.
Example:
class CBar { };
class CFoo : public CBar { };

void OnStart()
{
CBar bar;
//--- dynamic casting of *bar pointer type to *foo pointer is allowed
CFoo *foo = dynamic_cast<CFoo *>(&bar); // no critical error
Print(foo); // foo=NULL
//--- an attempt to explicitly cast a Bar type object reference to a Foo type object
foo=(CFoo *)&bar; // critical runtime error
Print(foo); // this string is not executed
}

See also
Data Types
MQL4 Reference / Language Basics / Data Types / Void Type and NULL Constant

Void Type and NULL Constant


Syntactically the void type is a fundamental type along with types of char, uchar, bool,
short, ushort, int, uint, color, long, ulong, datetime, float, double and string. This type
is used either to indicate that the function does not return any value, or as a function
parameter it denotes the absence of parameters.
The predefined constant variable NULL is of the void type. It can be assigned to
variables of any other fundamental types without conversion. The comparison of
fundamental type variables with the NULL value is allowed.
Example:
//--- If the string is not initialized, then assign our predefined value to it if(some

Also NULL can be compared to pointers to objects created with the new operator.
See also
Variables, Functions
MQL4 Reference / Language Basics / Data Types / User-defined Types

User-defined types
The typedef keyword in C++ allows creating user-defined data types. To do this, simply
specify a new data type name for an already existing data type. The new data type is
not created. A new name for the existing type is defined instead. User-defined types
make applications more flexible: sometimes, it is enough to change typedef instructions
using substitution macros (#define). User-defined types also improve code readability
since it is possible to apply custom names to standard data types using typedef. The
general format of the entry for creating a user-defined type:
typedef type new_name;

Here, type means any acceptable data type, while new_name is a new name of the type.
A new name is set only as an addition (not as a replacement) to an existing type name.
MQL5 allows creating pointers to functions using typedef.

Pointer to the function


A pointer to a function is generally defined in the following format
typedef function_result_type (*Function_name_type)(list_of_input_parameters_types)

where after typedef, the function signature (number and type of input parameters, as
well as a type of a result returned by the function) is set. Below is a simple example of
creating and applying a pointer to a function:
//--- declare a pointer to a function that accepts two int parameters typedef int
//--- TFunc is a type, and it is possible to declare the variable pointer to the func
TFunc func_ptr; // pointer to the function
//--- declare the functions corresponding to the TFunc description
int sub(int x,int y) { return(x-y); } // subtract one number from another
int add(int x,int y) { return(x+y); } // addition of two numbers
int neg(int x) { return(~x); } // invert bits in the variable
//--- the func_ptr variable may store the function address to declare it later
func_ptr=sub;
Print(func_ptr(10,5));
func_ptr=add;
Print(func_ptr(10,5));
func_ptr=neg; // error: neg does not have int (int,int) type
Print(func_ptr(10)); // error: two parameters needed

In this example, the func_ptr variable may receive the sub and add functions since they
have two inputs each of int type as defined in the TFunc pointer to the function. On the
contrary, the neg function cannot be assigned to the func_ptr pointer since its signature
is different.
Arranging event models in the user interface
Pointers to functions allow you to easily create processing of events when creating a user
interface. First, define a pointer to the TAction function to be called by pressing the
button and create three functions according to the TAction description.
//--- create a custom function type
typedef int(*TAction)(string,int);
//+------------------------------------------------------------------+
//| Open the file |
//+------------------------------------------------------------------+
int Open(string name,int id)
{
PrintFormat("%s function called (name=%s id=%d)",__FUNCTION__,name,id);
return(1);
}
//+------------------------------------------------------------------+
//| Save the file |
//+------------------------------------------------------------------+
int Save(string name,int id)
{
PrintFormat("%s function called (name=%s id=%d)",__FUNCTION__,name,id);
return(2);
}
//+------------------------------------------------------------------+
//| Close the file |
//+------------------------------------------------------------------+
int Close(string name,int id)
{
PrintFormat("%s function called (name=%s id=%d)",__FUNCTION__,name,id);
return(3);
}

Then, create the MyButton class from CButton, where we should add the TAction pointer
to the function.
//+------------------------------------------------------------------+
//| Create the button class with the events processing function |
//+------------------------------------------------------------------+
class MyButton: public CButton
{
private:
TAction m_action; // chart events handler
public:
MyButton(void){}
~MyButton(void){}
//--- constructor specifying the button text and the pointer to the events handlin
MyButton(string text, TAction act)
{
Text(text);
m_action=act;
}
//--- set the custom function called from the OnEvent() events handler
void SetAction(TAction act){m_action=act;}
//--- standard chart events handler
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,con
{
if(m_action!=NULL && lparam==Id())
{
//--- call the custom m_action() handler
m_action(sparam,(int)lparam);
return(true);
}
else
//--- return the result of calling the handler from the CButton parent class
return(CButton::OnEvent(id,lparam,dparam,sparam));
}
};

Create the CControlsDialog derivative class from CAppDialog, add the m_buttons array to
it for storing the buttons of the MyButton type, as well as the AddButton(MyButton
&button) and CreateButtons() methods.
//+------------------------------------------------------------------+
//| CControlsDialog class |
//| Objective: graphical panel for managing the application |
//+------------------------------------------------------------------+
class CControlsDialog : public CAppDialog
{
private:
CArrayObj m_buttons; // button array
public:
CControlsDialog(void){};
~CControlsDialog(void){};
//--- create
virtual bool Create(const long chart,const string name,const int subwin,const
//--- add the button
bool AddButton(MyButton &button){return(m_buttons.Add(GetPointer(butt
protected:
//--- create the buttons
bool CreateButtons(void);
};
//+------------------------------------------------------------------+
//| Create the CControlsDialog object on the chart |
//+------------------------------------------------------------------+
bool CControlsDialog::Create(const long chart,const string name,const int subwin,cons
{
if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))
return(false);
return(CreateButtons());
//---
}
//+------------------------------------------------------------------+
//| defines |
//+------------------------------------------------------------------+
//--- indents and gaps
#define INDENT_LEFT (11) // indent from left (with allow
#define INDENT_TOP (11) // indent from top (with allowa
#define CONTROLS_GAP_X (5) // gap by X coordinate
#define CONTROLS_GAP_Y (5) // gap by Y coordinate
//--- for buttons
#define BUTTON_WIDTH (100) // size by X coordinate
#define BUTTON_HEIGHT (20) // size by Y coordinate
//--- for the indication area
#define EDIT_HEIGHT (20) // size by Y coordinate
//+------------------------------------------------------------------+
//| Create and add buttons to the CControlsDialog panel |
//+------------------------------------------------------------------+
bool CControlsDialog::CreateButtons(void)
{
//--- calculate buttons coordinates
int x1=INDENT_LEFT;
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y);
int x2;
int y2=y1+BUTTON_HEIGHT;
//--- add buttons objects together with pointers to functions
AddButton(new MyButton("Open",Open));
AddButton(new MyButton("Save",Save));
AddButton(new MyButton("Close",Close));
//--- create the buttons graphically
for(int i=0;i<m_buttons.Total();i++)
{
MyButton *b=(MyButton*)m_buttons.At(i);
x1=INDENT_LEFT+i*(BUTTON_WIDTH+CONTROLS_GAP_X);
x2=x1+BUTTON_WIDTH;
if(![Link](m_chart_id,m_name+"bt"+[Link](),m_subwin,x1,y1,x2,y2))
{
PrintFormat("Failed to create button %s %d",[Link](),i);
return(false);
}
//--- add each button to the CControlsDialog container
if(!Add(b))
return(false);
}
//--- succeed
return(true);
}

Now, we can develop the program using the CControlsDialog control panel having 3
buttons: Open, Save and Close. When clicking a button, the appropriate function in the
form of the TAction pointer is called.
//--- declare the object on the global level to automatically create it when launchin
CControlsDialog MyDialog;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- now, create the object on the chart
if(![Link](0,"Controls",0,40,40,380,344))
return(INIT_FAILED);
//--- launch the application
[Link]();
//--- application successfully initialized
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- clear comments when the application shuts down
Comment("");
//--- destroy dialog
[Link](reason);
}
//+------------------------------------------------------------------+
//| Expert chart event function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, // event ID
const long& lparam, // event parameter of the long type
const double& dparam, // event parameter of the double type
const string& sparam) // event parameter of the string type
{
//--- call the handler from the parent class (here it is CAppDialog) for the chart ev
[Link](id,lparam,dparam,sparam);
}

The launched application's appearance and button clicking results are provided on the
screenshot.
 
The full source code of the program
//+------------------------------------------------------------------+
//| Panel_Buttons.mq5 |
//| Copyright 2017, MetaQuotes Software Corp. |
//| [Link] |
//+------------------------------------------------------------------+

#property copyright "Copyright 2017, MetaQuotes Software Corp."


#property link "[Link]
#property version "1.00"
#property description "The panel with several CButton buttons"
#include <Controls\[Link]>
#include <Controls\[Link]>
//+------------------------------------------------------------------+
//| defines |
//+------------------------------------------------------------------+
//--- indents and gaps
#define INDENT_LEFT (11) // indent from left (with allow
#define INDENT_TOP (11) // indent from top (with allowa
#define CONTROLS_GAP_X (5) // gap by X coordinate
#define CONTROLS_GAP_Y (5) // gap by Y coordinate
//--- for buttons
#define BUTTON_WIDTH (100) // size by X coordinate
#define BUTTON_HEIGHT (20) // size by Y coordinate
//--- for the indication area
#define EDIT_HEIGHT (20) // size by Y coordinate

//--- create the custom function type


typedef int(*TAction)(string,int);
//+------------------------------------------------------------------+
//| Open the file |
//+------------------------------------------------------------------+
int Open(string name,int id)
{
PrintFormat("%s function called (name=%s id=%d)",__FUNCTION__,name,id);
return(1);
}
//+------------------------------------------------------------------+
//| Save the file |
//+------------------------------------------------------------------+
int Save(string name,int id)
{
PrintFormat("%s function called (name=%s id=%d)",__FUNCTION__,name,id);
return(2);
}
//+------------------------------------------------------------------+
//| Close the file |
//+------------------------------------------------------------------+
int Close(string name,int id)
{
PrintFormat("%s function called (name=%s id=%d)",__FUNCTION__,name,id);
return(3);
}
//+------------------------------------------------------------------+
//| Create the button class with the events processing function |
//+------------------------------------------------------------------+
class MyButton: public CButton
{
private:
TAction m_action; // chart events handler
public:
MyButton(void){}
~MyButton(void){}
//--- constructor specifying the button text and the pointer to the events handlin
MyButton(string text,TAction act)
{
Text(text);
m_action=act;
}
//--- set the custom function called from the OnEvent() events handler
void SetAction(TAction act){m_action=act;}
//--- standard chart events handler
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,con
{
if(m_action!=NULL && lparam==Id())
{
//--- call the custom handler
m_action(sparam,(int)lparam);
return(true);
}
else
//--- return the result of calling the handler from the CButton parent class
return(CButton::OnEvent(id,lparam,dparam,sparam));
}
};
//+------------------------------------------------------------------+
//| CControlsDialog class |
//| Objective: graphical panel for managing the application |
//+------------------------------------------------------------------+
class CControlsDialog : public CAppDialog
{
private:
CArrayObj m_buttons; // button array
public:
CControlsDialog(void){};
~CControlsDialog(void){};
//--- create
virtual bool Create(const long chart,const string name,const int subwin,const
//--- add the button
bool AddButton(MyButton &button){return(m_buttons.Add(GetPointer(butt
protected:
//--- create the buttons
bool CreateButtons(void);
};
//+------------------------------------------------------------------+
//| Create the CControlsDialog object on the chart |
//+------------------------------------------------------------------+
bool CControlsDialog::Create(const long chart,const string name,const int subwin,cons
{
if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))
return(false);
return(CreateButtons());
//---
}
//+------------------------------------------------------------------+
//| Create and add buttons to the CControlsDialog panel |
//+------------------------------------------------------------------+
bool CControlsDialog::CreateButtons(void)
{
//--- calculate buttons coordinates
int x1=INDENT_LEFT;
int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y);
int x2;
int y2=y1+BUTTON_HEIGHT;
//--- add buttons objects together with pointers to functions
AddButton(new MyButton("Open",Open));
AddButton(new MyButton("Save",Save));
AddButton(new MyButton("Close",Close));
//--- create the buttons graphically
for(int i=0;i<m_buttons.Total();i++)
{
MyButton *b=(MyButton*)m_buttons.At(i);
x1=INDENT_LEFT+i*(BUTTON_WIDTH+CONTROLS_GAP_X);
x2=x1+BUTTON_WIDTH;
if(![Link](m_chart_id,m_name+"bt"+[Link](),m_subwin,x1,y1,x2,y2))
{
PrintFormat("Failed to create button %s %d",[Link](),i);
return(false);
}
//--- add each button to the CControlsDialog container
if(!Add(b))
return(false);
}
//--- succeed
return(true);
}
//--- declare the object on the global level to automatically create it when launchin
CControlsDialog MyDialog;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- now, create the object on the chart
if(![Link](0,"Controls",0,40,40,380,344))
return(INIT_FAILED);
//--- launch the application
[Link]();
//--- application successfully initialized
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- clear comments when the application shuts down
Comment("");
//--- destroy dialog
[Link](reason);
}
//+------------------------------------------------------------------+
//| Expert chart event function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, // event ID
const long& lparam, // event parameter of the long type
const double& dparam, // event parameter of the double type
const string& sparam) // event parameter of the string type
{
//--- call the handler from the parent class (here it is CAppDialog) for the chart ev
[Link](id,lparam,dparam,sparam);
}

 
See also
Variables, Functions
MQL4 Reference / Language Basics / Data Types / Object Pointers

Object Pointers
In MQL4, there is a possibility to dynamically create objects of complex type. This is
done by the new operator, which returns a descriptor of the created object. Descriptor
is 8 bytes large. Syntactically, object descriptors in MQL4 are similar to pointers in C++.
Examples:
MyObject* hobject= new MyObject();

In contrast to C++, the hobject variable from example above is not a pointer to memory,
but rather an object descriptor. Furthermore, in MQL5 all objects in function parameters
must be passed by reference. Below are examples of passing objects as function
parameters:
class Foo {
public:
string m_name;
int m_id;
static int s_counter;
//--- constructors and desctructors
Foo(void){Setup("noname");};
Foo(string name){Setup(name);};
~Foo(void){};
//--- initializes object of type Foo
void Setup(string name)
{
m_name=name;
s_counter++;
m_id=s_counter;
}
};
int Foo::s_counter=0;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- declare an object as variable with its automatic creation
Foo foo1;
//--- variant of passing an object by reference
PrintObject(foo1);

//--- declare a pointer to an object and create it using the 'new' operator
Foo *foo2=new Foo("foo2");
//--- variant of passing a pointer to an object by reference
PrintObject(foo2); // pointer to an object is converted automatically by compiler

//--- declare an array of objects of type Foo


Foo foo_objects[5];
//--- variant of passing an array of objects
PrintObjectsArray(foo_objects); // separate function for passing an array of objec

//--- declare an array of pointers to objects of type Foo


Foo *foo_pointers[5];
for(int i=0;i<5;i++)
{
foo_pointers[i]=new Foo("foo_pointer");
}
//--- variant of passing an array of pointers
PrintPointersArray(foo_pointers); // separate function for passing an array of poi

//--- it is obligatory to delete objects created as pointers before termination


delete(foo2);
//--- delete array of pointers
int size=ArraySize(foo_pointers);
for(int i=0;i<5;i++)
delete(foo_pointers[i]);
//---
}
//+------------------------------------------------------------------+
//| Objects are always passed by reference |
//+------------------------------------------------------------------+
void PrintObject(Foo &object)
{
Print(__FUNCTION__,": ",object.m_id," Object name=",object.m_name);
}
//+------------------------------------------------------------------+
//| Passing an array of objects |
//+------------------------------------------------------------------+
void PrintObjectsArray(Foo &objects[])
{
int size=ArraySize(objects);
for(int i=0;i<size;i++)
{
PrintObject(objects[i]);
}
}
//+------------------------------------------------------------------+
//| Passing an array of pointers to object |
//+------------------------------------------------------------------+
void PrintPointersArray(Foo* &objects[])
{
int size=ArraySize(objects);
for(int i=0;i<size;i++)
{
PrintObject(objects[i]);
}
}
//+------------------------------------------------------------------+

 
See also
Variables, Initialization of Variables, Visibility Scope and Lifetime of Variables, Creating
and Deleting Objects
MQL4 Reference / Language Basics / Data Types / References: Modifier & and Keyword this

References: Modifier & and Keyword this


Passing Parameters by Reference
In MQL4 parameters of simple types can be passed both by value and by
reference, while parameters of compound types are always passed by
reference. To inform the compiler that a parameter must be passed by
reference, the ampersand character & is added before the parameter
name.
Passing a parameter by reference means passing the address of the
variable, that's why all changes in the parameter that is passed by
reference will be immediately reflected in the source variable. Using
parameter passing by reference, you can implement return of several
results of a function at the same time. In order to prevent changing of a
parameter passed by reference, use the const modifier.
Thus, if the input parameter of a function is an array, a structure or class
object, symbol '&' is placed in the function header after the variable type
and before its name.
Example
class CDemoClass {
private:
double m_array[];

public:
void setArray(double &array[]);
};
//+------------------------------------------------------------------+
//| filling the array |
//+------------------------------------------------------------------+
void CDemoClass::setArray(double &array[])
{
if(ArraySize(array)>0)
{
ArrayResize(m_array,ArraySize(array));
ArrayCopy(m_array, array);
}
}

In the above example class CDemoClass is declared, which contains the


private member - array m_array[] of double type. Function setArray() is
declared, to which array[] is passed by reference. If the function header
doesn't contain the indication about passing by reference, i.e. doesn't
contain the ampersand character, an error message will be generated at
the attempt to compile such a code.
Despite the fact that the array is passed by reference, we can't assign one
array to another. We need to perform the element-wise copying of
contents of the source array to the recipient array. The presence of & in
the function description is the obligatory condition for arrays and
structures when passed as the function parameter.

Keyword this
A variable of class type (object) can be passed both by reference and by
pointer. As well as reference, the pointer allows having access to an
object. After the object pointer is declared, the new operator should be
applied to it to create and initialize it.
The reserved word this is intended for obtaining the reference of the
object to itself, which is available inside class or structure methods. this
always references to the object, in the method of which it is used, and the
expression GetPointer(this) gives the pointer of the object, whose member
is the function, in which call of GetPointer() is performed. In MQL4
functions can't return objects, but they can return the object pointer.
Thus, if we need a function to return an object, we can return the pointer
of this object in the form of GetPointer(this). Let's add function
getDemoClass() that returns pointer of the object of this class, into the
description of CDemoClass.
class CDemoClass
{
private:
double m_array[];

public:
void setArray(double &array[]);
CDemoClass *getDemoClass();
};
//+------------------------------------------------------------------+
//| filling the array |
//+------------------------------------------------------------------+
void CDemoClass::setArray(double &array[])
{
if(ArraySize(array)>0)
{
ArrayResize(m_array,ArraySize(array));
ArrayCopy(m_array,array);
}
}
//+------------------------------------------------------------------+
//| returns its own pointer |
//+------------------------------------------------------------------+
CDemoClass *CDemoClass::getDemoClass(void)
{
return(GetPointer(this));
}

Structures don't have pointers, operators new and delete can't be applied
to them, GetPointer(this) can't be used.
See also
Object Pointers, Creating and Deleting Objects, Visibility Scope and
Lifetime of Variables
MQL4 Reference / Language Basics / Operations and Expressions

Operations and Expressions


Some characters and character sequences are of a special importance. These are so-
called operation symbols, for example:
+ - * / % Symbols of arithmetic operations && || Symbols of logical operat
= += *= Characters assignment operators

Operation symbols are used in expressions and have sense when appropriate operands
are given to them. Punctuation marks are emphasized, as well. These are parentheses,
braces, comma, colon, and semicolon.
Operation symbols, punctuation marks, and spaces are used to separate language
elements from each other.
This section contains the description of the following topics:
Expressions
Arithmetic Operations
Assignment Operations
Operations of Relation
Boolean Operations
Bitwise Operations
Other Operations
Priorities and Operations Order
MQL4 Reference / Language Basics / Operations and Expressions / Expressions

Expressions
An expression consists of one or more operands and operation symbols. An expression
can be written in several lines.
Examples:
a++; b = 10; // several expressions are located in one line //--- one express
x = (y * z) /
(w + 2) + 127;

An expression that ends with a semicolon (;) is an operator.


See also
Precedence Rules
MQL4 Reference / Language Basics / Operations and Expressions / Arithmetic Operations

Arithmetic Operations
Arithmetic operations include additive and multiplicative operations:
Sum of variables i = j + 2; Difference of variables
Changing the sign x = - x;
Product of variables z = 3 * x;
Division quotient i = j / 5;
Remainder of division minutes = time % 60;
Adding 1 to the variable value i++;
Adding 1 to the variable value ++i;
Subtracting 1 from the variable value k--;
Subtracting 1 from the variable value --k;

Increment and decrement operations are applied only to variables, they can't be applied
to constants. The prefix increment (++i) and decrement (--k) are applied to the variable
right before this variable is used in an expression.
Post-increment (i++) and post-decrement (k--) are applied to the variable right after this
variable is used in an expression.
Important Notice
int i=5;
int k = i++ + ++i;

Computational problems may occur while moving the above expression from one
programming environment to another one (for example, from Borland C++ to MQL4). In
general, the order of computations depends on the compiler implementation. In
practice, there are two ways to implement the post-decrement (post-increment):
1. The post-decrement (post-increment) is applied to the variable after calculating the
whole expression.
2. The post-decrement (post-increment) is applied to the variable immediately at the
operation.
Currently the first way of post-decrement (post-increment) calculation is implemented
in MQL4. But even knowing this peculiarity, it is not recommended to experiment with its
use.
Examples:
int a=3;
a++; // valid expression
int b=(a++)*3; // invalid expression

See also
Precedence Rules
MQL4 Reference / Language Basics / Operations and Expressions / Assignment Operations

Assignment Operations
The value of the expression that includes the given operation is the value of the left
operand after assignment:
Assigning the value of x to the y variable y = x;

The following operations unite arithmetic or bitwise operations with operation of


assignment:
Adding x to the y variable y += x; Subtrac
Multiplying the y variable by x y *= x;
Dividing the y variable by x y /= x;
Reminder of division of the y variable by x y %= x;
Shift of the binary representation of y to the right by x bits y >>= x;
Shift of the binary representation of y to the left by x bits y <<= x;
AND bitwise operation of binary representations of y and x y &= x;
OR bitwise operation of binary representations of y and x y |= x;
Excluding OR bitwise operation of binary representations of y and x y ^= x;

Bitwise operations can be applied to integers only. When performing the operation of the
logical shift of the y representation to the right/left by x bits, the 5 smallest binary
digits of the x value are used, the highest ones are dropped, i.e. the shift is made to 0-
31 bits.
By %= operation (y value by module of x), the result sign is equal to the sign of divided
number.
The assignment operator can be used several times in an expression . In this case the
processing of the expression is performed from left to right:
y=x=3;

First, the variable x will be assigned the value 3, then the y variable will be assigned the
value of x, i.e. also 3.
See also
Precedence Rules
MQL4 Reference / Language Basics / Operations and Expressions / Operations of Relation

Operations of Relation
Boolean FALSE is represented with an integer zero value, while the boolean TRUE is
represented by any non-zero value.
The value of expressions containing operations of relation or logical operations is FALSE
(0) or TRUE (1).
True if a is equal to b a == b; True if a is not equal to b
True if a is less than b a < b;
True if a is greater than b a > b;
True if a is less than or equal to b a <= b;
True if a is greater than or equal to b a >= b;

The equality of two real numbers can't be compared. In most cases, two seemingly
identical numbers can be unequal because of different values in the 15th decimal place.
In order to correctly compare two real numbers, compare the normalized difference of
these numbers with zero.
Example:
bool CompareDoubles(double number1,double number2)
{
if(NormalizeDouble(number1-number2,8)==0) return(true);
else return(false);
}
void OnStart()
{
double first=0.3;
double second=3.0;
double third=second-2.7;
if(first!=third)
{
if(CompareDoubles(first,third))
printf("%.16f and %.16f are equal",first,third);
}
}
// Result: 0.3000000000000000 0.2999999999999998 are equal

See also
Precedence Rules
MQL4 Reference / Language Basics / Operations and Expressions / Boolean Operations

Boolean Operations
Logical Negation NOT (!)
Operand of the logical negation (!) must be of arithmetic type. The result is TRUE (1), if
the operand value is FALSE (0); and it is equal to FALSE (0), if the operand differs from
FALSE (0).
if(!a) Print("not 'a'");

Logical Operation OR (||)


Logical OR operation (||) of x and y values. The expression value is TRUE (1), if x or y
value is true (not null). Otherwise - FALSE (0).
if(x<0 || x>=max_bars) Print("out of range");

Logical Operation AND (&&)


Logical operation AND (&&) of x and y values. The expression value is TRUE (1), if the
values of x and y are true (not null). Otherwise - FALSE (0).
Brief Estimate of Boolean Operations
The scheme of the so called "brief estimate" is applied to boolean operations, i.e. the
calculation of the expression is terminated when the result of the expression can be
precisely estimated.
//+------------------------------------------------------------------+ //| Script prog
//+------------------------------------------------------------------+
void OnStart()
{
//--- the first example of the brief estimate
if(func_false() && func_true())
{
Print("Operation &&: You will never see this expression");
}
else
{
Print("Operation &&: Result of the first expression is false, so the second was
}
//--- the second example of the brief estimate
if(!func_false() || !func_true())
{
Print("Operation ||: Result of the first expression is true, so the second wasn
}
else
{
Print("Operation ||: You will never see this expression");
}
}
//+------------------------------------------------------------------+
//| the function always returns false |
//+------------------------------------------------------------------+
bool func_false()
{
Print("Function func_false()");
return(false);
}
//+------------------------------------------------------------------+
//| the function always returns true |
//+------------------------------------------------------------------+
bool func_true()
{
Print("Function func_true()");
return(true);
}

See also
Precedence Rules
MQL4 Reference / Language Basics / Operations and Expressions /
Bitwise Operations

Bitwise Operations
Complement to One
Complement of the variable value up to one. The value of
the expression contains 1 in all digits where the variable
value contains 0, and 0 in all digits where the variable
contains 1.
b = ~n;

Example:
char a='a',b; b=~a;
Print("a = ",a, " b = ",b);
// The result will be:
// a = 97 b = -98

Right Shift
The binary representation of x is shifted to the right by y
digits. If the value to shift is of the unsigned type, the
logical right shift is made, i.e. the freed left-side bits will
be filled with zeroes.
If the value to shift is of a sign type, the arithmetic right
shift is made, i.e. the freed left-side digits will be filled
with the value of a sign bit (if the number is positive, the
value of the sign bit is 0; if the number is negative, the
value of the sign bit is 1).
x = x >> y;

Example:
char a='a',b='b';
Print("Before: a = ",a, " b = ",b);
//--- shift to the right
b=a>>1;
Print("After: a = ",a, " b = ",b);
// The result will be:
// Before: a = 97 b = 98
// After: a = 97 b = 48

Left Shift
The binary representation of x is shifted to the left by y
digits, the freed right-side digits are filled with zeros.
x = x << y;

Example:
char a='a',b='b';
Print("Before: a = ",a, " b = ",b);
//--- shift to the left
b=a<<1;
Print("After: a = ",a, " b = ",b);
// The result will be:
// Before: a = 97 b = 98
// After: a = 97 b = -62

It is not recommended to shift by the number of bits


larger or equal to the length of the variable shifted,
because the result of such an operation is undefined.
Bitwise AND Operation
The bitwise AND operation of binary-coded x and y
representations. The value of the expression contains a 1
(TRUE) in all digits where both x and y contain non-zero,
and it contains 0 (FALSE) in all other digits.
b = ((x & y) != 0);

Example:
char a='a',b='b';
//--- AND operation
char c=a&b;
Print("a = ",a," b = ",b);
Print("a & b = ",c);
// The result will be:
// a = 97 b = 98
// a & b = 96

Bitwise OR Operation
The bitwise OR operation of binary representations of x
and y. The value of the expression contains 1 in all digits
where x or y does not contain 0, and it contains 0 in all
other digits.
b = x | y;

Example:
char a='a',b='b';
//--- OR operation
char c=a|b;
Print("a = ",a," b = ",b);
Print("a | b = ",c);
// The result will be:
// a = 97 b = 98
// a | b = 99

Bitwise Exclusive Operation OR


The bitwise exclusive OR (eXclusive OR) operation of
binary representations of x and y. The value of the
expression contains a 1 in all digits where x and y have
different binary values, and it contains 0 in all other
digits.
b = x ^ y;

Example:
char a='a', b='b';
//--- Excluding OR operation
char c=a^b;
Print("a = ",a," b = ",b);
Print("a ^ b = ",c);
// The result will be:
// a = 97 b = 98
// a ^ b = 3

Bitwise operations are performed with integers only.


See also
Precedence Rules
MQL4 Reference / Language Basics / Operations and Expressions / Other Operations

Other operations
Indexing ( [] )
When addressing the i-th element of the array, the expression value is the
value of a variable with the serial number i.
Example:
array[i] = 3; // Assign the value of 3 to i-th element of the array.

Only an integer can be index of an array. Four-dimensional and below arrays


are allowed. Each dimension is indexed from 0 to dimension size-1. In
particular case, for a one-dimensional array consisting of 50 elements, the
reference to the first element will look like array [0], that to the last
element will be array [49].
When addressing beyond the array, the executing subsystem will generate a
critical error, and the program will be stopped.

Calling Function with x1, x2 ,..., xn Arguments


Each argument can represent a constant, variable, or expression of the
corresponding type. The arguments passed are separated by commas and
must be inside of parentheses, the opening parenthesis must follow the name
of the called function.
The expression value is the value returned by the function. If the return
value is of void type, such function call cannot be placed to the right in the
assignment operation. Please make sure that the expressions x1,..., xn are
executed exactly in this order.
Example:
int length=1000000; string a="a",b="b",c;
//---Other Operations
int start=GetTickCount(),stop;
long i;
for(i=0;i<length;i++)
{
c=a+b;
}
stop=GetTickCount();
Print("time for 'c = a + b' = ",(stop-start)," milliseconds, i = ",i);

Comma Operation ( , )
Expressions separated by commas are executed from left to right. All side
effects of the left expression calculation can appear before the right
expression is calculated. The result type and value coincide with those of the
right expression. The list of parameters to be passed (see above) can be
considered as an example.
Example:
for(i=0,j=99; i<100; i++,j--) Print(array[i][j]);

Dot Operator ( . )
For the direct access to the public members of structures and classes the dot
operation is used. Syntax:
Variable_name_of_structure_type.Member_name

Example:
struct SessionTime
{
string sessionName;
int startHour;
int startMinutes;
int endHour;
int endMinutes;
} st;
[Link]="Asian";
[Link]=0;
[Link]=0;
[Link]=9;
[Link]=0;

Scope Resolution Operation ( :: )


Each function in a mql4 program has its own execution scope. For example,
the Print() system function is performed in a global scope. Imported functions
are called in the scope of the corresponding import. Method functions of
classes have the scope of the corresponding class. The syntax of the scope
resolution operation is as follows:
[Scope_name]::Function_name(parameters)

If there is no scope name, this is the explicit direction to use the global
scope. If there is no scope resolution operation, the function is sought in the
nearest scope. If there is no function in the local scope, the search is
conducted in the global scope.
The scope resolution operation is also used to define function-class member.
type Class_name::Function_name(parameters_description)
{
// function body
}

Use of several functions of the same name from different execution contexts
in a program may cause ambiguity. The priority order of function calls
without explicit scope specification is the following:
1. Class methods. If no function with the specified name is set in the class,
move to the next level.
2. MQL4 functions. If the language does not have such a function, move to
the next level.
3. User defined global functions. If no function with the specified name is
found, move to the next level.
4. Imported functions. If no function with the specified name is found, the
compiler returns an error.
To avoid the ambiguity of function calls, always explicitly specify the
function scope using the scope resolution operation.
 
Example:
#property script_show_inputs
#import "[Link]"
int GetLastError(void);
#import

class CCheckContext
{
int m_id;
public:
CCheckContext() { m_id=1234; }
protected:
int GetLastError() { return(m_id); }
};
class CCheckContext2 : public CCheckContext
{
int m_id2;
public:
CCheckContext2() { m_id2=5678; }
void Print();
protected:
int GetLastError() { return(m_id2); }
};
void CCheckContext2::Print()
{
::Print("Terminal GetLastError",::GetLastError());
::Print("kernel32 GetLastError",kernel32::GetLastError());
::Print("parent GetLastError",CCheckContext::GetLastError());
::Print("our GetLastError",GetLastError());
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
CCheckContext2 test;
[Link]();
}
//+------------------------------------------------------------------+

Operation of Obtaining Data Type Size or Size of Any Data


Type Object ( sizeof )
Using the sizeof operation, the memory size corresponding to an identifier or
type can be defined. The sizeof operation is of the following format:
Example:
sizeof(expression)
Any identifier, or type name enclosed in brackets can be used as an
expression. Note that the void type name can't be used, and the identifier
cannot belong to the field of bits, or be a function name.
If the expression is the name of a static array (i.e. the first dimension is
given), then the result is the size of the whole array (i.e. the product of the
number of elements and the length of the type). If the expression is the
name of a dynamic array (the first dimension is not specified), the result will
be the size of the object of the dynamic array.
When sizeof is applied to the name of structure or class type, or to the
identifier of the structure or class type, the result is the actual size of the
structure or class.
Example:
struct myStruct
{
char h;
int b;
double f;
} str;
Print("sizeof(str) = ",sizeof(str));
Print("sizeof(myStruct) = ",sizeof(myStruct));

The size is calculated at the compilation stage.


See also
Precedence Rules
 
MQL4 Reference / Language Basics / Operations and Expressions /
Precedence Rules

Precedence Rules
Each group of operations in the table has the same
priority. The higher the priority of operations is, the
higher it is position of the group in the table. The
precedence rules determine the grouping of operations
and operands.
Attention: Precedence of operations in the MQL4
language corresponds to the priority adopted in C++.
Operation Desciption Execution
Order
() Function Call From left to
[] Referencing to an array right
. element
Referencing to a structure
element
! Logical negation Right to left
~ Bitwise negation (complement)
++ Sign changing
-- Increment by one
(type) Decrement by one
sizeof Typecasting
Determining size in bytes
* Multiplication From left to
/ Division right
% Module division
+ Addition From left to
Subtraction right
Operation Desciption Execution
Order
<< Left shift From left to
>> Right shift right
< Less than From left to
<= Less than or equal right
> Greater than
>= Greater than or equal
== Equal From left to
!= Not equal right
& Bitwise AND operation From left to
right
^ Bitwise exclusive OR From left to
right
| Bitwise OR operation From left to
right
&& Logical AND operation From left to
right
|| Logical OR operation From left to
right
?: Conditional Operator Right to left
Operation Desciption Execution
Order
= Assignment Right to left
*= Multiplication with assignment
/= Division with assignment
%= Module with assignment
+= Addition with assignment
-= Subtraction with assignment
<<= Left shift with assignment
>>= Right shift with assignment
&= Bitwise AND with assignment
^= Exclusive OR with assignment
|= Bitwise OR with assignment
, Comma From left to
right

To change the operation execution order, parenthesis that


are of higher priority are used.
 
Precedence Rules for the old version of
MQL4
The precedence rules for the old version of MQL4
language are presented below.
Each group of operations in the table has the same
priority. The higher is the priority, the higher is the
position of the group in the table. The precedence rules
determine the grouping of operations and operands.
Operation Description Execution
Order
Operation Description Execution
Order
() Function call From left to
[] Referencing to an array right
element
! Logical negation From right to
- Sign changing operation left
++ Increment
-- Decrement
~ Bitwise negation
(complement)
& Bitwise operation AND From left to
| Bitwise operation OR right
^ Bitwise operation exclusive
<< OR
>> Left shift
Right shift
* Multiplication From left to
/ Division right
% Module division
+ Addition From left to
- Subtraction right
< Less than From left to
<= Less than or equal right
> Greater than
>= Greater than or equal
== Equal
!= Not equal
|| Logical OR From left to
right
Operation Description Execution
Order
&& Logical AND From left to
right
= Assignment From right to
+= Assignment addition left
-= Assignment subtraction
*= Assignment multiplication
/= Assignment division
%= Assignment module
>>= Assignment right shift
<<= Assignment left shift
&= Assignment bitwise AND
|= Assignment bitwise OR
^= Assignment exclusive OR
, Comma From left to
right

Parentheses that have higher priority are applied to


change the execution order of the operations.
Attention: Priority of performing operations in old MQL4
differs to some extent from that conventional in the C
language.
MQL4 Reference / Language Basics / Operators

Operators
Language operators describe some algorithmic operations that
must be executed to accomplish a task. The program body is a
sequence of such operators. Operators following one by one are
separated by semicolons.
Operator Description
Compound One or more operators of any type, enclosed in
operator {} curly braces {}
Expression Any expression that ends with a semicolon (;)
operator (;)
return operator Terminates the current function and returns
control to the calling program
if-else conditional Is used when it's necessary to make a choice
operator
?: conditional A simple analog of the if-else conditional
operator operator
switch selection Passes control to the operator, which corresponds
operator to the expression value
while loop Performs an operator until the expression
operator checked becomes false. The expression is
checked before each iteration
for loop operator Performs an operator until the expression
checked becomes false. The expression is
checked before each iteration
do-while loop Performs an operator until the expression
operator checked becomes false. The end condition is
checked, after each loop. The loop body is
always executed at least once.
Operator Description
break operator Terminates the execution of the nearest
attached external operator switch, while, do-
while or for
continue operator Passes control to the beginning of the nearest
external loop operator while, do-while or for
new operator Creates an object of the appropriate size and
returns a descriptor of the created object.
delete operator Deletes the object created by the new operator

One operator can occupy one or more lines. Two or more


operators can be located in the same line. Operators that
control over the execution order (if, if-else, switch, while and
for), can be nested into each other.
Example:
if(Month() == 12) if(Day() == 31) Print("Happy New Year!");

See also
Initialization of Variables, Visibility Scope and Lifetime of
Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Operators / Compound Operator

Compound Operator
A compound operator (a block) consists of one or more
operators of any type, enclosed in braces {}. The closing
brace must not be followed by a semicolon (;).
Example:
if(x==0) {
Print("invalid position x = ",x);
return;
}

See also
Initialization of Variables, Visibility Scope and Lifetime
of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Operators / Expression Operator

Expression Operator
Any expression followed by a semicolon (;) is the operator.
Here are some examples of expression operators.

Assignment Operator
Identifier = expression;
x=3; y=x=3;
bool equal=(x==y);

Assignment operator can be used many times in an


expression. In this case, the expression is processed from
left to right:
Function Calling Operator
Function_name (argument1,..., argumentN);
FileClose(file);

Empty Operator
Consists only of a semicolon (;) and is used to denote an
empty body of a control operator.
See also
Initialization of Variables, Visibility Scope and Lifetime
of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Operators / Return Operator

Return Operator
The return operator terminates the current function
execution and returns control to the calling program. The
expression calculation result is returned to the calling
function. The expression can contain an assignment
operator.
Example:
int CalcSum(int x, int y) {
return(x+y);
}

In functions with the void return type, the return operator


without expression must be used:
void SomeFunction()
{
Print("Hello!");
return; // this operator can be removed
}

The right brace of the function means implicit execution


of the return operator without expression.
What can be returned: simple types, simple structures,
object pointers. With   the return operator you can't
return any arrays, class objects, variables of compound
structure type.
See also
Initialization of Variables, Visibility Scope and Lifetime
of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Operators / Conditional
Operator if-else

If-Else Conditional Operator


The IF - ELSE operator is used when a choice must be
made. Formally, the syntax is as follows:
if (expression) operator1
else
operator2

If the expression is true, operator1 is executed and


control is given to the operator that follows operator2
(operator2 is not executed). If the expression is false,
operator2 is executed.
The else part of the if operator can be omitted. Thus, a
divergence may appear in nested if operators with
omitted else part. In this case, else addresses to the
nearest previous if operator in the same block that has no
else part.
Examples:
//--- The else part refers to the second if operator:
if(x>1)
if(y==2) z=5;
else z=6;
//--- The else part refers to the first if operator:
if(x>l)
{
if(y==2) z=5;
}
else z=6;
//--- Nested operators
if(x=='a')
{
y=1;
}
else if(x=='b')
{
y=2;
z=3;
}
else if(x=='c')
{
y=4;
}
else Print("ERROR");

See also
Initialization of Variables, Visibility Scope and Lifetime
of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Operators / Ternary Operator ?:

Ternary Operator ?:
The general form of the ternary operator is as follows:
expression1 ? expression2 : expression3

For the first operand - "expression1" - any expression that results in a bool type value
can be used. If the result is true, then the operator set by the second operand, i.e.
"expression2" is executed.
If the first operand is false, the third operand - "expression3" is performed. The second
and third operands, i.e. "expression2" and "expression3" should return values of one type
and should not be of void type. The result of the conditional operator execution is the
result of expression2 or result of the expression3, depending on the result of
expression1.
//--- normalize difference between open and close prices for a day range double true_r

This entry is equivalent to the following:


double true_range;
if(High==Low)true_range=0; // if High and Low are equal
else true_range=(Close-Open)/(High-Low); // if the range is not null

Operator Use Restrictions


Based on the value of "expression1", the operator must return one of the two values -
either "expression2" or "expression3". There are several limitations to these expressions:
1. Do not mix user-defined type with simple type or enumeration. NULL can be used for
the pointer.
2. If types of values are simple, the operator will be of the maximum type (see Type
casting).
3. If one of the values is an enumeration and the second one is of a numeric type, the
enumeration is replaced by int and the second rule is applied.
4. If both values are enumerations, their types must be identical, and the operator will
be of type enumeration.
Restrictions for the user-defined types (classes or structures):
a. Types must be identical or one should be derived from the other one.
b. If types are not identical (inheritance), then the child is implicitly cast to the parent,
i.e. the operator will be of the parent type.
c. Do not mix object and pointer both expressions must be either objects or pointers.
NULL can be used for the pointer.
Note
Be careful when using the conditional operator as an argument of an overloaded
function, because the type of the result of a conditional operator is defined at the time
of program compilation. And this type is determined as the larger of the types
"expression2" and "expression3".
Example:
void func(double d) { Print("double argument: ",d); }
void func(string s) { Print("string argument: ",s); }

bool Expression1=true;
double Expression2=M_PI;
string Expression3="3.1415926";

void OnStart()
{
func(Expression2);
func(Expression3);

func(Expression1?Expression2:Expression3); // warning on implicit casting to str


func(!Expression1?Expression2:Expression3); // warning on implicit casting to str
}

// Result:
// double argument: 3.141592653589793
// string argument: 3.1415926
// string argument: 3.141592653589793
// string argument: 3.1415926

See also
Initialization of Variables, Visibility Scope and Lifetime of Variables, Creating and
Deleting Objects
MQL4 Reference / Language Basics / Operators / Switch Operator

Switch Operator
Compares the expression value with constants in all the
case variants and passes control to the operator that
corresponds to the expression value. Each variant of case
can be marked with an integer constant, a literal constant
or a constant expression. The constant expression can't
contain variables or function calls. Expression of the
switch operator must be of integer type.
switch(expression) {
case constant: operators
case constant: operators
...
default: operators
}

Operators marked by the default label are executed if


none of the constants in case operators is equal to the
expression value. The default variant should not be
necessarily declared and should not be necessarily the last
one. If none of the constants corresponds to the
expression value and the default variant is not available,
no actions are executed.
The case keyword with a constant are just labels, and if
operators are executed for some case variant, the
program will further execute the operators of all
subsequent variants until the break operator occurs. It
allows to bind a sequence of operators with several
variants.
A constant expression is calculated during compilation. No
two constants in one switch operator can have the same
value.
Examples:
//--- First example
switch(x)
{
case 'A':
Print("CASE A");
break;
case 'B':
case 'C':
Print("CASE B or C");
break;
default:
Print("NOT A, B or C");
break;
}

//--- Second example


string res="";
int i=0;
switch(i)
{
case 1:
res=i;break;
default:
res="default";break;
case 2:
res=i;break;
case 3:
res=i;break;
}
Print(res);
/*
Result
default
*/

See also
Initialization of Variables, Visibility Scope and Lifetime
of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Operators / Loop Operator while

While Loop Operator


The while operator consists of a checked expression and
the operator, which must be fulfilled:
while(expression) operator;

If the expression is true, the operator is executed until


the expression becomes false. If the expression is false,
the control is passed to the next operator. The expression
value is defined before the operator is executed.
Therefore, if the expression is false from the very
beginning, the operator will not be executed at all.
Note
If it is expected that a large number of iterations will be
handled in a loop, it is advisable that you check the fact
of forced program termination using the IsStopped()
function.
Example:
while(k<n && !IsStopped())
{
y=y*x;
k++;
}

See also
Initialization of Variables, Visibility Scope and Lifetime
of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Operators / Loop Operator for

For Loop Operator


The for operator consists of three expressions and an
executable operator:
for(expression1; expression2; expression3) operator;

Expression1 describes the loop initialization. Expression2


checks the conditions of the loop termination. If it is true,
the loop body for is executed. The loop repeats
expression2 until it becomes false. If it is false, the loop is
terminated, and control is given to the next operator.
Expression3 is calculated after each iteration.
The for operator is equivalent to the following succession
of operators:
expression1;
while(expression2)
{
operator;
expression3;
};

Any of the three or all three expressions can be absent in


the for operator, but the semicolons (;) that separate
them must not be omitted. If expression2 is omitted, it is
considered constantly true. The for(;;) operator is a
continuous loop, equivalent to the while(1) operator. Each
expression 1 or 3 can consist of several expressions
combined by a comma operator ','.
Note
If it is expected that a large number of iterations will be
handled in a loop, it is advisable that you check the fact
of forced program termination using the IsStopped()
function.
Examples:
for(x=1;x<=7000; x++)
{
if(IsStopped())
break;
Print(MathPower(x,2));
}
//--- Another example
for(;!IsStopped();)
{
Print(MathPower(x,2));
x++;
if(x>10) break;
}
//--- Third example
for(i=0,j=n-l;i<n && !IsStopped();i++,j--) a[i]=a[j];

See also
Initialization of Variables, Visibility Scope and Lifetime
of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Operators / Loop Operator do while

Loop Operator do while


The for and while loops check the termination at the beginning, not at the end
of a loop. The third loop operator do - while checks the condition of
termination at the end, after each loop iteration. The loop body is always
executed at least once.
do operator;
while(expression);

First the operator is executed, then the expression is calculated. If it is true,


then the operator is executed again, and so on. If the expression becomes false,
the loop terminates.
Note
If it is expected that a large number of iterations will be handled in a loop, it is
advisable that you check the fact of forced program termination using the
IsStopped() function.
Example:
//--- Calculate the Fibonacci series
int counterFibonacci=15;
int i=0,first=0,second=1;
int currentFibonacciNumber;
do
{
currentFibonacciNumber=first+second;
Print("i = ",i," currentFibonacciNumber = ",currentFibonacciNumber);
first=second;
second=currentFibonacciNumber;
i++; // without this operator an infinite loop will appear!
}
while(i<counterFibonacci && !IsStopped());

See also
Initialization of Variables, Visibility Scope and Lifetime of Variables, Creating
and Deleting Objects
MQL4 Reference / Language Basics / Operators / Break Operator

Break Operator
The break operator terminates the execution of the nearest nested
outward switch, while, do-while or for operator. The control is passed to
the operator that follows the terminated one. One of the purposes of
this operator is to finish the looping execution when a certain value is
assigned to a variable.
Example:
//--- searching for the first zero element for(i=0;i<array_size;i++)
if(array[i]==0)
break;

See also
Initialization of Variables, Visibility Scope and Lifetime of Variables,
Creating and Deleting Objects
MQL4 Reference / Language Basics / Operators / Continue Operator

Continue Operator
The continue operator passes control to the beginning of
the nearest outward loop while, do-while or for operator,
the next iteration being called. The purpose of this
operator is opposite to that of break operator.
Example:
//--- Sum of all nonzero elements int func(int array[])
{
int array_size=ArraySize(array);
int sum=0;
for(int i=0;i<array_size; i++)
{
if(a[i]==0) continue;
sum+=a[i];
}
return(sum);
}

See also
Initialization of Variables, Visibility Scope and Lifetime of
Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Operators / Object Create Operator new

Object Create Operator new


The new operator automatically creates an object of a corresponding size, calls the
object constructor and returns a descriptor of created object. In case of failure, the
operator returns a null descriptor that can be compared with the NULL constant.
The new operator can be applied only to class objects. It can't be applied to structures.
The operator shall not be used to create arrays of objects. To do this, use the
ArrayResize() function.
Example:
//+------------------------------------------------------------------+ //| Figure crea
//+------------------------------------------------------------------+
void CTetrisField::NewShape()
{
m_ypos=HORZ_BORDER;
//--- randomly create one of the 7 possible shapes
int nshape=rand()%7;
switch(nshape)
{
case 0: m_shape=new CTetrisShape1; break;
case 1: m_shape=new CTetrisShape2; break;
case 2: m_shape=new CTetrisShape3; break;
case 3: m_shape=new CTetrisShape4; break;
case 4: m_shape=new CTetrisShape5; break;
case 5: m_shape=new CTetrisShape6; break;
case 6: m_shape=new CTetrisShape7; break;
}
//--- draw
if(m_shape!=NULL)
{
//--- pre-settings
m_shape.SetRightBorder(WIDTH_IN_PIXELS+VERT_BORDER);
m_shape.SetYPos(m_ypos);
m_shape.SetXPos(VERT_BORDER+SHAPE_SIZE*8);
//--- draw
m_shape.Draw();
}
//---
}

It should be noted that object descriptor is not a pointer to memory address.


An object created with the new operator must be explicitly removed using the delete
operator.
See also
Initialization of Variables, Visibility Scope and Lifetime of Variables, Creating and
Deleting Objects
MQL4 Reference / Language Basics / Operators / Object Delete
Operator delete

Object Delete Operator delete


The delete operator deletes an object created by the new
operator, calls the corresponding class destructor and
frees up memory occupied by the object. A real
descriptor of an existing object is used as an operand.
After the delete operation is executed, the object
descriptor becomes invalid.
Example:
//--- delete figure delete m_shape;
m_shape=NULL;
//--- create a new figure
NewShape();

See also
Initialization of Variables, Visibility Scope and Lifetime
of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Functions

Functions
Every task can be divided into subtasks, each of which can either be directly
represented in the form of a code, or divided into smaller sub-tasks. This method is
called stepwise refinement. Functions are used for writing the code of sub-tasks to
be solved. The code that describes what a function does is called function definition:
function_header {
instructions
}

All that is before the first brace is the header of the function definition, and what is
between braces is the body of the function definition. The function header includes a
description of the return value type, name (identifier) and formal parameters.  The
number of parameters passed to the function is limited and cannot exceed 64.
The function can be called from other parts of the program as many times as
necessary. In fact, the return type, function identifier and parameter types
constitute the function prototype.
Function prototype is the function declaration, but not its definition. Due to the
explicit declaration of the return type and a list of argument types, the strict type
checking and implicit typecasting are possible during function calls. Very often
function declarations are used in classes to improve the code readability.
The function definition must exactly match its declaration. Each declared function
must be defined.
Example:
double // return value type
linfunc (double a, double b) // function name and parameter list
{
// composite operator
return (a + b); // return value
}

The return operator can return the value of an expression located in this operator. If
necessary, the expression value is converted to the function result type. What can be
returned: simple types, simple structures, object pointers. With  the return operator
you can't return any arrays, class objects, variables of compound structure type.
A function that returns no value should be described as that of void type.
Example:
void errmesg(string s)
{
Print("error: "+s);
}
Parameters passed to the function can have default values, which are defined by
constants of that type.
Example:
int somefunc(double a,
double d=0.0001,
int n=5,
bool b=true,
string s="passed string")
{
Print("Required parameter a = ",a);
Print("Pass the following parameters: d = ",d," n = ",n," b = ",b," s = ",s);
return(0);
}

If any of parameters has a default value, all subsequent parameters must also have
default values.
Example of incorrect declaration:
int somefunc(double a,
double d=0.0001, // default value 0.0001 declared
int n, // default value is not specified !
bool b, // default value is not specified !
string s="passed string")
{
}

See also
Overload, Virtual Functions, Polymorphism
MQL4 Reference / Language Basics / Functions / Function Call

Function Call
If a name that has not been described before, appears in the expression and is followed
by the left parenthesis, it is contextually considered as the name of a function.
function_name (x1, x2,..., xn)

Arguments (formal parameters) are passed by value, i.e. each expression x1,..., xn is
calculated, and the value is passed to the function. The order of expressions calculation
and the order of values loading are not guaranteed. During the execution, the system
checks the number and type of arguments passed to the function. Such way of
addressing to the function is called a value call.
Function call is an expression, the value of which is the value returned by the function.
The function type described above must correspond with the type of the return value.
The function can be declared or described in any part of the program on the global
scope, i.e., outside other functions. The function cannot be declared or described inside
of another function.
Examples:
int start() {
double some_array[4]={0.3, 1.4, 2.5, 3.6};
double a=linfunc(some_array, 10.5, 8);
//...
}
double linfunc(double x[], double a, double b)
{
return (a*x[0] + b);
}

At calling of a function with default parameters, the list of parameters to be passed can
be limited, but not before the first default parameter.
Examples:
void somefunc(double init,
double sec=0.0001, //set default values
int level=10);
//...
somefunc(); // Wrong call. The first parameter must be presented
somefunc(3.14); // Correct call
somefunc(3.14,0.0002); // Correct call
somefunc(3.14,0.0002,10); // Correct call

When calling a function, one may not skip parameters, even those having default values:
somefunc(3.14, , 10); // Wrong call -> the second parameter was skipped.

Use of several functions of the same name from different execution contexts in a
program may cause ambiguity. To avoid the ambiguity of function calls, always explicitly
specify the function scope using scope resolution operation.
See also
Overload, Virtual Functions, Polymorphism
MQL4 Reference / Language Basics / Functions / Passing Parameters

Passing Parameters
There are two methods, by which the machine language can pass arguments to a
subprogram (function). The first method is to send a parameter by value. This method
copies the argument value into a formal function parameter. Therefore, any changes in
this parameter within the function have no influence on the corresponding call
argument.
//+------------------------------------------------------------------+ //| Passing par
//+------------------------------------------------------------------+
double FirstMethod(int i,int j)
{
double res;
//---
i*=2;
j/=2;
res=i+j;
//---
return(res);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
int a=14,b=8;
Print("a and b before call:",a," ",b);
double d=FirstMethod(a,b);
Print("a and b after call:",a," ",b);
}
//--- Result of script execution
// a and b before call: 14 8
// a and b after call: 14 8

The second method is to pass by reference. In this case, reference to a parameter (not
its value) is passed to a function parameter. Inside the function, it is used to refer to the
actual parameter specified in the call. This means that the parameter changes will
affect the argument used to call the function.
//+------------------------------------------------------------------+
//| Passing parameters by reference |
//+------------------------------------------------------------------+
double SecondMethod(int &i,int &j)
{
double res;
//---
i*=2;
j/=2;
res=i+j;
//---
return(res);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
int a=14,b=8;
Print("a and b before call:",a," ",b);
double d=SecondMethod(a,b);
Print("a and b after call:",a," ",b);
}
//+------------------------------------------------------------------+
//--- result of script execution
// a and b before call: 14 8
// a and b after call: 28 4

MQL4 uses both methods, with one exception: arrays, structure type variables and class
objects are always passed by reference. In order to avoid changes in actual parameters
(arguments passed at function call) use the access specifier const. When trying to
change the contents of a variable declared with the const specifier, the compiler will
generate an error.
Note
It should be noted that parameters are passed to a function in reversed order, i.e., first
the last parameter is calculated and passed, and then the last but one, etc. The last
calculated and passed parameter is the one that stands first after opening parenthesis.
Example:
void OnStart()
{
//---
int a[]={0,1,2};
int i=0;

func(a[i],a[i++],"First call (i = "+string(i)+")");


func(a[i++],a[i],"Second call (i = "+string(i)+")");
// Result:
// First call (i = 0) : par1 = 1 par2 = 0
// Second call (i = 1) : par1 = 1 par2 = 1

}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void func(int par1,int par2,string comment)
{
Print(comment,": par1 = ",par1," par2 = ",par2);
}

In first call (see example above) the i variable is first used in strings concatenation:
"First call (i = "+string(i)+")"

Here its value doesn't change. Then the i variable is used in calculation of the a[i++]
array element, i.e. when array element with index i is accessed, the i variable is
incremented. And only after that the first parameter with changed value of i variable is
calculated.
In the second call the same value of i (calculated on the first phase of function calling) is
used when calculating all three parameters. Only after the first parameters is calculated
the i variable is changed again.
See also
Visibility Scope and Lifetime of Variables, Overload, Virtual Functions, Polymorphism
MQL4 Reference / Language Basics / Functions / Function Overloading

Function Overloading
Usually the function name tends to reflect its main purpose. As a rule, readable
programs contain various well selected identifiers. Sometimes different functions are
used for the same purposes. Let's consider, for example, a function that calculates the
average value of an array of double precision numbers and the same function, but
operating with an array of integers. Both are convenient to be called AverageFromArray:
//+------------------------------------------------------------------+ //| The calcula
//+------------------------------------------------------------------+
double AverageFromArray(const double & array[],int size)
{
if(size<=0) return 0.0;
double sum=0.0;
double aver;
//---
for(int i=0;i<size;i++)
{
sum+=array[i]; // Summation for the double
}
aver=sum/size; // Just divide the sum by the number
//---
Print("Calculation of the average for an array of double type");
return aver;
}
//+------------------------------------------------------------------+
//| The calculation of average for an array of int type |
//+------------------------------------------------------------------+
double AverageFromArray(const int & array[],int size)
{
if(size<=0) return 0.0;
double aver=0.0;
int sum=0;
//---
for(int i=0;i<size;i++)
{
sum+=array[i]; // Summation for the int
}
aver=(double)sum/size;// Give the amount of type double, and divide
//---
Print("Calculation of the average for an array of int type");
return aver;
}

Each function contains the message output via the Print() function;
Print("Calculation of the average for an array of int type");

The compiler selects a necessary function in accordance with the types of arguments and
their quantity. The rule, according to which the choice is made, is called the signature
matching algorithm. A signature is a list of types used in the function declaration.
Example:
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
int a[5]={1,2,3,4,5};
double b[5]={1.1,2.2,3.3,4.4,5.5};
double int_aver=AverageFromArray(a,5);
double double_aver=AverageFromArray(b,5);
Print("int_aver = ",int_aver," double_aver = ",double_aver);
}
//--- Result of the script
// Calculate the average for an array of int type
// Calculate the average for an array of double type
// int_aver= 3.00000000 double_aver= 3.30000000

Function overloading is a process of creating several functions with the same name, but
different parameters. This means that in overloaded variants of a function, the number
of arguments and/or their type must be different. A specific function variant is selected
based on the correspondence of the list of arguments when calling the function, to the
list of parameters in the function declaration.
When an overloaded function is called, the compiler must have an algorithm to select
the appropriate function. The algorithm that performs this choice depends on castings of
what types are present. The best correspondence must be unique. An overloaded
function must be the best match among all the other variants for at least one argument.
At the same time it must match for all other arguments not worse than other variants.
Below is a matching algorithm for each argument.

Algorithm of Choosing an Overloaded Function


1. Use strict matching (if possible).
2. Try standard type increase.
3. Try standard typecasting.
The standard type increase is better than other standard conversions. Increase is the
conversion of float to double, of bool, char, short or enum to int. Typecasting of arrays
of similar integer types also belongs to typecasting. Similar types are: bool, char, uchar,
since all the three types are single-byte integers; double-byte integers short and ushort;
4-byte integers int, uint, and color; long, ulong, and datetime.
Of course, the strict matching is the best. To achieve such a consistency typecasting can
be used. The compiler cannot cope with ambiguous situations. Therefore you should not
rely on subtle differences of types and implicit conversions that make the overloaded
function unclear.
If you doubt, use explicit conversion to ensure strict compliance.
Examples of overloaded functions in MQL4 can be seen in the example of ArrayInitialize()
functions.
Function overloading rules apply to overload of class methods.
 
Overloading of system functions is allowed, but it should be observed that the compiler
is able to accurately select the necessary function. For example, we can overload the
system function MathMax() in 4 different ways, but only two variants are correct.
Example:
// 1. overload is allowed - function differs from built-in MathMax() function in the
double MathMax(double a,double b,double c);

// 2. overload is not allowed!


// number of parameters is different, but the last has a default value
// this leads to the concealment of the system function when calling, which is unacce
double MathMax(double a,double b,double c=DBL_MIN);

// 3. overload is allowed - normal overload by type of parameters a and b


double MathMax(int a,int b);

// 4. overload is not allowed!


// the number and types of parameters are the same as in original double MathMax(doub
int MathMax(double a,double b);

See also
Overload, Virtual Functions, Polymorphism
MQL4 Reference / Language Basics / Functions / Operation Overloading

Operation Overloading
For ease of code reading and writing, overloading of some operations is allowed.
Overloading operator is written using the keyword operator. The following operators can
be overloaded:
binary +,-,/,*,%,<<,>>,==,!=,<,>,<=,>=,=,+=,-=,/=,*=,%=,&=,|=,^=,
<<=,>>=,&&,||,&,|,^
unary +,-,++,--,!,~
assignment operator =
indexing operator []
 
Operation overloading allows the use of the operating notation (written in the form of
simple expressions) for complex objects - structures and classes. Writing expressions
using overloaded operations simplifies the view of the source code, because a more
complex implementation is hidden.
For example, consider complex numbers, which consist of real and imaginary parts. They
are widely used in mathematics. The MQL4 language has no data type to represent
complex numbers, but it is possible to create a new data type in the form of a structure
or class. Declare the complex structure and define four methods that implement four
arithmetic operations:
//+------------------------------------------------------------------+ //| A structure
//+------------------------------------------------------------------+
struct complex
{
double re; // Real part
double im; // Imaginary part
//--- Constructors
complex():re(0.0),im(0.0) { }
complex(const double r):re(r),im(0.0) { }
complex(const double r,const double i):re(r),im(i) { }
complex(const complex &o):re([Link]),im([Link]) { }
//--- Arithmetic operations
complex Add(const complex &l,const complex &r) const; // Addition
complex Sub(const complex &l,const complex &r) const; // Subtraction
complex Mul(const complex &l,const complex &r) const; // Multiplication
complex Div(const complex &l,const complex &r) const; // Division
};

Now, in our code we can declare variables representing complex numbers, and work with
them.
For example:
void OnStart()
{
//--- Declare and initialize variables of a complex type
complex a(2,4),b(-4,-2);
PrintFormat("a=%.2f+i*%.2f, b=%.2f+i*%.2f",[Link],[Link],[Link],[Link]);
//--- Sum up two numbers
complex z;
z=[Link](a,b);
PrintFormat("a+b=%.2f+i*%.2f",[Link],[Link]);
//--- Multiply two numbers
z=[Link](a,b);
PrintFormat("a*b=%.2f+i*%.2f",[Link],[Link]);
//--- Divide two numbers
z=[Link](a,b);
PrintFormat("a/b=%.2f+i*%.2f",[Link],[Link]);
//---
}

But it would be more convenient to use usual operators "+", "-", "*" and "/" for ordinary
arithmetic operations with complex numbers.
Keyword operator is used for defining a member function that performs type conversion.
Unary and binary operations for class object variables can be overloaded as non-static
member functions. They implicitly act on the class object.
Most binary operations can be overloaded like regular functions that take one or both
arguments as a class variable or a pointer to an object of this class. For our type
complex, overloading in the declaration will look like this:
//--- Operators
complex operator+(const complex &r) const { return(Add(this,r)); }
complex operator-(const complex &r) const { return(Sub(this,r)); }
complex operator*(const complex &r) const { return(Mul(this,r)); }
complex operator/(const complex &r) const { return(Div(this,r)); }

The full example of the script:


//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- Declare and initialize variables of type complex
complex a(2,4),b(-4,-2);
PrintFormat("a=%.2f+i*%.2f, b=%.2f+i*%.2f",[Link],[Link],[Link],[Link]);
//[Link]=5;
//[Link]=1;
//[Link]=-1;
//[Link]=-5;
//--- Sum up two numbers
complex z=a+b;
PrintFormat("a+b=%.2f+i*%.2f",[Link],[Link]);
//--- Multiply two numbers

z=a*b;
PrintFormat("a*b=%.2f+i*%.2f",[Link],[Link]);
//--- Divide two numbers
z=a/b;
PrintFormat("a/b=%.2f+i*%.2f",[Link],[Link]);
//---
}
//+------------------------------------------------------------------+
//| A structure for operations with complex numbers |
//+------------------------------------------------------------------+
struct complex
{
double re; // Real part
double im; // Imaginary part
//--- Constructors
complex():re(0.0),im(0.0) { }
complex(const double r):re(r),im(0.0) { }
complex(const double r,const double i):re(r),im(i) { }
complex(const complex &o):re([Link]),im([Link]) { }
//--- Arithmetic operations
complex Add(const complex &l,const complex &r) const; // Addition
complex Sub(const complex &l,const complex &r) const; // Subtraction
complex Mul(const complex &l,const complex &r) const; // Multiplication
complex Div(const complex &l,const complex &r) const; // Division
//--- Binary operators
complex operator+(const complex &r) const { return(Add(this,r)); }
complex operator-(const complex &r) const { return(Sub(this,r)); }
complex operator*(const complex &r) const { return(Mul(this,r)); }
complex operator/(const complex &r) const { return(Div(this,r)); }
};
//+------------------------------------------------------------------+
//| Addition |
//+------------------------------------------------------------------+
complex complex::Add(const complex &l,const complex &r) const
{
complex res;
//---
[Link]=[Link]+[Link];
[Link]=[Link]+[Link];
//--- Result
return res;
}
//+------------------------------------------------------------------+
//| Subtraction |
//+------------------------------------------------------------------+
complex complex::Sub(const complex &l,const complex &r) const
{
complex res;
//---
[Link]=[Link];
[Link]=[Link];
//--- Result
return res;
}
//+------------------------------------------------------------------+
//| Multiplication |
//+------------------------------------------------------------------+
complex complex::Mul(const complex &l,const complex &r) const
{
complex res;
//---
[Link]=[Link]*[Link]*[Link];
[Link]=[Link]*[Link]+[Link]*[Link];
//--- Result
return res;
}
//+------------------------------------------------------------------+
//| Division |
//+------------------------------------------------------------------+
complex complex::Div(const complex &l,const complex &r) const
{
//--- Empty complex number
complex res(EMPTY_VALUE,EMPTY_VALUE);
//--- Check for zero
if([Link]==0 && [Link]==0)
{
Print(__FUNCTION__+": number is zero");
return(res);
}
//--- Auxiliary variables
double e;
double f;
//--- Selecting calculation variant
if(MathAbs([Link])<MathAbs([Link]))
{
e = [Link]/[Link];
f = [Link]+[Link]*e;
[Link]=([Link]+[Link]*e)/f;
[Link]=([Link]*e)/f;
}
else
{
e = [Link]/[Link];
f = [Link]+[Link]*e;
[Link]=([Link]+[Link]*e)/f;
[Link]=(-[Link]+[Link]*e)/f;
}
//--- Result
return res;
}

 
Most unary operations for classes can be overloaded as ordinary functions that accept a
single class object argument or a pointer to it. Add overloading of unary operations "-"
and "!".
//+------------------------------------------------------------------+
//| Structure for operations with complex numbers |
//+------------------------------------------------------------------+
struct complex
{
double re; // Real part
double im; // Imaginary part
...
//--- Unary operators
complex operator-() const; // Unary minus
bool operator!() const; // Negation
};
...
//+------------------------------------------------------------------+
//| Overloading the "unary minus" operator |
//+------------------------------------------------------------------+
complex complex::operator-() const
{
complex res;
//---
[Link]=-re;
[Link]=-im;
//--- Result
return res;
}
//+------------------------------------------------------------------+
//| Overloading the "logical negation" operator |
//+------------------------------------------------------------------+
bool complex::operator!() const
{
//--- Are the real and imaginary parts of the complex number equal to zero?
return (re!=0 && im!=0);
}

 
Now we can check the value of a complex number for zero and get a negative value:
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- Declare and initialize variables of type complex
complex a(2,4),b(-4,-2);
PrintFormat("a=%.2f+i*%.2f, b=%.2f+i*%.2f",[Link],[Link],[Link],[Link]);
//--- Divide the two numbers
complex z=a/b;
PrintFormat("a/b=%.2f+i*%.2f",[Link],[Link]);
//--- A complex number is equal to zero by default (in the default constructor re==0
complex zero;
Print("!zero=",!zero);
//--- Assign a negative value
zero=-z;
PrintFormat("z=%.2f+i*%.2f, zero=%.2f+i*%.2f",[Link],[Link], [Link],[Link]);
PrintFormat("-zero=%.2f+i*%.2f",-[Link],-[Link]);
//--- Check for zero once again
Print("!zero=",!zero);
//---
}

Note that we did not have to overload the assignment operator "=", as structures of
simple types can be directly copied one into each other. Thus, we can now write a code
for calculations involving complex numbers in the usual manner.
Overloading of the indexing operator allows to obtain the values of the arrays enclosed
in an object, in a simple and familiar way, and it also contributes to a better readability
of the source code. For example, we need to provide access to a symbol in the string at
the specified position. A string in MQL4 is a separate type string, which is not an array of
symbols, but with the help of an overloaded indexing operation we can provide a simple
and transparent work in the generated CString class:
//+------------------------------------------------------------------+
//| Class to access symbols in string as in array of symbols |
//+------------------------------------------------------------------+
class CString
{
string m_string;

public:
CString(string str=NULL):m_string(str) { }
ushort operator[] (int x) { return(StringGetCharacter(m_string,x)); }
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- An array for receiving symbols from a string
int x[]={ 19,4,18,19,27,14,15,4,17,0,19,14,17,27,26,28,27,5,14,
17,27,2,11,0,18,18,27,29,30,19,17,8,13,6 };
CString str("abcdefghijklmnopqrstuvwxyz[ ]CS");
string res;
//--- Make up a phrase using symbols from the str variable
for(int i=0,n=ArraySize(x);i<n;i++)
{
res+=ShortToString(str[x[i]]);
}
//--- Show the result
Print(res);
}

 
Another example of overloading of the indexing operation is operations with matrices.
The matrix represents a two-dimensional dynamic array, the array size is not defined in
advance. Therefore, you cannot declare an array of form array[][] without specifying the
size of the second dimension, and then pass this array as a parameter. A possible solution
is a special class CMatrix, which contains an array of CRow class objects.
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- Operations of addition and multiplication of matrices
CMatrix A(3),B(3),C();
//--- Prepare an array for rows
double a1[3]={1,2,3}, a2[3]={2,3,1}, a3[3]={3,1,2};
double b1[3]={3,2,1}, b2[3]={1,3,2}, b3[3]={2,1,3};
//--- Fill the matrices
A[0]=a1; A[1]=a2; A[2]=a3;
B[0]=b1; B[1]=b2; B[2]=b3;
//--- Output the matrices in the Experts log
Print("---- Elements of matrix A");
Print([Link]());
Print("---- Elements of matrix B");
Print([Link]());

//--- Addition of matrices


Print("---- Addition of matrices A and B");
C=A+B;
//--- Output the formatted string representation
Print([Link]());

//--- Multiplication of matrices


Print("---- Multiplication of matrices A and B");
C=A*B;
Print([Link]());

//--- Now we show how to get values in the style of dynamic arrays matrix[i][j]
Print("Output the values of matrix C elementwise");
//--- Go through the matrix rows - CRow objects - in a loop
for(int i=0;i<3;i++)
{
string com="| ";
//--- Form rows from the matrix for the value
for(int j=0;j<3;j++)
{
//--- Get the matrix element by the number of the row and column
double element=C[i][j];// [i] - Access to CRow in the array m_rows[] ,
// [j] - Overloaded operator of indexing in CRow
com=com+StringFormat("a(%d,%d)=%G ; ",i,j,element);
}
com+="|";
//--- Output the values of the row
Print(com);
}
}
//+------------------------------------------------------------------+
//| Class "Row" |
//+------------------------------------------------------------------+
class CRow
{
private:
double m_array[];
public:
//--- Constructors and a destructor
CRow(void) { ArrayResize(m_array,0); }
CRow(const CRow &r) { this=r; }
CRow(const double &array[]);
~CRow(void){};
//--- Number of elements in the row
int Size(void) const { return(ArraySize(m_array));}
//--- Returns a string with values
string String(void) const;
//--- Indexing operator
double operator[](int i) const { return(m_array[i]); }
//--- Assignment operators
void operator=(const double &array[]); // An array
void operator=(const CRow & r); // Another CRow object
double operator*(const CRow &o); // CRow object for multiplica
};
//+------------------------------------------------------------------+
//| Constructor for initializing a row with an array |
//+------------------------------------------------------------------+
void CRow::CRow(const double &array[])
{
int size=ArraySize(array);
//--- If the array is not empty
if(size>0)
{
ArrayResize(m_array,size);
//--- Fill with values
for(int i=0;i<size;i++)
m_array[i]=array[i];
}
//---
}
//+------------------------------------------------------------------+
//| Assignment operation for the array |
//+------------------------------------------------------------------+
void CRow::operator=(const double &array[])
{
int size=ArraySize(array);
if(size==0) return;
//--- Fill the array with values
ArrayResize(m_array,size);
for(int i=0;i<size;i++) m_array[i]=array[i];
//---
}
//+------------------------------------------------------------------+
//| Assignment operation for CRow |
//+------------------------------------------------------------------+
void CRow::operator=(const CRow &r)
{
int size=[Link]();
if(size==0) return;
//--- Fill the array with values
ArrayResize(m_array,size);
for(int i=0;i<size;i++) m_array[i]=r[i];
//---
}
//+------------------------------------------------------------------+
//| Operator of multiplication by another row |
//+------------------------------------------------------------------+
double CRow::operator*(const CRow &o)
{
double res=0;
//--- Verifications
int size=Size();
if(size!=[Link]() || size==0)
{
Print(__FUNCSIG__,": Failed to multiply two matrices, their sizes are different
return(res);
}
//--- Multiply arrays elementwise and add the products
for(int i=0;i<size;i++)
res+=m_array[i]*o[i];
//--- Result
return(res);
}
//+------------------------------------------------------------------+
//| Returns a formatted string representation |
//+------------------------------------------------------------------+
string CRow::String(void) const
{
string out="";
//--- If the size of the array is greater than zero
int size=ArraySize(m_array);
//--- We work only with a non-zero number of array elements
if(size>0)
{
out="{";
for(int i=0;i<size;i++)
{
//--- Collect the values to a string
out+=StringFormat(" %G;",m_array[i]);
}
out+=" }";
}
//--- Result
return(out);
}
//+------------------------------------------------------------------+
//| Class "Matrix" |
//+------------------------------------------------------------------+
class CMatrix
{
private:
CRow m_rows[];

public:
//--- Constructors and a destructor
CMatrix(void);
CMatrix(int rows) { ArrayResize(m_rows,rows); }
~CMatrix(void){};
//--- Get the matrix sizes
int Rows() const { return(ArraySize(m_rows)); }
int Cols() const { return(Rows()>0? m_rows[0].Size():0); }
//--- Returns the value of the column in the form of a CRow row
CRow GetColumnAsRow(const int col_index) const;
//--- Returns a string with the matrix values
string String(void) const;
//--- The indexing operator returns a string by its number
CRow *operator[](int i) const { return(GetPointer(m_rows[i])); }
//--- Addition operator
CMatrix operator+(const CMatrix &m);
//--- Multiplication operator
CMatrix operator*(const CMatrix &m);
//--- Assignment operator
CMatrix *operator=(const CMatrix &m);
};
//+------------------------------------------------------------------+
//| Default constructor, create and array of rows of zero size |
//+------------------------------------------------------------------+
CMatrix::CMatrix(void)
{
//--- The zero number of rows in the matrix
ArrayResize(m_rows,0);
//---
}
//+------------------------------------------------------------------+
//| Returns the column value in the form of CRow |
//+------------------------------------------------------------------+
CRow CMatrix::GetColumnAsRow(const int col_index) const
{
//--- A variable to get the values from the column
CRow row();
//--- The number of rows in the matrix
int rows=Rows();
//--- If the number of rows is greater than zero, execute the operation
if(rows>0)
{
//--- An array to receive the values of the column with index col_index
double array[];
ArrayResize(array,rows);
//--- Filling the array
for(int i=0;i<rows;i++)
{
//--- Check the number of the column for row i - it may exceed the boundarie
if(col_index>=this[i].Size())
{
Print(__FUNCSIG__,": Error! Column number ",col_index,"> row size ",i);
break; // row will be uninitialized object
}
array[i]=this[i][col_index];
}
//--- Create a CRow row based on the array values
row=array;
}
//--- Result
return(row);
}
//+------------------------------------------------------------------+
//| Addition of two matrices |
//+------------------------------------------------------------------+
CMatrix CMatrix::operator+(const CMatrix &m)
{
//--- The number of rows and columns in the passed matrix
int cols=[Link]();
int rows=[Link]();
//--- The matrix to receive the addition results
CMatrix res(rows);
//--- The sizes of the matrix must match
if(cols!=Cols() || rows!=Rows())
{
//--- Addition impossible
Print(__FUNCSIG__,": Failed to add two matrices, their sizes are different");
return(res);
}
//--- Auxiliary array
double arr[];
ArrayResize(arr,cols);
//--- Go through rows to add
for(int i=0;i<rows;i++)
{
//--- Write the results of addition of matrix strings in the array
for(int k=0;k<cols;k++)
{
arr[k]=this[i][k]+m[i][k];
}
//--- Place the array to the matrix row
res[i]=arr;
}
//--- return the result of addition of matrices
return(res);
}
//+------------------------------------------------------------------+
//| Multiplication of two matrices |
//+------------------------------------------------------------------+
CMatrix CMatrix::operator*(const CMatrix &m)
{
//--- Number of columns of the first matrix, number of rows passed in the matrix
int cols1=Cols();
int rows2=[Link]();
int rows1=Rows();
int cols2=[Link]();
//--- Matrix to receive the addition result
CMatrix res(rows1);
//--- Matrices should be coordinated
if(cols1!=rows2)
{
//--- Multiplication impossible
Print(__FUNCSIG__,": Failed to multiply two matrices, format is not compatible
"- number of columns in the first factor should be equal to the number of
return(res);
}
//--- Auxiliary array
double arr[];
ArrayResize(arr,cols1);
//--- Fill the rows in the multiplication matrix
for(int i=0;i<rows1;i++)// Go through rows
{
//--- Reset the receiving array
ArrayInitialize(arr,0);
//--- Go through elements in the row
for(int k=0;k<cols1;k++)
{
//--- Take values of column k of the matrix m in the for of CRow
CRow column=[Link](k);
//--- Multiply two rows and write the result of scalar multiplication of vec
arr[k]=this[i]*column;
}
//--- place array arr[] in the i-th row of the matrix
res[i]=arr;
}
//--- Return the product of two matrices
return(res);
}
//+------------------------------------------------------------------+
//| Assignment operation |
//+------------------------------------------------------------------+
CMatrix *CMatrix::operator=(const CMatrix &m)
{
//--- Find and set the number of rows
int rows=[Link]();
ArrayResize(m_rows,rows);
//--- Fill our rows with the values of rows of the passed matrix
for(int i=0;i<rows;i++) this[i]=m[i];
//---
return(GetPointer(this));
}
//+------------------------------------------------------------------+
//| String representation of the matrix |
//+------------------------------------------------------------------+
string CMatrix::String(void) const
{
string out="";
int rows=Rows();
//--- Form string by string
for(int i=0;i<rows;i++)
{
out=out+this[i].String()+"\r\n";
}
//--- Result
return(out);
}

See also
Overloading, Arithmetic Operations, Function Overloading, Precedence Rules
MQL4 Reference / Language Basics / Functions / Description of External Functions

Description of External Functions


External functions defined in another module must be explicitly described. The
description includes returned type, function name and series of input parameters with
their types. The absence of such a description can lead to errors when compiling,
building, or executing a program. When describing an external object, use the keyword
#import indicating the module.
Examples:
#import "[Link]" int MessageBoxW(int hWnd ,string szText,string szCaption,in
int SendMessageW(int hWnd,int Msg,int wParam,int lParam);
#import "lib.ex4"
double round(double value);
#import

With the help of import, it is easy to describe functions that are called from external
DLL or compiled EX4 libraries. EX4 libraries are compiled ex4 files, which have the
library property. Only function described with the export modifier can be imported from
EX4 libraries.
Please keep in mind that DLL and EX4 libraries should have different names (regardless
of the directories they are located in) if they are imported together. All imported
functions have the scope resolution corresponding to the library's "file name".
Use of several functions of the same name from different execution contexts in a
program may cause ambiguity. To avoid the ambiguity of function calls, always explicitly
specify the function scope using the scope resolution operation.
Example:
#import "[Link]"
int GetLastError();
#import "lib.ex4"
int GetLastError();
#import

class CFoo
{
public:
int GetLastError() { return(12345); }
void func()
{
Print(GetLastError()); // call of the class method
Print(::GetLastError()); // call of the MQL5 function
Print(kernel32::GetLastError()); // call of the DLL library function from kerne
Print(lib::GetLastError()); // call of the EX4 library function from lib.e
}
};

void OnStart()
{
CFoo foo;
[Link]();
}

See also
Overload, Virtual Functions, Polymorphism
MQL4 Reference / Language Basics / Functions / Exporting Functions

Exporting Functions
A function declared in a mql4 program with the export
postmodifier can be used in another mql4 program. Such a
function is called exportable, and it can be called from
other programs after compilation.
int Function() export {
}

This modifier orders the compiler to add the function into


the table of EX4 functions exported by this ex4 file. Only
function with such a modifier are accessible ("visible")
from other mql4 programs.
The library property tells the compiler that the EX4-file
will be a library, and the compiler will show it in the
header of EX4.
All functions that are planned as exportable ones must be
marked with the export modifier.
When compiling libraries in the strict mode, the export
modifier should be added for each exported function,
otherwise the function will not be accessible from
outside.
See also
Overload, Virtual Functions, Polymorphism
MQL4 Reference / Language Basics / Functions / Event Handling Functions

Event Handling Functions


The MQL4 language provides processing of some predefined events. Functions for
handling these events must be defined in a MQL4 program; function name, return type,
composition of parameters (if there are any) and their types must strictly conform to the
description of the event handler function.
The event handler of the client terminal identifies functions, handling this or that event,
by the type of return value and type of parameters. If other parameters, not
corresponding to below descriptions, are specified for a corresponding function, or
another return type is indicated for it, such a function will not be used as an event
handler.
OnStart
The OnStart() function is the Start event handler, which is automatically generated only
for running scripts. It must be of void type, with no parameters:
void OnStart();

For the OnStart() function, the int return type can be specified.
OnInit
The OnInit() function is the Init event handler. It must be of void or int type, with no
parameters:
void OnInit();

The Init event is generated immediately after an Expert Advisor or an indicator is


downloaded; The OnInit() function is used for initialization. If OnInit() has the int type of
the return value, the non-zero return code means unsuccessful initialization, and it
generates the Deinit event with the code of deinitialization reason REASON_INITFAILED.
OnInit() function execution result is analyzed by the terminal's runtime subsystem only if
the program has been compiled using #property strict.
To optimize input parameters of an Expert Advisor, it is recommended to use values of
the ENUM_INIT_RETCODE enumeration as the return code.. During initialization of an
Expert Advisor before the start of testing you can request information about the
configuration and resources using the TerminalInfoInteger() function.
ENUM_INIT_RETCODE
Identifier Description
INIT_SUCCEEDED Successful initialization, testing of the Expert Advisor can be
continued.
This code means the same as a null value the Expert Advisor has
been successfully initialized in the tester.
INIT_FAILED Initialization failed; there is no point in continuing testing because
of fatal errors. For example, failed to create an indicator that is
required for the work of the Expert Advisor.
This return value means the same as a value other than zero -
initialization of the Expert Advisor in the tester failed.
Identifier Description
INIT_PARAMETERS_INCORRECT This value means the incorrect set of input parameters. The result
string containing this return code is highlighted in red in the
general optimization table.
Testing for the given set of parameters of the Expert Advisor will
not be executed

The OnInit() function of the void type always denotes successful initialization.
OnDeinit
The OnDeinit() function is called during deinitialization and is the Deinit event handler. It
must be declared as the void type and should have one parameter of the const int type,
which contains the code of deinitialization reason. If a different type is declared, the
compiler will generate a warning, but the function will not be called.
void OnDeinit(const int reason);

The Deinit event is generated for Expert Advisors and indicators in the following cases:
before reinitialization due to the change of a symbol or chart period, to which the
mql4 program is attached;
before reinitialization due to the change of input parameters;
before unloading the mql4 program.
OnTick
The NewTick event is generated for Expert Advisors only when a new tick for a symbol
is received, to the chart of which the Expert Advisor is attached. It's useless to define
the OnTick() function in a custom indicator or script, because the NewTick event is not
generated for them.
The Tick event is generated only for Expert Advisors, but this does not mean that Expert
Advisors required the OnTick() function, since not only NewTick events are generated for
Expert Advisors, but also events of Timer, BookEvent and ChartEvent are generated. It
must be declared as the void type, with no parameters:
void OnTick();

OnTimer
The OnTimer() function is called when the Timer event occurs, which is generated by the
system timer only for Expert Advisors and indicators - it can't be used in scripts. The
frequency of the event occurrence is set when subscribing to notifications about this
event to be received by the EventSetTimer() function.
You can unsubscribe from receiving timer events for a particular Expert Advisor using the
EventKillTimer() function. The function must be defined with the void type, with no
parameters:
void OnTimer();

It is recommended to call the EventSetTimer() function once in the OnInit() function,


and the EventKillTimer() function should be called once in OnDeinit().
Every Expert Advisor, as well as every indicator works with its own timer and receives
events only from it. As soon as the mql4 program stops operating, the timer is destroyed
forcibly, if it was created but hasn't been disabled by the EventKillTimer() function.
OnTester
The OnTester() function is the handler of the Tester event that is automatically
generated after a history testing of an Expert Advisor on the chosen interval is over. The
function must be defined with the double type, with no parameters:
double OnTester();

The function is called right before the call of OnDeinit() and has the same type of the
return value - double. OnTester() can be used only in the testing of Expert Advisors. Its
main purpose is to calculate a certain value that is used as the Custom max criterion in
the genetic optimization of input parameters.
In the genetic optimization descending sorting is applied to results within one
generation. I.e. from the point of view of the optimization criterion, the best results are
those with largest values (for the Custom max optimization criterion values returned by
the OnTester function are taken into account). In such a sorting, the worst values are
positioned at the end and further thrown off and do not participate in the forming of the
next generation.
OnChartEvent
OnChartEvent() is the handler of a group of ChartEvent events:
CHARTEVENT_KEYDOWN event of a keystroke, when the chart window is focused;
CHARTEVENT_MOUSE_MOVE mouse move events and mouse click events (if
CHART_EVENT_MOUSE_MOVE=true is set for the chart);
CHARTEVENT_OBJECT_CREATE event of graphical object creation (if
CHART_EVENT_OBJECT_CREATE=true is set for the chart);
CHARTEVENT_OBJECT_CHANGE event of change of an object property via the
properties dialog;
CHARTEVENT_OBJECT_DELETE event of graphical object deletion (if
CHART_EVENT_OBJECT_DELETE=true is set for the chart);
CHARTEVENT_CLICK event of a mouse click on the chart;
CHARTEVENT_OBJECT_CLICK event of a mouse click in a graphical object belonging to
the chart;
CHARTEVENT_OBJECT_DRAG event of a graphical object move using the mouse;
CHARTEVENT_OBJECT_ENDEDIT event of the finished text editing in the entry box of
the LabelEdit graphical object;
CHARTEVENT_CHART_CHANGE   event of chart changes;
CHARTEVENT_CUSTOM+n ID of the user event, where n is in the range from 0 to
65535.
CHARTEVENT_CUSTOM_LAST the last acceptable ID of a custom event
(CHARTEVENT_CUSTOM +65535).
The function can be called only in Expert Advisors and indicators. The function should be
of void type with 4 parameters:
void OnChartEvent(const int id, // Event ID const long& lpar
const double& dparam, // Parameter of type double event
const string& sparam // Parameter of type string events
);

For each type of event, the input parameters of the OnChartEvent() function have
definite values that are required for the processing of this event. The events and values
passed through these parameters are listed in the table below.
Event Value of the id parameter Value of the lparam Value
parameter dpara
Event of a keystroke CHARTEVENT_KEYDOWN code of a pressed Repea
key numb
the
repea
of the
down
Mouse events (if property CHARTEVENT_MOUSE_MOVE the X coordinate the Y
CHART_EVENT_MOUSE_MOVE=true is
set for the chart)

Event of graphical object creation CHARTEVENT_OBJECT_CREATE


(if
CHART_EVENT_OBJECT_CREATE=true
is set for the chart)
Event of change of an object CHARTEVENT_OBJECT_CHANGE
property via the properties dialog

Event of graphical object deletion CHARTEVENT_OBJECT_DELETE


(if
CHART_EVENT_OBJECT_DELETE=true
is set for the chart)
Event of a mouse click on the chart CHARTEVENT_CLICK the X coordinate the Y
Event of a mouse click in a graphical CHARTEVENT_OBJECT_CLICK the X coordinate the Y
object belonging to the chart

Event of a graphical object dragging CHARTEVENT_OBJECT_DRAG


using the mouse
Event of the finished text editing in CHARTEVENT_OBJECT_ENDEDIT
the entry box of the LabelEdit
graphical object

Event of chart Changes CHARTEVENT_CHART_CHANGE


ID of the user event under the N CHARTEVENT_CUSTOM+N Value set by the Value
number EventChartCustom() Event
function functi
OnCalculate
The OnCalculate() function is called only in custom indicators when it's necessary to
calculate the indicator values by the Calculate event. This usually happens when a new
tick is received for the symbol, for which the indicator is calculated. This indicator is not
required to be attached to any price chart of this symbol.
The OnCalculate() function must have a return type int.
int OnCalculate (const int rates_total, // size of input time series
const int prev_calculated, // bars handled in previous call
const datetime& time[], // Time
const double& open[], // Open
const double& high[], // High
const double& low[], // Low
const double& close[], // Close
const long& tick_volume[], // Tick Volume
const long& volume[], // Real Volume
const int& spread[] // Spread
);

Parameters of open[], high[], low[] and close[] contain arrays with open prices, high and
low prices and close prices of the current time frame. The time[] parameter contains an
array with open time values, the spread[] parameter has an array containing the history
of spreads (if any spread is provided for the traded security). The parameters of
volume[] and tick_volume[] contain the history of trade and tick volume, respectively.
To determine the indexing direction of time[], open[], high[], low[], close[],
tick_volume[], volume[] and spread[], call ArrayGetAsSeries(). In order not to depend on
default values, you should unconditionally call the ArraySetAsSeries() function for those
arrays, which are expected to work with.
The first rates_total parameter contains the number of bars, available to the indicator
for calculation, and corresponds to the number of bars available in the chart.
We should note the connection between the return value of OnCalculate() and the
second input parameter prev_calculated. During the function call, the prev_calculated
parameter contains a value returned by OnCalculate() during previous call. This allows
for economical algorithms for calculating the custom indicator in order to avoid
repeated calculations for those bars that haven't changed since the previous run of this
function.
For this, it is usually enough to return the value of the rates_total parameter, which
contains the number of bars in the current function call. If since the last call of
OnCalculate() price data has changed (a deeper history downloaded or history blanks
filled), the value of the input parameter prev_calculated will be set to zero by the
terminal.
To understand it better, it would be useful to start the indicator, which code is attached
below.
Indicator Example:
#property indicator_chart_window
#property indicator_buffers 1
//---- plot Line
#property indicator_label1 "Line"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDarkBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- indicator buffers
double LineBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,LineBuffer,INDICATOR_DATA);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime& time[],
const double& open[],
const double& high[],
const double& low[],
const double& close[],
const long& tick_volume[],
const long& volume[],
const int& spread[])
{
//--- Get the number of bars available for the current symbol and chart period
int bars=Bars(Symbol(),0);
Print("Bars = ",bars,", rates_total = ",rates_total,", prev_calculated = ",prev_c
Print("time[0] = ",time[0]," time[rates_total-1] = ",time[rates_total-1]);
//--- return value of prev_calculated for next call
return(rates_total);
}

See also
Running Programs, Client Terminal Events, Working with Events
MQL4 Reference / Language Basics / Variables

Variables
Declaring Variables
Variables must be declared before they are used. Unique names are used to
identify variables. To declare a variable, you must specify its type and a unique
name. Declaration of variable is not an operator.
Simple types are:
char, short, int, long, uchar, ushort, uint, ulong integers;
color integer representing the RGB-color;
datetime the date and time, an unsigned integer containing the number of
seconds since 0 hour January 1, 1970;
bool boolean values true and false;
double double-precision floating point number;
float single-precision floating point number;
string character strings.
Examples:
string szInfoBox; int nOrders;
double dSymbolPrice;
bool bLog;
datetime tBegin_Data = D'2004.01.01 00:00';
color cModify_Color = C'0x44,0xB9,0xE6';

Complex or compound types:


Structures are composite data types, constructed using other types.
struct MyTime
{
int hour; // 0-23
int minute; // 0-59
int second; // 0-59
};
...
MyTime strTime; // Variable of the previously declared structure MyTime

You can't declare variables of the structure type until you declare the structure.
Arrays
Array  is the indexed sequence of identical-type data:
int a[50]; // One-dimensional array of 50 integers.
double m[7][50]; // Two-dimensional array of seven arrays,
// each of them consisting of 50 numbers.
MyTime t[100]; // Array containing elements such as MyTime
Only an integer can be an array index. No more than four-dimensional arrays are
allowed. Numbering of array elements starts with 0. The last element of a one-
dimensional array has the number which is 1 less than the array size. This means
that call for the last element of an array consisting of 50 integers will appear as
a[49]. The same concerns multidimensional arrays: A dimension is indexed from 0
to the dimension size-1. The last element of a two-dimensional array from the
example will appear as m[6][49].
Static arrays can't be represented as timeseries, i.e., the ArraySetAsSeries()
function, which sets access to array elements from the end to beginning, can't be
applied to them. If you want to provide access to an array the same as in
timeseries, use the dynamic array object.
If there is an attempt to access out of the array range, the executing subsystem
will generate a critical error and the program will be stopped.
Access Specifiers
Access specifiers define how the compiler can access variables, members of
structures or classes.
The const specifier declares a variable as a constant, and does not allow to
change this variable during runtime. A single initialization of a variable is allowed
when declaring it.
Example:
int OnCalculate (const int rates_total, // size of input time series
const int prev_calculated, // bars handled in previous call
const datetime& time[], // Time
const double& open[], // Open
const double& high[], // High
const double& low[], // Low
const double& close[], // Close
const long& tick_volume[], // Tick Volume
const long& volume[], // Real Volume
const int& spread[] // Spread
);

To access members of structures and classes use the following qualifiers:


public allows unrestricted access to the variable or class method
protected allows access from methods of this class, as well as from methods of
publicly inherited classes. Other access is impossible;
private allows access to variables and class methods only from methods of the
same class.
virtual applies only to class methods (but not to methods of structures) and
tells the compiler that this method should be placed in the table of virtual
functions of the class.
Storage Classes
There are three storage classes: static, input and extern. These modifiers of a
storage class explicitly indicate to the compiler that corresponding variables are
distributed in a pre-allocated area of memory, which is called the global pool.
Besides, these modifiers indicate the special processing of variable data. If a
variable declared on a local level is not a static one, memory for such a variable is
allocated automatically at a program stack. Freeing of memory allocated for a
non-static array is also performed automatically when going beyond the visibility
area of the block, in which the array is declared.
See also
Data Types, Encapsulation and Extensibility of Types,Initialization of Variables,
Visibility Scope and Lifetime of Variables, Creating and Deleting Objects, Static
Members of a Class
MQL4 Reference / Language Basics / Variables / Local Variables

Local Variables
A variable declared inside a function is local. The scope of
a local variable is limited to the function range inside
which it is declared. Local variable can be initialized by
outcome of any expression. Every call of the function
initializes a local variable. Local variables are stored in
memory area of the corresponding function.
Example:
int somefunc() {
int ret_code=0;
...
return(ret_code);
}

Scope of a variable is a program part, in which a variable


can be referred to. Variables declared inside a block (at
the internal level), have the block as their scope. The
block scope start with the variable declaration and ends
with the final right brace.
Local variables declared in the beginning of a function also
have the scope of block, as well as function parameters
that are local variables. Any block can contain variable
declarations. If blocks are nested and the identifier in the
external block has the same name as the identifier in the
internal block, the external block identifier is hidden, until
the operation of the internal block is over.
Example:
void OnStart()
{
//---
int i=5; // local variable of the function
{
int i=10; // function variable
Print("Inside block i = ",i); // result is i=10;
}
Print("Outside block i = ",i); // result is i=5;
}

This means that while the internal block is running, it sees


values of its own local identifiers, not the values of
identifiers with identical names in the external block.
Example:
void OnStart()
{
//---
int i=5; // local variable of the function
for(int i=0;i<3;i++)
Print("Inside for i = ",i);
Print("Outside the block i = ",i);
}
/* Execution result
Inside for i = 0
Inside for i = 1
Inside for i = 2
Outside block i = 5
*/

Local variables declared as static have the scope of the


block, despite the fact that they exist since the program
start.

Stack
In every MQL4 program, a special memory area called
stack is allocated for storing local function variables that
are created automatically. One stack is allocated for all
functions. The default stack size is 256 kb, the stack size
can be managed using the #property stacksize compiler
directive.
Static local variables are stored in the same place where
other static and global variables are stored - in a special
memory area, which exists separately from the stack.
Dynamically created variables also use a memory area
separate from the stack.
With each function call, a place on the stack is allocated
for internal non-static variables. After exiting the function,
the memory is available for use again.
If from the first function the second one is called, then the
second function occupies the required size from the
remaining stack memory for its variables. Thus, when using
included functions, stack memory will be sequentially
occupied for each function. This may lead to a shortage of
memory during one of the function calls, such a situation is
called stack overflow.
Therefore, for large local data you should better use
dynamic memory - when entering a function, allocate the
memory, which is required for local needs, in the system
(new, ArrayResize()), and when exiting the function,
release the memory (delete, ArrayFree()).
See also
Data Types, Encapsulation and Extensibility of
Types,Initialization of Variables, Visibility Scope and
Lifetime of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Variables / Formal Parameters

Formal Parameters
Parameters passed to the function are local. The scope is
the function block. Formal parameters must have names
differing from those of external variables and local
variables defined within one function. Some values can be
assigned to formal parameters in the function block. If a
formal parameter is declared with the const modifier, its
value can't be changed within the function.
Example:
void func(const int & x[], double y, bool z) {
if(y>0.0 && !z)
Print(x[0]);
...
}

Formal parameters can be initialized by constants. In this


case, the initializing value is considered as the default
value. Parameters, next to the initialized one, must also
be initialized.
Example:
void func(int x, double y = 0.0, bool z = true)
{
...
}

When calling such a function, the initialized parameters


can be omitted, the defaults being substituted instead of
them.
Example:
func(123, 0.5);

Parameters of simple types are passed by value, i.e.,


modifications of the corresponding local variable of this
type inside the called function will not be reflected in the
calling function. Arrays of any type and data of the
structure type are always passed by reference. If it is
necessary to prohibit modifying the array or structure
contents, the parameters of these types must be declared
with the const keyword.
There is an opportunity to pass parameters of simple
types by reference. In this case, modification of such
parameters inside the calling function will affect the
corresponding variables passed by reference. In order to
indicate that a parameter is passed by reference, put the
& modifier after the data type.
Example:
void func(int& x, double& y, double & z[])
{
double calculated_tp;
...
for(int i=0; i<OrdersTotal(); i++)
{
if(i==ArraySize(z)) break;
if(OrderSelect(i)==false) break;
z[i]=OrderOpenPrice();
}
x=i;
y=calculated_tp;
}

Parameters passed by reference can't be initialized by


default values.
Maximum 64 parameters can be passed into a function.
See also
Input Variables, Data Types, Encapsulation and
Extensibility of Types,Initialization of Variables, Visibility
Scope and Lifetime of Variables, Creating and Deleting
Objects
MQL4 Reference / Language Basics / Variables / Static Variables

Static Variables
The storage class of static defines a static variable. The static modifier is indicated
before the data type.
Example:
int somefunc() {
static int flag=10;
...
return(flag);
}

A static variable can be initialized by a constant or constant expression


corresponding to its type, unlike a simple local variable, which can be initialized by
any expression.
Static variables exist from the moment of program execution and are initialized
only once after the program is loaded. If the initial values are not specified,
variables of the static storage class are taking zero initial values. The scope of the
static variables is the same as the scope of the global variables: the lifetime of the
mql4-program. The scope of a static variable is local to the block in which the
variable is defined.
Local variables declared with the static keyword retain their values throughout the
function lifetime. With each next function call, such local variables contain the
values that they had during the previous call.
Any variables in a block, except formal parameters of a function, can be defined as
static. If a variable declared on a local level is not a static one, memory for such a
variable is allocated automatically at a program stack.
Example:
int Counter()
{
static int count;
count++;
if(count%100==0) Print("Function Counter has been called ",count," times");
return count;
}
void OnStart()
{
//---
int c=345;
for(int i=0;i<1000;i++)
{
int c=Counter();
}
Print("c =",c);
}
See also
Data Types, Encapsulation and Extensibility of Types, Initialization of Variables,
Visibility Scope and Lifetime of Variables, Creating and Deleting Objects, Static
Class Members
MQL4 Reference / Language Basics / Variables / Global Variables

Global Variables
Global variables are created by placing their declarations
outside function descriptions. Global variables are defined
at the same level as functions, i.e., they are not local in
any block.
Example:
int GlobalFlag=10; // Global variable int OnStart()
{
...
}

The scope of global variables is the entire program.


Global variables are accessible from all functions defined
in the program. They are initialized to zero unless another
initial value is explicitly defined. A global variable can be
initialized only by a constant or constant expression that
corresponds to its type.
Global variables are initialized only once after the
program is loaded into the client terminal memory and
before the first handling of the Init event. For global
variables representing class objects, during their
initialization the corresponding constructors are called.
The scope of the global variables is the same as the scope
of the static variables : the lifetime of MQL4 program.
Note: Variables declared at global level must not be
mixed up with the client terminal global variables that
can be accessed using the GlobalVariable...() functions.
See also
Data Types, Encapsulation and Extensibility of
Types,Initialization of Variables, Visibility Scope and
Lifetime of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Variables / Input Variables

Input Variables
The input storage class defines the external variable. The input modifier
is indicated before the data type. A variable with the input modifier can't
be changed inside mql4-programs, such variables can be accessed for
reading only. Values of input variables can be changed only by a user from
the program properties window. External variables are always
reinitialized immediately before the OnInit() is called.
Example:
//--- input parameters input int MA_Period=13;
input int MA_Shift=0;
input ENUM_MA_METHOD MA_Method=MODE_SMMA;

Input variables determine the input parameters of a program. They are


available from the Properties window of a program.

 
There is another way to set how your input parameter will look like in the
Inputs tab. For this, place a string comment after the description of an
input parameter in the same line. In this way you can make names of
input parameters more understandable for users.
Example:
//--- input parameters
input int InpMAPeriod=13; // Smoothing period
input int InpMAShift=0; // Line horizontal shift
input ENUM_MA_METHOD InpMAMethod=MODE_SMMA; // Smoothing method
Note: Arrays and variables of complex types can't act as input variables.
Note: The length of a string comment for Input variables cannot exceed
63 characters.
 
Passing Parameters When Calling Custom Indicators from
MQL4 Programs
Custom Indicators are called using the iCustom() function. After the name
of the custom indicator, parameters should go in a strict accordance with
the declaration of input variables of this custom indicator. If indicated
parameters are less than input variables declared in the called custom
indicator, the missing parameters are filled with values specified during
the declaration of variables.
If the custom indicator uses the OnCalculate function of the first type
(i.e., the indicator is calculated using the same array of data), then one
of ENUM_APPLIED_PRICE values or handle of another indicator should be
used as the last parameter when calling such a custom indicator. All
parameters corresponding to input variables must be clearly indicated.
Enumerations as input Parameters
Not only built-in enumerations provided in MQL4, but also user defined
variables can be used as input variables (input parameters for mql4
programs). For example, we can create the dayOfWeek enumeration,
describing days of the week, and use the input variable to specify a
particular day of the week, not as a number, but in a more common way.
Example:
#property script_show_inputs
//--- day of week
enum dayOfWeek
{
S=0, // Sunday
M=1, // Monday
T=2, // Tuesday
W=3, // Wednesday
Th=4, // Thursday
Fr=5, // Friday,
St=6, // Saturday
};
//--- input parameters
input dayOfWeek swapday=W;

In order to enable a user to select a necessary value from the properties


window during the script startup, we use the preprocessor command
#property script_show_inputs. We start the script and can choose one of
values of the dayOfWeek enumeration from the list. We start the
EnumInInput script and go to the Inputs tab. By default, the value of
swapday (day of triple swap charge) is Wednesday (W = 3), but we can
specify any other value, and use this value to change the program
operation.

Number of possible values of an enumeration is limited. In order to select


an input value the drop-down list is used. Mnemonic names of
enumeration members are used for values displayed in the list. If a
comment is associated with a mnemonic name, as shown in this example,
the comment content is used instead of the mnemonic name.
Each value of the dayOfWeek enumeration has its value from 0 to 6, but
in the list of parameters, comments specified for each value will be
shown. This provides additional flexibility for writing programs with clear
descriptions of input parameters.
 

Variables with sinput Modifier


Variables with input modifier allow not only setting external parameters
values when launching programs but are also necessary when optimizing
trading strategies in the Strategy Tester. Each input variable excluding the
one of a string type can be used in optimization.
Sometimes, it is necessary to exclude some external program parameters
from the area of all passes in the tester. sinput memory modifier has been
introduced for such cases. sinput stands for static external variable
declaration (sinput = static input). It means that the following declaration
in an Expert Advisor code
sinput int layers=6; // Number of layers

will be equivalent to the full declaration


static input int layers=6; // Number of layers

The variable declared with sinput modifier is an input parameter of MQL4


program. The value of this parameter can be changed when launching the
program. However, this variable is not used in the optimization of input
parameters. In other words, its values are not enumerated when
searching for the best set of parameters fitting a specified condition.

The Expert Advisor shown above has 5 external parameters. "Number of


layers" is declared to be sinput and equal to 6. This parameter cannot be
changed during a trading strategy optimization. We can specify the
necessary value for it to be used further on. Start, Step and Stop fields
are not available for such a variable.
Therefore, users will not be able to optimize this parameter after we
specify sinput modifier for the variable. In other words, the terminal
users will not be able to set initial and final values for it in the Strategy
Tester for automatic enumeration in the specified range during
optimization.
However, there is one exception to this rule: sinput variables can be
varied in optimization tasks using ParameterSetRange() function. This
function has been introduced specifically for the program control of
available values sets for any input variable including the ones declared as
static input (sinput). The ParameterGetInput() function allows to receive
input variables values when optimization is launched (in OnTesterInit()
handler) and to reset a change step value and a range, within which an
optimized parameter values will be enumerated.
In this way, combining the sinput modifier and two functions that work
with input parameters, allows to create a flexible rules for setting
optimization intervals of input parameters that depend on values of
another input parameters.
See also
iCustom, Enumerations, Properties of Programs
MQL4 Reference / Language Basics / Variables / Extern Variables

Extern variables
The extern storage class defines the external variable. The extern modifier is
indicated before the data type.
//--- extern parameters extern int MA_Period=13;
extern int MA_Shift=0;
extern ENUM_MA_METHOD MA_Method=MODE_SMMA;

Similar to input-variables, extern ones also determine the input parameters of an


mql4 program. They are available from the Properties window. Unlike input
variables, values of extern variables can be modified in the program during its
operation. External variables are always reinitialized immediately before the
OnInit() is called.
Example:
//--- strict compilation mode
#property strict
//--- show input parameters
#property show_inputs
//--- declare extern and input variables
extern int ExtVar=1; // ExtVar extern variable
input int InpVar=2; // InpVar input variable
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- display the values of ExtVar and InpVar variables
PrintFormat("Extern=%d, Input=%d",ExtVar,InpVar);
//--- increase the value of ExtVar variable by one
ExtVar++;
//--- attempt to change the input variable will result in the compilation error
//--- InpVar++;
//--- display the values of ExtVar and InpVar variables
PrintFormat("Extern=%d, Input=%d",ExtVar,InpVar);
}

Strict compilation mode with the output of the input parameters window is set in
this script. Therefore, the values set in the string comments instead of ExtVar and
InpVar variable names are displayed in Variable field.
Note: Arrays and variables of complex types can't act as extern variables.
Note: The length of a string comment for extern variables cannot exceed 63
characters.
See also
Input Variables, Data Types, Encapsulation and Extensibility of Types, Initialization
of Variables, Visibility Scope and Lifetime of Variables, Creating and Deleting
Objects
MQL4 Reference / Language Basics / Variables / Initialization of Variables

Initialization of Variables
Any variable can be initialized during definition. If a variable is not initialized
explicitly, the value stored in this variable can be any. Implicit initialization is not
used.
Global and static variables can be initialized only by a constant of the
corresponding type or a constant expression. Local variables can be initialized by
any expression, not just a constant.
Initialization of global and static variables is performed only once. Initialization of
local variables is made every time you call the corresponding functions.
Examples:
int n = 1; string s = "hello";
double f[] = { 0.0, 0.236, 0.382, 0.5, 0.618, 1.0 };
int a[4][4] = { {1, 1, 1, 1}, {2, 2, 2, 2}, {3, 3, 3, 3}, {4, 4, 4, 4 } };
//--- from tetris
int right[4]={WIDTH_IN_PIXELS+VERT_BORDER,WIDTH_IN_PIXELS+VERT_BORDER,
WIDTH_IN_PIXELS+VERT_BORDER,WIDTH_IN_PIXELS+VERT_BORDER};
//--- initialization of all fields of the structure with zero values
MqlTradeRequest request={0};

List of values of the array elements must be enclosed in curly brackets. Missed
initializing sequences are considered equal to 0. The initializing sequence must
have at least one value: this value is initialized to the first element of the
corresponding structure or array, missing elements are considered equal to zero.
If the size of the initialized array is not specified, it is determined by a compiler,
based on the size of the initialization sequence. Multi-dimensional arrays cannot
be initialized by a one-dimensional sequence (a sequence without additional curly
brackets), except for the case, when only one initializing element is specified
(zero, as a rule).
Arrays (including those announced at the local level) can be initialized only by
constants.
Examples:
struct str3
{
int low_part;
int high_part;
};
struct str10
{
str3 s3;
double d1[10];
int i3;
};
void OnStart()
{
str10 s10_1={{1,0},{1.0,2.1,3.2,4.4,5.3,6.1,7.8,8.7,9.2,10.0},100};
str10 s10_2={{1,0},{0},100};
str10 s10_3={{1,0},{1.0}};
//---
Print("1. s10_1.d1[5] = ",s10_1.d1[5]);
Print("2. s10_2.d1[5] = ",s10_2.d1[5]);
Print("3. s10_3.d1[5] = ",s10_3.d1[5]);
Print("4. s10_3.d1[0] = ",s10_3.d1[0]);
}

 
For structure type variable partial initialization is allowed, as well as for static
arrays (with an implicitly set size). You can initialize one or more first elements of
a structure or array, the other elements will be initialized with zeroes in this case.
See also
Data Types, Encapsulation and Extensibility of Types, Visibility Scope and
Lifetime of Variables, Creating and Deleting Objects
MQL4 Reference / Language Basics / Variables / Visibility Scope and Lifetime of Variables

Visibility Scope and Lifetime of Variables


There are two basic types of scope: local scope and global scope.
A variable declared outside all functions is located into the global scope. Access to such
variables can be done from anywhere in the [Link] variables are located in the
global pool of memory, so their lifetime coincides with the lifetime of the program.
A variable declared inside a block (part of code enclosed in curly brackets) belongs to
the local scope. Such a variable is not visible (and therefore not available) outside the
block, in which it is declared. The most common case of local declaration is a variable
declared within a function. A variable declared locally, is located on the stack, and the
lifetime of such a variable is equal to the lifetime of the function.
Since the scope of a local variable is the block in which it is declared, it is possible to
declare variables with the same name, as those of variables declared in other blocks; as
well as of those declared at upper levels, up to the global level.
Example:
void CalculateLWMA(int rates_total,int prev_calculated,int begin,const double &price[
int i,limit;
static int weightsum=0;
double sum=0;
//---
if(prev_calculated==0)
{
limit=MA_Period+begin;
//--- set empty value for first limit bars
for(i=0; i<limit; i++) LineBuffer[i]=0.0;
//--- calculate first visible value
double firstValue=0;
for(int i=begin; i<limit; i++)
{
int k=i-begin+1;
weightsum+=k;
firstValue+=k*price[i];
}
firstValue/=(double)weightsum;
LineBuffer[limit-1]=firstValue;
}
else
{
limit=prev_calculated-1;
}

for(i=limit;i<rates_total;i++)
{
sum=0;
for(int j=0; j<MA_Period; j++) sum+=(MA_Period-j)*price[i-j];
LineBuffer[i]=sum/weightsum;
}
//---
}
Pay attention to the variable i, declared in line
for(int i=begin; i<limit; i++)
{
int k=i-begin+1;
weightsum+=k;
firstValue+=k*price[i];
}

Its scope is only the for loop; outside of this loop there is another variable with the same
name, declared at the beginning of the function. In addition, the k variable is declared
in the loop body, its scope is the loop body.
Local variables can be declared with the access specifier static. In this case, the
compiler has a variable in the global pool of memory. Therefore, the lifetime of a static
variable is equal to the lifetime of the program. Here the scope of such a variable is
limited to the block in which it is declared.
See also
Data Types, Encapsulation and Extensibility of Types,Initialization of Variables, Creating
and Deleting Objects
MQL4 Reference / Language Basics / Variables / Creating and
Deleting Objects

Creating and Deleting Objects


After a MQL4 program is loaded for execution, memory is
allocated to each variable according to its type. According
to the access level, all variables are divided into two
types - global variables and local variables. According to
the memory class, they can be input parameters of a
MQL4 program, static and automatic. If necessary, each
variable is initialized by a corresponding value. After
being used a variable is unintialized and memory used by
it is returned to the MQL4 executable system.

Initialization and Deinitialization of Global


Variables
Global variables are initialized automatically right after a
MQL4 program is loaded and before any of function is
called. During initialization initial values are assigned to
variables of simple types and a constructor (if there is
any) is called for objects. Input variables are always
declared at a global level, and are initialized by values
set by a user in the dialog during the program start.
Despite the fact that static variables are usually declared
at a local level, the memory for these variables is pre-
allocated, and initialization is performed right after a
program is loaded, the same as for global variables.
The initialization order corresponds to the variable
declaration order in the program. Deinitialization is
performed in the reverse order. This rule is true only for
the variables that were not created by the new operator.
Such variables are created and initialized automatically
right after loading, and are deinitialized before the
program unloading.

Initialization and Deinitialization of Local


Variables
If a variable declared on a local level is not a static one,
memory is allocated automatically for such a variable.
Local variables, as well as global ones, are initialized
automatically at the moment when the program execution
meets their declaration. Thus the initialization order
corresponds to the order of declaration.
Local variables are deinitialized at the end of the program
block, in which they were declared, and in the order
opposite to their declaration. A program block is a
compound operator that can be a part of selection
operator switch, loop operator (for, while, do-while), a
function body or a part of the if-else operator.
Local variables are initialized only at the moment when
the program execution meets the variable declaration. If
during the program execution the block, in which the
variable is declared, was not executed, such a variable is
not initialized.

Initialization and Deinitialization of Objects


Placed
A special case is that with object pointers, because
declaration of a pointer does not entail initialization of a
corresponding objects. Dynamically placed objects are
initialized only at the moment when the class sample is
created by the new operator. Initialization of objects
presupposes call of a constructor of a corresponding class.
If there is no corresponding constructor in the class, its
members of a simple type will not be automatically
initialized; members of types string, dynamic array and
complex object will be automatically initialized.
Pointers can be declared on a local or global level; and
they can be initialized by the empty value of NULL or by
the value of the pointer of the same or inherited type. If
the new operator is called for a pointer declared on a
local level, the delete operator for this pointer must be
performed before exiting the level. Otherwise the pointer
will be lost and the explicit deletion of the object will
fail.
All objects created by the expression of
object_pointer=new Class_name, must be then deleted by
the delete(object_pointer) operator. If for some reasons
such a variable is not deleted by the delete operator
when the program is completed, the corresponding entry
will appear in the "Experts" journal. One can declare
several variables and assign a pointer of one object to all
of them.
If a dynamically created object has a constructor, this
constructor will be called at the moment of the new
operator execution. If an object has a destructor, it will
be called during the execution of the delete operator.
Thus dynamically placed objects are created only at the
moment when the corresponding new operator is invoked,
and are assuredly deleted either by the delete operator or
automatically by the executing system of MQL4 during the
program unloading. The order of declaration of pointers
of dynamically created object doesn't influence the order
of their initialization. The order of initialization and
deinitialization is fully controlled by the programmer.

Dynamic memory allocation in MQL4


When working with dynamic arrays, released memory is
immediately returned back to the operating system.
When working with dynamic class objects using the new
operator, first memory is requested from the class
memory pool the memory manager is working with. If
there is not enough memory in the pool, memory is
requested from the operating system. When deleting the
dynamic object using the delete operator, released
memory is immediately returned back to the class
memory pool.
Memory manager releases memory back to the operating
system immediately after exiting the following event
handling functions: OnInit(), OnDeinit(), OnStart(),
OnTick(), OnCalculate(), OnTimer(), OnTester(),
OnChartEvent().

Brief Characteristics of Variables


The main information about the order of creation,
deletion, about calls of constructors and destructors is
given in the below table.
Global Local Dynamically
automatic automatic created
variable variable object
Global Local Dynamically
automatic automatic created
variable variable object
Initialization right after a when the at the
mql4 code line execution of
program is where it is the new
loaded declared is operator
reached
during
execution
Initialization in the order in the order irrespective
order of of of the order
declaration declaration of
declaration
Deinitialization before a when when the
mql4 execution delete
program is exits the operator is
unloaded declaration executed or
block before a
mql4 program
is unloaded
Deinitialization in the order in the order irrespective
order opposite to opposite to of the
the the initialization
initialization initialization order
order order
Constructor at mql4 at at the
call program initialization execution of
loading the new
operator
Global Local Dynamically
automatic automatic created
variable variable object
Destructor call at mql4 when exiting at the
program the block execution of
unloading where the the delete
variable was operator
initialized
Error logs log message log message log message
in the in the in the
"Experts" "Experts" "Experts"
journal about journal about journal about
the attempt the attempt undeleted
to delete an to delete an dynamically
automatically automatically created
created created objects at
object object the unload of
a mql4
program

See also
Data Types, Encapsulation and Extensibility of
Types,Initialization of Variables, Visibility Scope and
Lifetime of Variables
MQL4 Reference / Language Basics / Preprocessor

Preprocessor
Preprocessor is a special subsystem of the MQL4 compiler
that is intended for preparation of the program source
code immediately before the program is compiled.
Preprocessor allows enhancement of the source code
readability. The code can be structured by including of
specific files containing source codes of mql4-programs.
The possibility to assign mnemonic names to specific
constants contributes to enhancement of the code
readability.
Preprocessor also allows determining specific parameters
of mql4-programs:
Declare constants
Set program properties
Include files in program text
Import functions
Conditional compilation
If the # symbol is used as the first character in a line of
the program, this line is considered as a preprocessor
directive. A preprocessor directive ends with a line feed
character.
MQL4 Reference / Language Basics / Preprocessor / Macro substitution (#define)

Macro substitution (#define, #undef)


The #define directive can be used to assign mnemonic names to constants. There are
two forms:
#define identifier expression // parameter-free form #define identif

The #define directive substitutes expression for all further found entries of identifier in
the source text. The identifier is replaced only if it is a separate token. The identifier is
not replaced if it is part of a comment, part of a string, or part of another longer
identifier.
The constant identifier is governed by the same rules as variable names. The value can
be of any type:
#define ABC 100
#define PI 3.14
#define COMPANY_NAME "MetaQuotes Software Corp."
...
void ShowCopyright()
{
Print("Copyright 2001-2013, ",COMPANY_NAME);
Print("[Link]
}

expression can consist of several tokens, such as keywords, constants, constant and non-
constant expressions. expression ends with the end of the line and can't be transferred
to the next line.
Example:
#define TWO 2
#define THREE 3
#define INCOMPLETE TWO+THREE
#define COMPLETE (TWO+THREE)
void OnStart()
{
Print("2 + 3*2 = ",INCOMPLETE*2);
Print("(2 + 3)*2 = ",COMPLETE*2);
}
// Result
// 2 + 3*2 = 8
// (2 + 3)*2 = 10

 
Parametric Form #define
With the parametric form, all the subsequent found entries of identifier will be replaced
by expression taking into account the actual parameters. For example:
// example with two parameters a and b
#define A 2+3
#define B 5-1
#define MUL(a, b) ((a)*(b))

double c=MUL(A,B);
Print("c=",c);
/*
expression double c=MUL(A,B);
is equivalent to double c=((2+3)*(5-1));
*/
// Result
// c=20

Be sure to enclose parameters in parentheses when using the parameters in expression,


as this will help avoid non-obvious errors that are hard to find. If we rewrite the code
without using the brackets, the result will be different:
// example with two parameters a and b
#define A 2+3
#define B 5-1
#define MUL(a, b) a*b

double c=MUL(A,B);
Print("c=",c);
/*
expression double c=MUL(A,B);
is equivalent to double c=2+3*5-1;
*/
// Result
// c=16

When using the parametric form, maximum 8 parameters are allowed.


// correct parametric form
#define LOG(text) Print(__FILE__,"(",__LINE__,") :",text) // one parameter - 'text

// incorrect parametric form


#define WRONG_DEF(p1, p2, p3, p4, p5, p6, p7, p8, p9) p1+p2+p3+p4 // more than 8 pa

 
The #undef directive
The #undef directive cancels declaration of the macro substitution, defined before.
Example:
#define MACRO

void func1()
{
#ifdef MACRO
Print("MACRO is defined in ",__FUNCTION__);
#else
Print("MACRO is not defined in ",__FUNCTION__);
#endif
}

#undef MACRO

void func2()
{
#ifdef MACRO
Print("MACRO is defined in ",__FUNCTION__);
#else
Print("MACRO is not defined in ",__FUNCTION__);
#endif
}

void OnStart()
{
func1();
func2();
}

/* Result:
MACRO is defined in func1
MACRO is not defined in func2
*/

See also
Identifiers, Character Constants
MQL4 Reference / Language Basics / Preprocessor / Program Properties (#property)

Program Properties (#property)


Every MQL4-program allows to specify additional specific parameters named #property
that help client terminal in proper servicing for programs without the necessity to launch
them explicitly. This concerns external settings of indicators, first of all. Properties
described in included files are completely ignored. Properties must be specified in the
main mq4 file.
#property identifier value

The compiler will write declared values in the configuration of the module executed.
Constant Type Description
strict   Compiler directive for strict compilation mode (see
Updated MQL4)
icon string Path to the file of an image that will be used as an icon of
the EX4 program. Path specification rules are the same as
for resources. The property must be specified in the main
module with the MQL4 source code. The icon file must be
in the ICO format.
link string Link to the company website
copyright string The company name
version string Program version, maximum 31 characters
description string Brief text description of a MQL4-program. Several
description can be present, each of them describes one
line of the text. The total length of all description can not
exceed 511 characters including line feed.
stacksize int MQL4 program stack size. The stack of sufficient size is
necessary when executing function recursive calls.
When launching a script or an Expert Advisor on the chart,
the stack of at least 8 MB is allocated. In case of
indicators, the stack size is always fixed and equal to 1
MB.
When a program is launched in the strategy tester, the
stack of 8 MB is always allocated for it.
library   A library; no start function is assigned, functions with the
export modifier can be imported in other MQL4-programs
indicator_chart_window   Show the indicator in the chart window
indicator_separate_window   Show the indicator in a separate window
indicator_height int Fixed height of the indicator subwindow in pixels
(property INDICATOR_HEIGHT)
indicator_buffers int Number of buffers for indicator calculation
indicator_minimum double The bottom scaling limit for a separate indicator window
indicator_maximum double The top scaling limit for a separate indicator window
Constant Type Description
indicator_labelN string Sets a label for the N-th graphic series displayed in
DataWindow
indicator_colorN color The color for displaying line N, where N is the number of
graphic series; numbering starts from 1
indicator_widthN int Line thickness in graphic series, where N is the number of
graphic series; numbering starts from 1
indicator_styleN int Line style in graphic series, specified by the values of
ENUM_LINE_STYLE. N is the number of graphic series;
numbering starts from 1
indicator_typeN int Type of indicator drawing style. N is the number of
graphic series; numbering starts from 1
indicator_levelN double Horizontal level of N in a separate indicator window
indicator_levelcolor color Color of horizontal levels of the indicator
indicator_levelwidth int Thickness of horizontal levels of the indicator
indicator_levelstyle int Style of horizontal levels of the indicator
script_show_confirm   Display a confirmation window before running the script
script_show_inputs   Display a window with the properties before running the
script and disable this confirmation window
tester_file string File name from <terminal_data_folder>\MQL4\Files\ to be
sent to a virtual server
tester_indicator string Indicator file name from
<terminal_data_folder>\MQL4\Indicators\ to be sent to a
virtual server
tester_library string Library file name from
<terminal_data_folder>\MQL4\Libraries\ to be sent to a
virtual server

tester_file, tester_indicator and tester_library properties are necessary for describing


the list of the files required for working in virtual hosting.
Indicator files called in iCustom() function with a fixed name, as well as all library files
used in MQL4 programs are copied automatically during the migration.
Find out more about migration of programs in the article "How to Prepare a Trading
Account for Migration to Virtual Hosting".
Sample code for moving files to a hosting
#property tester_file "trade_patterns.csv" // file with the data to be read by an

Example of an implicit indication of an indicator name in the code


string indicator_name="smoothed_ma.ex4";
double val=iCustom(NULL,0,indicator_name,13,1,0);

Sample Task of Description and Version Number


#property version "3.70" // Current version of the Expert Advisor
#property description "ZigZag universal with Pesavento Patterns"
#property description "At the moment in the indicator several ZigZags with different
#property description "It is possible to embed a large number of other indicators sho
#property description "lows and automatically build from these highs and lows various
MQL4 Reference / Language Basics / Preprocessor / Including Files
(#include)

Including Files (#include)


The #include command line can be placed anywhere in
the program, but usually all inclusions are placed at the
beginning of the source code. Call format:
#include <file_name> #include "file_name"

Examples:
#include <[Link]>
#include "[Link]"

The preprocessor replaces the line #include <file_name>


with the content of the file [Link]. Angle
brackets indicate that the [Link] file will be
taken from the standard directory (usually it is
terminal_installation_directory\MQL4\Include). The
current directory is not included in the search.
If the file name is enclosed in quotation marks, the search
is made in the current directory (which contains the main
source file). The standard directory is not included in the
search.
See also
Importing Functions
MQL4 Reference / Language Basics / Preprocessor / Importing Functions  (#import)

Importing Function (#import)


Functions are imported from compiled MQL4 modules (*.ex4 files) and from
operating system modules (*.dll files). The module name is specified in the
#import directive. For compiler to be able to correctly form the imported
function call and organize proper transmission parameters, the full
description of functions is needed. Function descriptions immediately follow
the #import "module name" directive. New command #import (can be
without parameters) completes the block of imported function descriptions.
#import "file_name" func1 define;
func2 define;
...
funcN define;
#import

Imported functions can have any names. Functions having the same names
but from different modules can be imported at the same time. Imported
functions can have names that coincide with the names of built-in functions.
Operation of scope resolution defines which of the functions should be
called.
The order of searching for a file specified after the #import keyword is
described in Call of Imported Functions.
Since the imported functions are outside the compiled module, the compiler
can not verify the validity of passed parameters. Therefore, to avoid run-
time errors, one must accurately describe the composition and order of
parameters passed to imported functions. Parameters passed to imported
functions (both from EX4, and from the DLL-module) can have default
values.
The following can't be used for parameters in imported functions:
pointers (*);
links to objects that contain dynamic arrays and/or pointers.
Classes, string arrays or complex objects that contain strings and/or dynamic
arrays of any types cannot be passed as a parameter to functions imported
from DLL.
Examples:
#import "[Link]"
int MessageBoxW(uint hWnd,string lpText,string lpCaption,uint uType);
#import "stdlib.ex4"
string ErrorDescription(int error_code);
int RGB(int red_value,int green_value,int blue_value);
bool CompareDoubles(double number1,double number2);
string DoubleToStrMorePrecision(double number,int precision);
string IntegerToHexString(int integer_number);
#import "[Link]"
int GetIntValue(int);
double GetDoubleValue(double);
string GetStringValue(string);
double GetArrayItemValue(double &arr[],int,int);
bool SetArrayItemValue(double &arr[],int,int,double);
double GetRatesItemValue(double &rates[][6],int,int,int);
#import

To import functions during execution of a mql4 program, early binding is


used. This means that the library is loaded during the loading of a program
using its ex4 program.
It's not recommended to use a fully qualified name of the loadable module of
type Drive:\Directory\[Link]. MQL4 libraries are loaded from the
terminal_dir\MQL4\Libraries folder.
See also
Including Files
MQL4 Reference / Language Basics / Preprocessor / Conditional Compilation (#ifdef, #ifndef, #else, #endif)

Conditional Compilation (#ifdef, #ifndef, #else, #endif)


Preprocessor conditional compilation directives allow compiling or skipping a part of the
program depending on the fulfillment of a certain condition.
That condition can take one of the following forms.
#ifdef identifier // the code located here is compiled if identifier has already be
#endif

#ifndef identifier
// the code located here is compiled if identifier is not currently defined by #de
#endif

Any of the conditional compilation directives can be followed by any number of lines
possibly containing #else directive and ending with #endif. If the verified condition is
true, the lines between #else and #endif are ignored. If the verified condition is not
fulfilled, all lines between checking and #else directive (or #endif directive if the former
is absent) are ignored.
Example:
#ifndef TestMode
#define TestMode
#endif
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
#ifdef TestMode
Print("Test mode");
#else
Print("Normal mode");
#endif
}

Depending on the program type and compilation mode, the standard macros are defined
the following way:
__MQL4__   macro is defined when compiling *.mq4 file, __MQL5__ macro is defined
when compiling *.mq5 one.
_DEBUG macro is defined when compiling in debug mode.
_RELEASE macro is defined when compiling in release mode.
Example:
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
#ifdef __MQL5__
#ifdef _DEBUG
Print("Hello from MQL5 compiler [DEBUG]");
#else
#ifdef _RELEASE
Print("Hello from MQL5 compiler [RELEASE]");
#endif
#endif
#else
#ifdef __MQL4__
#ifdef _DEBUG
Print("Hello from MQL4 compiler [DEBUG]");
#else
#ifdef _RELEASE
Print("Hello from MQL4 compiler [RELEASE]");
#endif
#endif
#endif
#endif
}
MQL4 Reference / Language Basics / Object-Oriented Programming

Object-Oriented Programming
Object-oriented programming (OOP) is programming
primarily focused on data, while data and behavior are
being inseparably linked. Data and behavior together
constitute a class, while objects are class instances.
The components of the object-oriented approach are:
Encapsulation and type extensibility
Inheritance
Polymorphism
Overloading
Virtual functions
OOP considers computation as modeling of behavior. The
modeled item is the object represented by computational
abstractions. Suppose we want to write a well known
game "Tetris". To do this, we must learn how to model the
appearance of random shapes composed of four squares
joined together by edges. Also we need to regulate the
falling speed of shapes, define operations of rotation and
shift of shapes. Moving of shapes on the screen is limited
by the well's boundaries, this requirement must also be
modeled. Besides that, filled rows of cubes must be
destroyed and achieved points must be counted.
Thus, this easy-to-understand game requires the creation
of several models - shape model, well model, shape
movement model and so on. All these models are
abstractions, represented by calculations in the computer.
To describe these models, the concept of Abstract Data
Type, ADT (or complex data type) is used. Strictly
speaking, the model of the "shapes" motion in the DOM is
not a data type, but it is a set of operations on the
"shape" data type, using the restrictions of the "well" data
type.
Objects are class variables. Object-oriented programming
allows you to easily create and use ADT. Object-oriented
programming uses the inheritance mechanism. The
benefit of inheritance is in the fact that it allows
obtaining derivative types from data types already
defined by a user.
For example, to create Tetris shapes, it's convenient to
create a base class Shape first. The other classes
representing all seven possible shape types can be derived
on its basis. Behavior of shapes is defined in the base
class, while implementation of behavior of each separate
shape is defined in derivative classes.
In OOP objects are responsible for their behavior. ADT
developer should include a code to describe any behavior
that would normally be expected from the corresponding
objects. The fact that the object itself is responsible for
its behavior, greatly simplifies the task of programming
for the user of this object.
If we want to draw a shape on the screen, we need to
know where the center will be and how to draw it. If a
separate shape knows how to draw itself, the programmer
should send a "draw" message when using such a shape.
The MQL4 Language is a C++ like, and it also has the
encapsulation mechanism for the implementation of ADT.
On the one hand encapsulation combines the internal
details of the implementation of a particular type, and on
the other hand it combines externally accessible functions
that can influence objects of this type. Implementation
details may be inaccessible for a program that uses this
type.
 
The concept of OOP has a set of related concepts,
including the following:
Simulation of actions from the real world
User-defined data types
Hiding the implementation details
Possibility of the code reuse through inheritance
Interpretation of function calls during execution
Some of these concepts are rather vague, some are
abstract, others are general.
MQL4 Reference / Language Basics / Object-Oriented Programming / Encapsulation and Extensibility of
Types

Encapsulation and Extensibility of Types


OOP is a balanced approach to writing software. Data and behavior are packed
together. This encapsulation creates user-defined data types, extending the
language data types and interacting with them. Types extensibility is an opportunity
to add to the language user-defined data types, which are also easy to use, as well
as basic types.
An abstract data type, for example, a string, is a description of the ideal, well
known behavior type.
The string user knows that the string operations, such as concatenation or print,
have a certain behavior. Concatenation and print operations are called methods.
A certain implementation of ADT may have some restrictions, for example, strings
can be limited in length. These limitations affect the behavior opened to all. At the
same time, internal or private implementation details do not affect directly the way
the user sees the object. For example, the string is often implemented as an array,
while the internal base address of this array and its name are not essential for the
user.
Encapsulation is the ability to hide the implementation details when the open
interfaces to user-defined type is provided. In MQL4, as well as in C++, class and
structure definitions (class and struct) are used for the encapsulation provisions in
combination with access keywords private, protected and public.
The public keyword shows that access to the members that stand behind it is open
without restrictions. Without this keyword, class members are locked by default.
Private members are accessible only by member functions only of its class.
Protected class functions are available to class functions not only in its class, but
also in its inheritor classes. Public class functions are available for any function
within the scope of the class declaration. The protection makes possible to hide
part of the class implementation, thus preventing unexpected changes in the
structure of data. Access restriction or data hiding is a feature of the object-
oriented programming.
Usually, class functions are protected and declared with the protected modifier, the
reading and writing of the values are performed by using special so-called set-and
get-methods that are defined by the public access modifier.
 
Example:
class CPerson {
protected:
string m_name; // name
public:
void SetName(string n){m_name=n;}// sets name
string GetName(){return (m_name);} // returns name
};

 
This approach offers several advantages. First, by function name we can understand
what it does - sets or gets the value of a class member. Secondly, perhaps in the
future we will need to change the type of the m_name variable in the CPerson class
or in any of its derivative classes.
In this case, we'll need just to change the implementation of functions SetName()
and GetName(), while objects of the CPerson class will be available for using in a
program without any code changes because the user will not even know that the
data type of m_name has changed.
Example:
struct Name
{
string first_name; // name
string last_name; // last name
};

class CPerson
{
protected:
Name m_name; // name
public:
void SetName(string n);
string GetName(){return(m_name.first_name+" "+m_name.last_name);}
private:
string GetFirstName(string full_name);
string GetLastName(string full_name);
};

void CPerson::SetName(string n)
{
m_name.first_name=GetFirstName(n);
m_name.last_name=GetLastName(n);
}

string CPerson::GetFirstName(string full_name)


{
int pos=StringFind(full_name," ");
if(pos>0) StringSetCharacter(full_name,pos,0);
return(full_name);
}

string CPerson::GetLastName(string full_name)


{
string ret_string;
int pos=StringFind(full_name," ");
if(pos>0) ret_string=StringSubstr(full_name,pos+1);
else ret_string=full_name;
return(ret_string);
}

See also
Data Types
MQL4 Reference / Language Basics / Object-Oriented Programming / Inheritance

Inheritance
The characteristic feature of OOP is the encouragement of code reuse through
inheritance. A new class is made from the existing, which is called the base class. The
derived class uses the members of the base class, but can also modify and supplement
them.
Many types are variations of the existing types. It is often tedious to develop a new code
for each of them. In addition, the new code implies new errors. The derived class
inherits the description of the base class, thus any re-development and re-testing of
code is unnecessary. The inheritance relationships are hierarchical.
Hierarchy is a method that allows to copy the elements in all their diversity and
complexity. It introduces the objects classification. For example, the periodic table of
elements has gases. They possess to properties inherent to all periodic elements.
Inert gases constitute the next important subclass. The hierarchy is that the inert gas,
such as argon is a gas, and gas, in its turn, is part of the system. Such a hierarchy allows
to interpret behaviour of inert gases easily. We know that their atoms contain protons
and electrons, that is true for all other elements.
We know that they are in a gaseous state at room temperature, like all the gases. We
know that no gas from inert gas subclass enters usual chemical reaction with other
elements, and it is a property of all inert gases.
Consider an example of the inheritance of geometric shapes. To describe the whole
variety of simple shapes (circle, triangle, rectangle, square etc.), the best way is to
create a base class (ADT), which is the ancestor of all the derived classes.
Let's create a base class CShape, which contains just the most common members
describing the shape. These members describe properties that are characteristic of any
shape - the type of the shape and main anchor point coordinates.
Example:
//--- The base class Shape class CShape
{
protected:
int m_type; // Shape type
int m_xpos; // X - coordinate of the base point
int m_ypos; // Y - coordinate of the base point
public:
CShape(){m_type=0; m_xpos=0; m_ypos=0;} // constructor
void SetXPos(int x){m_xpos=x;} // set X
void SetYPos(int y){m_ypos=y;} // set Y
};

Next, create new classes derived from the base class, in which we will add necessary
fields, each specifying a certain class. For the Circle shape it is necessary to add a
member that contains the radius value. The Square shape is characterized by the side
value. Therefore, derived classes, inherited from the base class CShape will be declared
as follows:
//--- The derived class circle
class CCircle : public CShape // After a colon we define the base class
{ // from which inheritance is made
private:
int m_radius; // circle radius

public:
CCircle(){m_type=1;}// constructor, type 1
};

For the Square shape class declaration is similar:


//--- the derived class Square
class CSquare : public CShape // After a colon we define the base class
{ // from which inheritance is made
private:
int m_square_side; // square side

public:
CSquare(){m_type=2;} // constructor, type 2
};

It should be noted that while object is created the base class constructor is called first,
and then the constructor of the derived class is called. When an object is destroyed first
the destructor of the derived class is called, and then a base class destructor is called.
Thus, by declaring the most general members in the base class, we can add an additional
members in derived classes, which specify a particular class. Inheritance allows creating
powerful code libraries that can be reused many times.
The syntax for creating a derived class from an already existing one is as follows:
class class_name :
(public | protected | private) opt base_class_name
{
class members declaration
};

 
One of aspects of the derived class is the visibility (openness) of its members successors
(heirs). The  public, protected and private keywords are used to indicate the extent, to
which members of the base class will be available for the derived one. The public
keyword after a colon in the header of a derived class indicates that the protected and
public members of the base class CShape should be inherited as protected and public
members of the derived class CCircle.
The private class members of the base class are not available for the derived class. The
public inheritance also means that derived classes (CCircle and CSquare) are CShapes.
That is, the Square (CSquare) is a shape (CShape), but the shape does not necessarily
have to be a square.
The derived class is a modification of the base class, it inherits the protected and public
members of the base class. The constructors and destructors of the base class cannot be
inherited. In addition to members of the base class, new members are added in a
derivative class.
The derived class may include the implementation of member functions, different from
the base class. It has nothing common with an overload, when the meaning of the same
function name may be different for different signatures.
In protected inheritance, public and protected members of base class become protected
members of derived class. In private inheritance, the public and protected members of
base class become private members of the derived class.
In protected and private inheritance, the relation that "the object of a derivative class is
object of a base class" is not true. The protected and private inheritance types are rare,
and each of them needs to be used carefully.
It should be understood that the type of inheritance (public, protected or private) does
not affect the ways of accessing the members of base classes in the hierarchy of
inheritance from a derived class. With any type of inheritance, only base class
members declared with public and protected access specifiers will be available out of
the derived classes. Let's consider it in the following example:
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link "[Link]
#property version "1.00"
//+------------------------------------------------------------------+
//| Example class with a few access types |
//+------------------------------------------------------------------+
class CBaseClass
{
private: //--- The private member is not available from derived classes
int m_member;
protected: //--- The protected method is available from the base class and
int Member(){return(m_member);}
public: //--- Class constructor is available to all members of classes
CBaseClass(){m_member=5;return;};
private: //--- A private method for assigning a value to m_member
void Member(int value) { m_member=value;};

};
//+------------------------------------------------------------------+
//| Derived class with errors |
//+------------------------------------------------------------------+
class CDerived: public CBaseClass // specification of public inheritance can be omitt
{
public:
void Func() // In the derived class, define a function with calls to base class me
{
//--- An attempt to modify a private member of the base class
m_member=0; // Error, the private member of the base class is not availa
Member(0); // Error, the private method of the base class is not availa
//--- Reading the member of the base class
Print(m_member); // Error, the private member of the base class is not availa
Print(Member()); // No error, protected method is available from the base cla
}
};

In the above example, CBaseClass has only a public method the constructor. Constructors
are called automatically when creating a class object. Therefore, the private member
m_member and the protected methods Member() cannot be called from the outside. But
in case of public inheritance, the Member() method of the base class will be available
from the derived classes.
In case of protected inheritance, all the members of the base class with public and
protected access become protected. It means that if public data members and methods
of the base class were accessible from the outside, with protected inheritance they are
available only from the classes of the derived class and its further derivatives.
//+------------------------------------------------------------------+
//| Example class with a few access types |
//+------------------------------------------------------------------+
class CBaseMathClass
{
private: //--- The private member is not available from derived classes
double m_Pi;
public: //--- Getting and setting a value for m_Pi
void SetPI(double v){m_Pi=v;return;};
double GetPI(){return m_Pi;};
public: // The class constructor is available to all members
CBaseMathClass() {SetPI(3.14); PrintFormat("%s",__FUNCTION__);}
};
//+------------------------------------------------------------------+
//| A derived class, in which m_Pi cannot be modified |
//+------------------------------------------------------------------+
class CProtectedChildClass: protected CBaseMathClass // Protected inheritance
{
private:
double m_radius;
public: //--- Public methods in the derived class
void SetRadius(double r){m_radius=r; return;};
double GetCircleLength(){return GetPI()*m_radius;};
};
//+------------------------------------------------------------------+
//| Script starting function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- When creating a derived class, the constructor of the base class will be called
CProtectedChildClass pt;
//--- Specify radius
[Link](10);
PrintFormat("Length=%G",[Link]());
//--- If we uncomment the line below, we will get an error at the stage of compilatio
// [Link](3);

//--- Now declare a variable of the base class and try to set the Pi constant equal t
CBaseMathClass bc;
[Link](10);
//--- Here is the result
PrintFormat("[Link]()=%G",[Link]());
}

The example shows that methods SetPI() and GetPi() in the base class CBaseMathClass
are open and available for calling from any place of the program. But at the same time,
for CProtectedChildClass which is derived from it these methods can be called only from
the methods of the CProtectedChildClass class or its derived classes.
In case of private inheritance, all the members of the basic class with the public and
protected access become private, and calling them becomes impossible in further
inheritance.
MQL4 has no multiple inheritance.
See also
Structures and Classes
MQL4 Reference / Language Basics / Object-Oriented Programming / Polymorphism

Polymorphism
Polymorphism is an opportunity for different classes of objects, related through
inheritance, to respond in various ways when calling the same function element. It helps
to create a universal mechanism describing the behavior of not only the base class, but
also descendant classes.
Let's continue to develop a base class CShape, and define a member function GetArea(),
designed to calculate the area of a shape. In all the descendant classes, produced by
inheritance from the base class, we redefine this function in accordance with rules of
calculating the area of a particular shape.
For a square (class CSquare), the area is calculated through its sides, for a circle (class
CCircle), area is expressed through its radius etc. We can create an array to store
objects of CShape type, in which both objects of a base class and those of all descendant
classes can be stored. Further we can call the same function for each element of the
array.
Example:
//--- Base class class CShape
{
protected:
int m_type; // Shape type
int m_xpos; // X - coordinate of the base point
int m_ypos; // Y - coordinate of the base point
public:
void CShape(){m_type=0;}; // constructor, type=0
int GetType(){return(m_type);};// returns type of the shape
virtual
double GetArea(){return (0); }// returns area of the shape
};

Now, all of the derived classes have a member function getArea(), which returns a zero
value. The implementation of this function in each descendant will vary.
//--- The derived class Circle
class CCircle : public CShape // After a colon we define the base class
{ // from which inheritance is made
private:
double m_radius; // circle radius

public:
void CCircle(){m_type=1;}; // constructor, type=1
void SetRadius(double r){m_radius=r;};
virtual double GetArea(){return (3.14*m_radius*m_radius);}// circle area
};

For the class Square the declaration is the same:


//--- The derived class Square
class CSquare : public CShape // After a colon we define the base class
{ // from which inheritance is made
private:
double m_square_side; // square side

public:
void CSquare(){m_type=2;}; // constructor, type=1
void SetSide(double s){m_square_side=s;};
virtual double GetArea(){return (m_square_side*m_square_side);}// square area
};

For calculating the area of the square and circle, we need the corresponding values of
m_radius and m_square_side, so we have added the functions SetRadius() and SetSide()
in the declaration of the corresponding class.
It is assumed that object of different types (CCircle and CSquare) derived from one base
type CShape are used in our program. Polymorphism allows creating an array of objects
of the base CShape class, but when declaring this array, these objects are yet unknown
and their type is undefined.
The decision on what type of object will be contained in each element of the array will
be taken directly during program execution. This involves the dynamic creation of
objects of the appropriate classes, and hence the necessity to use object pointers
instead of objects.
The new operator is used for dynamic creation of objects. Each such object must be
individually and explicitly deleted using the delete operator. Therefore we will declare
an array of pointers of CShape type, and create an object of a proper type for each
element (new Class_Name), as shown in the following script example:
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- Declare an array of object pointers of the base type
CShape *shapes[5]; // An array of pointers to CShape object

//--- Here fill in the array with derived objects


//--- Declare a pointer to the object of CCircle type
CCircle *circle=new CCircle();
//--- Set object properties at the circle pointer
[Link](2.5);
//--- Place the pointer value in shapes[0]
shapes[0]=circle;

//--- Create another CCircle object and write down its pointer in shapes[1]
circle=new CCircle();
shapes[1]=circle;
[Link](5);

//--- Here we intentionally "forget" to set a value for shapes[2]


//circle=new CCircle();
//[Link](10);
//shapes[2]=circle;

//--- Set NULL for the element that is not used


shapes[2]=NULL;

//--- Create a CSquare object and write down its pointer to shapes[3]
CSquare *square=new CSquare();
[Link](5);
shapes[3]=square;

//--- Create a CSquare object and write down its pointer to shapes[4]
square=new CSquare();
[Link](10);
shapes[4]=square;

//--- We have an array of pointers, get its size


int total=ArraySize(shapes);
//--- Pass in a loop through all pointers in the array
for(int i=0; i<5;i++)
{
//--- If the pointer at the specified index is valid
if(CheckPointer(shapes[i])!=POINTER_INVALID)
{
//--- Log the type and square of the shape
PrintFormat("The object of type %d has the square %G",
shapes[i].GetType(),
shapes[i].GetArea());
}
//--- If the pointer has type POINTER_INVALID
else
{
//--- Notify of an error
PrintFormat("Object shapes[%d] has not been initialized! Its pointer is %s",
i,EnumToString(CheckPointer(shapes[i])));
}
}

//--- We must delete all created dynamic objects


for(int i=0;i<total;i++)
{
//--- We can delete only the objects with pointers of POINTER_DYNAMIC type
if(CheckPointer(shapes[i])==POINTER_DYNAMIC)
{
//--- Notify of deletion
PrintFormat("Deleting shapes[%d]",i);
//--- Delete an object by its pointer
delete shapes[i];
}
}
}

Please note that when deleting an object using the delete operator, the type of its
pointer must be checked. Only objects with the POINTER_DYNAMIC pointer can be
deleted using delete. For pointers of other type, an error will be returned.
But besides the redefining of functions during inheritance, polymorphism also includes
the implementation of one and the same functions with different sets of parameters
within a class. This means that the class may have several functions with the same name
but with a different type and/or set of parameters. In this case, polymorphism is
implemented through the function overload.
 
MQL4 Reference / Language Basics / Object-Oriented Programming /
Overload

Overload
Within one class it is possible to define two or more
methods that use the same name, but have different
numbers of parameters. When this occurs, methods are
called overloaded and such a process is referred to as
method overloading.
Method overloading is one of ways of polymorphism
realization. Overloading of methods is performed
according to the same rules as the function overloading.
If the called function has no exact match, the compiler
searches for a suitable function on three levels
sequentially:
1. search within class methods.
2. search within the base class methods, consistently
from the nearest ancestor to the very first.
3. search among other functions.
If there is no exact correspondence at all levels, but
several suitable functions at different levels have been
found, the function found at the least level is used.
Within one level, there can't be more than one suitable
function.
See also
Function Overloading
MQL4 Reference / Language Basics / Object-Oriented Programming / Virtual Functions

Virtual Functions
The virtual keyword is the function specifier, which provides a mechanism to select
dynamically at runtime an appropriate function-member among the functions of basic
and derived classes. Structures cannot have virtual functions. It can be used to change
the declarations for function-members only.
The virtual function, like an ordinary function, must have an executable body. When
called, its semantic is the same as that of other functions.
A virtual function may be overridden in a derived class. The choice of what function
definition should be called for a virtual function is made dynamically (at runtime). A
typical case is when a base class contains a virtual function, and derived classes have
their own versions of this function.
The pointer to the base class can indicate either a base class object or the object of a
derived class. The choice of the member-function to call will be performed at runtime
and will depend on the type of the object, not the type of the pointer. If there is no
member of a derived type, the virtual function of the base class is used by default.
Destructors are always virtual, regardless of whether they are declared with the virtual
keyword or not.
Attention: it is not recommended to call virtual methods from constructors and
desctructors, because the result is undefined in this case.
Let's consider the use of virtual functions on the example of Tetris.mq5. The base class
CTetrisShape with the virtual function Draw is defined in the included file
[Link].
//+------------------------------------------------------------------+ class CTetrisSh
{
protected:
int m_type;
int m_xpos;
int m_ypos;
int m_xsize;
int m_ysize;
int m_prev_turn;
int m_turn;
int m_right_border;
public:
void CTetrisShape();
void SetRightBorder(int border) { m_right_border=border; }
void SetYPos(int ypos) { m_ypos=ypos; }
void SetXPos(int xpos) { m_xpos=xpos; }
int GetYPos() { return(m_ypos); }
int GetXPos() { return(m_xpos); }
int GetYSize() { return(m_ysize); }
int GetXSize() { return(m_xsize); }
int GetType() { return(m_type); }
void Left() { m_xpos-=SHAPE_SIZE; }
void Right() { m_xpos+=SHAPE_SIZE; }
void Rotate() { m_prev_turn=m_turn; if(++m_turn>3)
virtual void Draw() { return; }
virtual bool CheckDown(int& pad_array[]);
virtual bool CheckLeft(int& side_row[]);
virtual bool CheckRight(int& side_row[]);
};

Further, for each derived class, this function is implemented in accordance with
characteristics of a descendant class. For example, the first shape CTetrisShape1 has its
own implementation of the Draw() function:
class CTetrisShape1 : public CTetrisShape
{
public:
//--- shape drawing
virtual void Draw()
{
int i;
string name;
//---
if(m_turn==0 || m_turn==2)
{
//--- horizontal
for(i=0; i<4; i++)
{
name=SHAPE_NAME+(string)i;
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,m_xpos+i*SHAPE_SIZE);
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,m_ypos);
}
}
else
{
//--- vertical
for(i=0; i<4; i++)
{
name=SHAPE_NAME+(string)i;
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,m_xpos);
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,m_ypos+i*SHAPE_SIZE);
}
}
}
}

The Square shape is described by class CTetrisShape6 and has its own implementation of
the Draw() method:
class CTetrisShape6 : public CTetrisShape
{
public:
//--- Shape drawing
virtual void Draw()
{
int i;
string name;
//---
for(i=0; i<2; i++)
{
name=SHAPE_NAME+(string)i;
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,m_xpos+i*SHAPE_SIZE);
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,m_ypos);
}
for(i=2; i<4; i++)
{
name=SHAPE_NAME+(string)i;
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,m_xpos+(i-2)*SHAPE_SIZE);
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,m_ypos+SHAPE_SIZE);
}
}
};

Depending on the class, to which the created object belongs, it calls the virtual function
of this or that derived class.
void CTetrisField::NewShape()
{
//--- creating one of the 7 possible shapes randomly
int nshape=rand()%7;
switch(nshape)
{
case 0: m_shape=new CTetrisShape1; break;
case 1: m_shape=new CTetrisShape2; break;
case 2: m_shape=new CTetrisShape3; break;
case 3: m_shape=new CTetrisShape4; break;
case 4: m_shape=new CTetrisShape5; break;
case 5: m_shape=new CTetrisShape6; break;
case 6: m_shape=new CTetrisShape7; break;
}
//--- draw
m_shape.Draw();
//---
}

 
MQL4 Reference / Language Basics / Object-Oriented Programming / Static Members of a Class

Static members of a Class/Structure


Static Members
The members of a class can be declared using the storage class modifier static. These
data members are shared by all instances of this class and are stored in one place. Non-
static data members are created for each class object variable.
The inability to declare static members of a class would have led to the need to declare
these data on the the global level of the program. It would break the relationship
between the data and their class, and is not consistent with the basic paradigm of the
OOP - joining data and methods for handling them in a class. The static member allows
class data that are not specific to a particular instance to exist in the class scope.
Since a static class member does not depend on the particular instance, the reference to
it is as follows:
class_name::variable

where class_name is the name of the class, and variable is the name of the class
member.
As you see, to access the static member of a class, context resolution operator :: is
used. When you access a static member within class methods, the context operator is
optional.
Static member of a class has to be explicitly initialized with desired value. For this it
must be declared and initialized in global scope. The sequence of static members
initialization will correspond to the sequence of their declaration in global scope.
For example, we have a class CParser used for parsing the text, and we need to count
the total number of processed words and characters. We only need to declare the
necessary class members as static and initialize them at the global level. Then all
instances of the class will use common counters of words and characters.
//+------------------------------------------------------------------+ //| Class "Text
//+------------------------------------------------------------------+
class CParser
{
public:
static int s_words;
static int s_symbols;
//--- Constructor and destructor
CParser(void);
~CParser(void){};
};
...
//--- Initialization of static members of the Parser class at the global level
int CParser::s_words=0;
int CParser::s_symbols=0;

A static class member can be declared with the const keyword. Such static constants
must be initialized at the global level with the const keyword:
//+------------------------------------------------------------------+
//| Class "Stack" for storing processed data |
//+------------------------------------------------------------------+
class CStack
{
public:
CStack(void);
~CStack(void){};
...
private:
static const int s_max_length; // Maximum stack capacity
};

//--- Initialization of the static constant of the CStack class


const int CStack::s_max_length=1000;

Pointer this
The keyword this denotes an implicitly declared pointer to itself to a specific instance of
the class, in the context of which the method is executed. It can be used only in non-
static methods of the class. Pointer this is an implicit non-static member of any class.
In static functions you can access only static members/methods of a class.

Static Methods
In MQL4 member functions of type static can be used. The static modifier must precede
the return type of a function in the declaration inside a class.
class CStack
{
public:
//--- Constructor and destructor
CStack(void){};
~CStack(void){};
//--- Maximum stack capacity
static int Capacity();
private:
int m_length; // The number of elements in the stack
static const int s_max_length; // Maximum stack capacity
};
//+------------------------------------------------------------------+
//| Returns the maximum number of elements to store in the stack |
//+------------------------------------------------------------------+
int CStack::Capacity(void)
{
return(s_max_length);
}
//--- Initialization of the static constant of the CStack class
const int CStack::s_max_length=1000;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- declare CStack type variable
CStack stack;
//--- call the object's static method
Print("CStack.s_max_length=",[Link]());
//--- it can also be called the following way, as the method is static and does not r
Print("CStack.s_max_length=",CStack::Capacity());
}

A method with the const modifier is called constant and cannot modify implicit members
of its class. Declaration of constant functions of a class and constant parameters is
called const-correctness control. Through this control you can be sure that the compiler
will ensure the consistency of values of objects and will return an error during
compilation if there is something wrong.
The const modifier is placed after the list of arguments inside a class declaration.
Definition outside a class should also include the const modifier:
//+------------------------------------------------------------------+
//| Class "Rectangle" |
//+------------------------------------------------------------------+
class CRectangle
{
private:
double m_width; // Width
double m_height; // Height
public:
//--- Constructors and destructor
CRectangle(void):m_width(0),m_height(0){};
CRectangle(const double w,const double h):m_width(w),m_height(h)
~CRectangle(void){};
//--- Calculating the area
double Square(void) const;
static double Square(const double w,const double h);// { return(w*h); }
};
//+------------------------------------------------------------------+
//| Returns the area of the "Rectangle" object |
//+------------------------------------------------------------------+
double CRectangle::Square(void) const
{
return(Square(m_width,m_height));
}
//+------------------------------------------------------------------+
//| Returns the product of two variables |
//+------------------------------------------------------------------+
static double CRectangle::Square(const double w,const double h)
{
return(w*h);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- Create a rectangle rect with the sides equal to 5 and 6
CRectangle rect(5,6);
//--- Find the rectangle area using a constant method
PrintFormat("[Link]()=%.2f",[Link]());
//--- Find the product of numbers using the static method of class CRectangle
PrintFormat("CRectangle::Square(2.0,1.5)=%f",CRectangle::Square(2.0,1.5));
}

An additional argument in favor of using the constancy control is the fact that in this
case, the compiler generates a special optimization, for example, places a constant
object in read-only memory.
A static function cannot be determined with the const modifier, because this modifier
ensures the constancy of the instance members when calling this function. But, as
mentioned above, the static function cannot access non-static class members.
See also
Static Variables, Variables, References. Modifier & and Keyword this
MQL4 Reference / Language Basics / Object-Oriented Programming / Function Templates

Function Templates
Overloaded functions are commonly used to perform similar operations on
various data types. ArraySize() is a simple example of such function in
MQL4. It returns size of any type of array. In fact, this system function is
overloaded and the entire implementation of such an overload is hidden
from MQL4 application developers:
int ArraySize( void& array[] // checked array
);

It means that MQL4 language compiler inserts necessary implementation for


each call of this function. For example, that is how it can be done for
integer type arrays:
int ArraySize(
int& array[] // array with int type elements
);

ArraySize() function can be displayed the following way for MqlRates type
array for working with quotations in historical data format:
int ArraySize(
MqlRates& array[] // array filled with MqlRates type values
);

Thus, it is very convenient to use the same function for working with
different types. However, all preliminary work should be carried out the
necessary function should be overloaded for all data types it should
correctly work with.
There is a convenient solution. If similar operations should be executed for
each data type, it is possible to use function templates. In this case, a
programmer needs to write only one function template description. When
describing the template in such a way, we should specify only some formal
parameter instead of some definite data type the function should work
with. The compiler will automatically generate various functions for the
appropriate handling of each type based on the types of the arguments used
when calling the function.
Function template definition starts with the template keyword followed by
the list of formal parameters in angle brackets. Each formal parameter is
preceded by the typename keyword. Formal parameter types are built-in or
user-defined types. They are used:
to specify the types of function arguments,
to specify the types of function's return value,
to declare the variables inside the function definition
 
Number of template parameters cannot exceed eight. Each formal
parameter in the template definition should appear in the list of function
parameters at least once. Each name of the formal parameter should be
unique.
Below is an example of a function template for searching the highest value
in the array of any numeric type (integer and real numbers):
template<typename T>
T ArrayMax(T &arr[])
{
uint size=ArraySize(arr);
if(size==0) return(0);

T max=arr[0];
for(uint n=1;n<size;n++)
if(max<arr[n]) max=arr[n];
//---
return(max);
}

This template defines the function that finds the highest value in the
passed array and returns this value as a result. Keep in mind that the
ArrayMaximum() function built in MQL4 returns only the highest value index
that can be used to find the value itself. For example:
//--- create an array
double array[];
int size=50;
ArrayResize(array,size);
//--- fill with random values
for(int i=0;i<size;i++)
{
array[i]=MathRand();
}

//--- find position of the highest value in the array


int max_position=ArrayMaximum(array);
//--- now, get the highest value itself in the array
double max=array[max_position];
//--- display the found value
Print("Max value = ",max);
Thus, we have performed two steps to get the highest value in the array.
With ArrayMax() function template, we can get the result of the necessary
type just by passing the array of an appropriate type into this function. It
means that instead of two last lines
//--- find position of the highest value in the array
int max_position=ArrayMaximum(array);
//--- now, receive the highest value itself in the array
double max=array[max_position];

we now can use only one line, in which the returned result has the same
type as the array passed into function:
//--- find the highest value
double max=ArrayMax(array);

In this case, the type of result returned by the ArrayMax() function will
automatically match the type of array.
 
Use the typename keyword to get the argument type as a string in order to
create general purpose methods of working with various data types. Let's
consider a specific example of the function that returns data type as a
string:
#include <Trade\[Link]>
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnStart()
{
//---
CTrade trade;
double d_value=M_PI;
int i_value=INT_MAX;
Print("d_value: type=",GetTypeName(d_value), ", value=", d_value);
Print("i_value: type=",GetTypeName(i_value), ", value=", i_value);
Print("trade: type=",GetTypeName(trade));
//---
}
//+------------------------------------------------------------------+
//| Type is returned as a line |
//+------------------------------------------------------------------+
template<typename T>
string GetTypeName(const T &t)
{
//--- return the type as a line
return(typename(T));
//---
}

 
Function templates can also be used for class methods, for example:
class CFile
{
...
public:
...
template<typename T>
uint WriteStruct(T &data);
};

template<typename T>
uint CFile::WriteStruct(T &data)
{
...
return(FileWriteStruct(m_handle,data));
}

Function templates should not be declared with export, virtual and #import
keywords.
Template function overload
A template function overload may be necessary sometimes. For example,
we have a template function that writes the value of the second parameter
to the first one using typecasting. MQL5 does not allow typecasting string to
bool. We can do that ourselves let's create an overload of a template
function. For example:
//+------------------------------------------------------------------+
//| Template function |
//+------------------------------------------------------------------+
template<typename T1,typename T2>
string Assign(T1 &var1,T2 var2)
{
var1=(T1)var2;
return(__FUNCSIG__);
}
//+------------------------------------------------------------------+
//| Special overload for bool+string |
//+------------------------------------------------------------------+
string Assign(bool &var1,string var2)
{
var1=(StringCompare(var2,"true",false) || StringToInteger(var2)!=0);
return(__FUNCSIG__);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
int i;
bool b;
Print(Assign(i,"test"));
Print(Assign(b,"test"));
}

As a result of the code execution, we can see that the Assign() template
function has been used for the int+string pair, while the overloaded version
has already been used for the bool+string pair during the second call.
string Assign<int,string>(int&,string)
string Assign(bool&,string)

 
See also
Overload
MQL4 Reference / Language Basics / Object-Oriented Programming / Class Templates

Template advantages
Function templates are used when you need to perform similar operations on various
data types, for example, searching for a maximum element in the array.   The main
advantage of applying the templates is that you do not have to code a separate overload
for each type.  Instead of declaring multiple overloads of each type
double ArrayMax(double array[]) {
...
}
int ArrayMax(int array[])
{
...
}
uint ArrayMax(uint array[])
{
...
}
long ArrayMax(long array[])
{
...
}
datetime ArrayMax(datetime array[])
{
...
}

we need to write only one template function


template<typename T>
T ArrayMax(T array[])
{
if(ArraySize()==0)
return(0);
uint max_index=ArrayMaximum(array);
return(array[max_index]);
}

to use it in your code:


double high[];
datetime time[];
....
double max_high=ArrayMax(high);
datetime lasttime=ArrayMax(time);

Here, the T formal parameter specifying a type of used data is replaced with an actually
applied type during compilation, i.e. the compiler automatically generates a separate
function for each type double, datetime, etc. MQL5 also allows you to develop class
templates using all the advantages of the approach.

Class templates
A class template is declared using the template keyword followed by angle brackets<>
enumerating the list of formal parameters with the typename keyword. This entry
informs the compiler that it deals with a generic class with the T formal parameter
defining a real variable type when implementing a class. For example, let's create a
vector class for storing an array with T type elements:
#define TOSTR(x) #x+" " // macro for displaying an object name
//+------------------------------------------------------------------+
//| Vector class for storing T-type elements |
//+------------------------------------------------------------------+
template <typename T>
class TArray
{
protected:
T m_array[];
public:
//--- constructor creates an array for 10 elements by default
void TArray(void){ArrayResize(m_array,10);}
//--- constructor for creating a vector with a specified array size
void TArray(int size){ArrayResize(m_array,size);}
//--- return a type and amount of data stored in the TArray type object
string Type(void){return(typename(m_array[0])+":"+(string)ArraySize(m_array));};
};

Next, let's apply different methods to create three TArray objects in the program for
working with various types
void OnStart()
{
TArray<double> double_array; // vector has a default size of 10
TArray<int> int_array(15); // vector has a size of 15
TArray<string> *string_array; // pointer to TArray<string> vector
//--- create a dynamic object
string_array=new TArray<string>(20);
//--- display an object name, data type and vector size in the Journal
PrintFormat("%s (%s)",TOSTR(double_array),double_array.Type());
PrintFormat("%s (%s)",TOSTR(int_array),int_array.Type());
PrintFormat("%s (%s)",TOSTR(string_array),string_array.Type());
//--- remove a dynamic object before completing the program
delete(string_array);
}

Script execution results:


double_array (double:10)
int_array (int:15)
string_array (string:20)

Now, we have 3 vectors with different data types: double, int and string.
Class templates are well suited for developing containers objects designed for
encapsulating other objects of any type. Container objects are collections already
containing objects of one certain type. Usually, working with stored data is instantly
built into the container.
For example, you can create a class template that does not allow accessing an element
outside the array, thus avoiding the "out of range" critical error.
//+------------------------------------------------------------------+
//| Class for a free access to an array element |
//+------------------------------------------------------------------+
template<typename T>
class TSafeArray
{
protected:
T m_array[];
public:
//--- default constructor
void TSafeArray(void){}
//--- constructor for creating the array of a specified size
void TSafeArray(int size){ArrayResize(m_array,size);}
//--- array size
int Size(void){return(ArraySize(m_array));}
//--- change the array size
int Resize(int size,int reserve){return(ArrayResize(m_array,size,res
//--- release the array
void Erase(void){ZeroMemory(m_array);}
//--- operator for accessing the array element by index
T operator[](int index);
//--- assignment operator for receiving all elements from the array at once
void operator=(const T &array[]); // T type array
};
//+------------------------------------------------------------------+
//| Receiving an element by index |
//+------------------------------------------------------------------+
template<typename T>
T TSafeArray::operator[](int index)
{
static T invalid_value;
//---
int max=ArraySize(m_array)-1;
if(index<0 || index>=ArraySize(m_array))
{
PrintFormat("%s index %d is not in range (0-%d)!",__FUNCTION__,index,max);
return(invalid_value);
}
//---
return(m_array[index]);
}
//+------------------------------------------------------------------+
//| Assigning for the array |
//+------------------------------------------------------------------+
template<typename T>
void TSafeArray::operator=(const T &array[])
{
int size=ArraySize(array);
ArrayResize(m_array,size);
//--- T type should support the copying operator
for(int i=0;i<size;i++)
m_array[i]=array[i];
//---
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
int copied,size=15;
MqlRates rates[];
//--- copy the array of quotes
if((copied=CopyRates(_Symbol,_Period,0,size,rates))!=size)
{
PrintFormat("CopyRates(%s,%s,0,%d) returned %d error code",
_Symbol,EnumToString(_Period),size,GetLastError());
return;
}
//--- create a container and insert the MqlRates value array to it
TSafeArray<MqlRates> safe_rates;
safe_rates=rates;
//--- index within the array
int index=3;
PrintFormat("Close[%d]=%G",index,safe_rates[index].close);
//--- index outside the array
index=size;
PrintFormat("Close[%d]=%G",index,safe_rates[index].close);
}

Please note that template declaration should also be used when describing methods
outside the class declaration:
template<typename T>
T TSafeArray::operator[](int index)
{
...
}
template<typename T>
void TSafeArray::operator=(const T &array[])
{
...
}

Class and function templates allow you to define multiple comma-separated formal
parameters, for example, Map collection for storing "key value" pairs:
template<typename Key, template Value>
class TMap
{
...
}

 
See also
Function templates, Overload
MQL4 Reference / Language Basics / Object-Oriented Programming / Abstract Classes

Abstract Classes and Pure Virtual Functions


Abstract classes are used for creating generic entities, that you expect to use for
creating more specific derived classes. An abstract class can only be used as the base
class for some other class, that is why it is impossible to create an object of the abstract
class type.
A class which contains at least one pure virtual function in it is abstract. Therefore,
classes derived from the abstract class must implement all its pure virtual functions,
otherwise they will also be abstract classes.
A virtual function is declared as "pure" by using the pure-specifier syntax. Consider the
example of the CAnimal class, which is only created to provide common functions the
objects of the CAnimal type are too general for practical use. Thus, CAnimal is a good
example for an abstract class:
class CAnimal {
public:
CAnimal(); // Constructor
virtual void Sound() = 0; // A pure virtual function
private:
double m_legs_count; // The number of the animal's legs
};

Here Sound() is a pure virtual function, because it is declared with the specifier of the
pure virtual function PURE (=0).
Pure virtual functions are only the virtual functions for which the PURE specifier is set:
(=NULL) or (=0). Example of abstract class declaration and use:
class CAnimal
{
public:
virtual void Sound()=NULL; // PURE method, should be overridden in the der
};
//--- Derived from an abstract class
class CCat : public CAnimal
{
public:
virtual void Sound() { Print("Myau"); } // PURE is overridden, CCat is not a
};

//--- Examples of wrong use


new CAnimal; // Error of 'CAnimal' - the compiler returns the "cannot instant
CAnimal some_animal; // Error of 'CAnimal' - the compiler returns the "cannot instant

//--- Examples of proper use


new CCat; // No error - the CCat class is not abstract
CCat cat; // No error - the CCat class is not abstract

 
Restrictions on abstract classes
If the constructor for an abstract class calls a pure virtual function (either directly or
indirectly), the result is undefined.
//+------------------------------------------------------------------+
//| An abstract base class |
//+------------------------------------------------------------------+
class CAnimal
{
public:
//--- A pure virtual function
virtual void Sound(void)=NULL;
//--- Function
void CallSound(void) { Sound(); }
//--- Constructor
CAnimal()
{
//--- An explicit call of the virtual method
Sound();
//--- An implicit call (using a third function)
CallSound();
//--- A constructor and/or destructor always calls its own functions,
//--- even if they are virtual and overridden by a called function in a derived
//--- If the called function is pure virtual,
//--- its call will cause a critical runtime error: "pure virtual function call"
}
};

However, constructors and destructors for abstract classes can call other member
functions.
 
MQL4 Reference / Language Basics / Updated MQL4

What's New in MQL4


Starting from build 600, MQL4 programming language has been completely revised
reaching the level of MQL5 - now you can develop trading robots in MQL4/5 using the
unified MetaEditor development environment, single style, libraries and debugging
tools.
MQL4 is popular among automated system developers due to the ease of learning and a
huge amount of code generated for many years of using MetaTrader 4 terminal.
However, the language also has some drawbacks arising from its main advantage - a
simple programming language does not allow development of complex systems and
hinders porting of debugged libraries from high-level languages. Therefore, we decided
to implement in it the maximum possible amount of MQL5 language functions and
features fully preserving MQL4 functionality. In other words, all powerful MQL5
functions, including ООP and the native code compiler, will become available in MQL4.
To achieve this, we have developed a unified compiler that automatically supports both
MQL4 and MQL5 languages. MetaEditor will also become a unified application both for
MetaTrader 4 and MetaTrader 5 platforms. Thus, it will be possible to compile both
MQL4 and MQL5 from any version. MQL5 Storage also becomes available for work.
Protection of MQL4 applications rises to MQL5 level. New EX4/EX5 files are provided
with a serious and completely revised protection. This means that the Market of secure
EX4 applications also becomes available to MetaTrader 4.
Besides, MQL4 now features new graphical objects and new functions for working with
charts. MQL5 Standard Library is to be ported to MQL4 providing developers with new
possibilities in creating their own graphical interfaces and trading libraries. Now, you
can create full-fledged applications in MetaTrader 4 using the resources.  
Changes in MQL4 Language
Added new char, short, long, uchar, ushort, uint, ulong and double data types. This will
allow transferring codes from other C++ like languages. Data of various types is
processed at different rates. Integer data is the fastest one to be processed. A special
co-processor is used to handle the double-precision data. However, due to the
complexity of the internal representation of floating-point data, it is processed slower
than integer one. Typecasting has also been implemented.
Strings are now presented in Unicode format, though they were in ANSI format (single
byte ones) before. That should be considered if the program uses DLLs and passes
string variables to them.
Predefined Volume variable is now of long type. The time series for accessing the
volumes also consist of long type arrays. It is recommended to use explicit casting of
data having this type to the target type in old MQL4 programs to avoid type overflow
error.
Structures and classes, object pointers, void type and this key word allowing an object
to receive a reference to itself have been added. All object-oriented programming
standards are supported:
Encapsulation and Extensibility of Types
Inheritance
Polymorphism
Overload
Virtual functions
ООP allows developing programs using classes. This facilitates debugging and
development of large applications, as well as provides ability to reuse previously
generated code multiple times due to inheritance. However, that does not mean that
you cannot generate your MQL4 code in procedure-oriented style as before. You can
develop your programs as you did in the past if you don't need the new features.
init(), deinit() and start() predefined functions have remained for compatibility,
however, OnInit(), OnDeinit(), OnStart(), OnCalculate() and OnTick() ones can now be
used instead. Besides, new predefined OnTimer(), OnChartEvent() and OnTester()
handler functions have been implemented. In the previous MQL4, predefined functions
could have any parameters and any return type, and they could be called by their
names, not signatures. In the new MQL4, all predefined functions should strictly
correspond to their signatures. In other words, they should have precisely defined set
of parameters and return type.
Now, variable names cannot contain special characters and points, and new MQL4
language keywords cannot be used as names. Old MQL4 programs can be recompiled
with the new compiler in order to easily correct all such errors while following the
compiler's messages.
The Precedence rule now matches C language standards. If you are unsure, you can
insert parentheses in old MQL4 apps to clearly indicate the priority to increase
reliability.
Shortened conditions check is now used in logical operations, unlike the old MQL4
version where all expressions have been calculated and the check has been performed
afterwards. Suppose there is a check of two conditions with the use of logical AND:
if(condition1 && condition2)
{
// some block of statements
}

If condition1 expression is false, calculation of condition2 expression is not performed,


as false && true result is still equal to false.
 
ArrayCopyRates() function behavior has changed. In the previous MQL4 versions this
function was used for copying price series to array double[][6]. Now, if you need to
receive a time series, use the arrays of the MqlRates structure elements:
//--- Structure that stores information about the prices, volumes and spread.
struct MqlRates
{
datetime time; // Period start time
double open; // Open price
double high; // The highest price of the period
double low; // The lowest price of the period
double close; // Close price
long tick_volume; // Tick volume
int spread; // Spread
long real_volume; // Trade volume
};

Also the new function format can be used for virtual copying, when there is no actual
copying, and accessing the copied values you actually access the price data.
int ArrayCopyRates(
MqlRates& rates_array[], // MqlRates array, passed by reference
string symbol=NULL, // symbol
int timeframe=0 // timeframe
);

To provide compatibility with old MQL4 programs, the previous call format is also
preserved, but now it leads to actual copying of data into a double-type array.
int ArrayCopyRates(
void& dest_array[][], // destination array, passed by reference
string symbol=NULL, // symbol
int timeframe=0 // timeframe
);

This means that when the values in the time series change (new bars are added,
restructuring, the last bar's Close price is uodated), you must re-copy the required data
into the dest_array[][]. The receiver array will be automatically allocated for the
required number of copied bars, even if it was declared statically.
 
Changed RateInfo history data storage format. RateInfo structure was presented as
follows in the old version:
struct RateInfo
{
unsigned int ctm; // bar open date
double open; // Open price
double low; // Low price
double high; // High price
double close; // Close price
double vol; // volume
};

In the new format, RateInfo structure features fields for storing spread and trading
volume:
//--- Standard quote presentation in the new terminal version
struct RateInfo
{
INT64 ctm; // open date and time
double open; // Open price (absolute value)
double high; // Low price
double low; // High price
double close; // Close price
UINT64 vol; // tick volume
INT32 spread; // spread
UINT64 real; // trade volume
};

Thus, if MQL4 programs contain DLLs for passing/accepting price data, the
corresponding functions in the source codes should be rewritten and recompiled
considering format changes to ensure proper operation.
Old EX4 applications and DLLs based on old RateInfo format will not work in the new
terminal. Conversion to the new format is required.

 
In file operations, the number of simultaneously opened files can now reach 64 ones,
while there could be no more than 32 ones in the old MQL4. Until recently, the files
were always opened in FILE_SHARE_READ or FILE_SHARE_WRITE mode. Now, the
necessary opening mode should be specified explicitly.
For FileWrite(), FileWriteArray(), FileWriteDouble(), FileWriteInteger() and
FileWriteString() functions the type of returned value has been changed from int to
uint. The functions return the number of bytes, actually written or 0 in case of error
(in old version of MQL4 the negative number is returned in case of error).
Working with functions, scope of variables and memory release in local arrays has also
been changed. Since the number of changes is large enough, the new #property strict
property has been introduced to provide maximum compatibility with the previous
approach to developing MQL4 programs. When creating new MQL4 application using
MQL wizard, this property is always added to the template.
The string representation of datetime type depends on compilation mode:
datetime date=D'2014.03.05 [Link]';
string str="mydate="+date;
//--- str="mydate=1394034418" - old compiler/new compiler without #property strict
//--- str="mydate=2014.03.05 [Link]" - new compiler with #property strict

The table below contains the differences between MQL4, new MQL4 without using strict
and new MQL4 with specified strict compilation mode:
#property strict

When compiling libraries in the strict mode, the export modifier should be added for
each exported function, otherwise the function will not be accessible from outside.
The table of differences between compilers:
Old MQL4 compiler New MQL4 compiler New MQL4 with #property
strict
Old MQL4 compiler New MQL4 compiler New MQL4 with #property
strict
init(), start() and deinit() init(), start() and deinit() Ditto
entry points may have any have been remained intact for
parameters and any return compatibility,
type while new OnInit(), OnStart(),
OnCalculate(), OnTick(),
OnTimer(), OnChartEvent(),
OnTester() and OnDeinit()
should strictly correspond to
their signatures
The result of the return from The result of the return from If a non-zero value is returned
init() function is not analyzed init() and OnInit() functions is from OnInit(), the operation of
by the runtime subsystem not analyzed by the runtime an Expert Advisor or an
subsystem indicator is stopped, the
program is unloaded
Virtually any variable names Variable names cannot have Ditto
(except for the reserved special characters and points.
words) are possible, including The list of the reserved words
special characters and points has been expanded. Thus,
such widespread words as
short, long, const, etc. cannot
be used as names
Variable scope is from Ditto Variable scope is from
declaration (even in the declaration to the end of the
nested block) to the function block, in which the variable is
end declared
Implicit initialization of all Ditto Only global variables are
the variables (both global and initialized. In local variables,
local ones) by zero only strings are initialized
implicitly
Local arrays are not released Local arrays are released Local arrays are released when
when exiting the function when exiting the function exiting {} block
"Array out of range" does not Ditto, except for the arrays of "Array out of range" is a
cause a critical error structures and classes, for critical error causing the
which this error is critical one program to stop
No structures and classes Structures and classes are Ditto
present. Additional data types
are implemented
Strings are single-byte. Strings are unicode ones. Ditto
datetime is a 32-bit integer datetime is a 64-bit integer
Predefined Volume variable is Predefined Volume variable is
of double type of long type
Old MQL4 compiler New MQL4 compiler New MQL4 with #property
strict
ArrayCopyRates() performs ArrayCopyRates() performs Ditto
virtual copying to double[][6] virtual copying to MqlRates[]
array array. Copying to double[][6]
array has remained intact for
the sake of compatibility,
however, that copying is real,
not virtual.
The functions may not return Ditto Functions of any type should
values even if they have a return a value
type. To do this, return(0) is
automatically inserted by the
compiler in the function end
The number of The number of simultaneously Ditto
simultaneously opened files is opened files is 64
32
The files are always opened FILE_SHARE_READ and/or Ditto
in FILE_SHARE_READ, FILE_SHARE_WRITE should be
FILE_SHARE_WRITE mode ** specified explicitly
The names of extern The names of extern and String comments instead of
variables are displayed for input variables are displayed extern and input variable
scripts in the input for scripts in show_inputs names are displayed for scripts
parameters window mode in the input parameters in show_inputs mode in the
window input parameters window

* Please pay special attention to "Array out of range" error - many old custom indicators
will display this error in strict mode of the new compiler when launched on the chart.
It is recommended to find the cause and eliminate it.
**   In the new MQL4 and MQL5, FILE_SHARE_READ and FILE_SHARE_WRITE flags are
responsible for the files shared use mode. There were no such files in the old MQL4.
 
Changes in File Structure
In the previous builds of MetaTrader 4 client terminal (509 and older), all MQL4
applications were stored in the following subdirectories of
<terminal_installation_folder>\experts\ root directory:
\experts - Expert Advisors (trading robots),
\experts\indicators - custom indicators,
\experts\scripts - scripts (MQL4 applications for a single run on the chart),
\include - source code MQH and MQ4 files implemented into other programs,
\libraries - libraries in the form of MQ4 source codes and EX4 executable files
compiled from them. They are used for the dynamic call of the functions contained
there by other MQL4 programs,
\files - special "file sandbox". MQL4 applications are allowed to execute file
operations only within this directory.
 
In the new MQL4 version, the file structure for storing the source codes has changed.
Now, all MQL4 applications should be located in the appropriate folders of
<data_folder>\MQL4\ directory:
\Experts - Expert Advisors (trading robots),
\Indicators - custom indicators,
\Scripts - scripts (MQL4 applications for a single run on the chart),
\Include - source code MQH and MQ4 files implemented into other programs,
\Libraries - libraries in the form of MQ4 source codes and EX4 executable files
compiled from them. They are used for the dynamic call of the functions contained
there by other MQL4 programs,
\Images - image files for using in resources,
\Files - special "file sandbox". MQL4 applications are allowed to execute file
operations only within this directory.
When updating MetaTrader 4 terminal from build 509 to the newer version, all MQ4,
MQH and EX4 files from standard root directories of the previous version are
automatically copied and relocated to the appropriate folders. Subfolders additionally
created by a user, as well as files contained there are not processed. They should be
relocated to the new place manually if necessary.
 
No files or folders are deleted during the update! All file copy operations including used file
paths are fixed in the terminal Journal during the update.

 
No automatic re-compilation of the old EX4 files to the new version is performed
during the update. Users are free to decide what source codes should be compiled to
the new EX4 version. All old EX4 will work in the new MetaTrader 4 terminal. EX4
libraries compiled by the new compiler can be called only from the EX4 programs that
have also been compiled in the new version.
In some cases, you may need to edit the path in #include for included files (if relative
paths have changed) in the source files. Please note that MetaEditor's root directory is
now <data_folder>\MQL4\. All programs should be located in the correct subdirectories.
You can find the data folder (<data_folder>) for each copy of MetaTrader 4 terminal on
your computer via the terminal menu or in MetaEditor: File - Open Data Folder.
MQL4 Reference / Constants, Enumerations and Structures

Constants, Enumerations and Structures


To simplify the program writing and to make program
texts more convenient for perception, the MQL4 language
provides predefined standard constants and
enumerations. Besides that, service structures are used
for storing information.
Standard constants are similar to macros and are of int
type.
The constants are grouped by their purposes:
Chart constants are used when working with price
charts: opening, navigation, setting parameters;
Objects constants are intended for processing graphical
objects that can be created and displayed in charts;
Indicators constants are used for working with standard
and custom indicators;
Environment state constants describe properties of a
MQL4-program, show information about a client
terminal, financial instrument and current account;
Trade constants allow to specify a variety of
information in the course of trading;
Named constants are constants of the MQL4 language;
Data structures describe data storage formats used;
Codes of errors and warnings describe compiler
messages and trading server answers to trade requests;
In/out constants are designed for working with file
functions and displaying messages on the screen by the
MessageBox() function.
 
MQL4 Reference / Constants, Enumerations and Structures / Chart Constants

Chart Constants
Constants describing various properties of charts are divided into the
following groups:
Types of events events that occur when working with charts;
Chart timeframes standard built-in periods;
Properties of chart identifiers that are used as parameters of chart
functions;
Positioning constants - value of a parameter of the ChartNavigate()
function;
Displaying charts - setting the chart appearance.
 
What's new in MQL5
The new generation platform has two times more timeframes (21 vs
9). It also features new graphical objects and analytical tools. Object
anchors can be placed in any position between the chart bars up to a
minute. Moreover, when switching between timeframes, the accurate
positioning of the control points of the object is preserved.
You can set any chart properties directly from an MQL5 program. The
number of properties has been increased. CHART_SHOW and
CHART_IS_DOCKED are among the most notable ones. They allow
moving any chart beyond the terminal turning it into a full-fledged
separate trading panel. Disable the display of unnecessary areas on
the chart and place OBJ_CHART objects, indicators and an EA on it to
get your own trading control center with all the necessary technical
analysis tools.
The table shows the new properties allowing you to fully manage a
symbol chart.
Property
ID Description
Type
Property
ID Description
Type
Price chart drawing. If false,
drawing any price chart
attributes is disabled and all
chart border indents are
eliminated, including time and
price scales, quick navigation
bar, Calendar event labels,
trade labels, indicator and bar
CHART_SHOW tooltips, indicator subwindows, bool
volume histograms, etc.
Disabling the drawing is a
perfect solution for creating a
custom program interface using
the graphical resources.
The graphical objects are
always drawn regardless of the
CHART_SHOW property value.
Identifying "Chart"
(OBJ_CHART) object returns
CHART_IS_OBJECT bool   r/o
true for a graphical object.
Returns false for a real chart
bool
Show chart on top of other
CHART_CONTEXT_MENU   (default
charts
is 'true')
Enabling/disabling access to
the context menu using the
right click.
When bool
CHART_CROSSHAIR_TOOL CHART_CONTEXT_MENU=false,   (default
only the chart context menu is is 'true')
disabled. The context menu of
objects on the chart remains
available.
Enabling/disabling access to
CHART_MOUSE_SCROLL the Crosshair tool using the bool
middle click.
Property
ID Description
Type
Scrolling the chart horizontally
using the left mouse button.
Vertical scrolling is also
available if the value of any
following properties is set to
bool
true: CHART_SCALEFIX,
CHART_EVENT_MOUSE_WHEEL   (default
CHART_SCALEFIX_11 or
is 'true')
CHART_SCALE_PT_PER_BAR
When
CHART_MOUSE_SCROLL=false,
chart scrolling with the mouse
wheel is unavailable
Sending messages about mouse
wheel events
CHART_EVENT_MOUSE_MOVE bool
(CHARTEVENT_MOUSE_WHEEL)
to all mql5 programs on a chart
Send notifications of mouse
move and mouse click events
CHART_EVENT_OBJECT_CREATE bool
(CHARTEVENT_MOUSE_MOVE)
to all mql5 programs on a chart
Send a notification of an event
of new object creation
CHART_EVENT_OBJECT_DELETE bool
(CHARTEVENT_OBJECT_CREATE)
to all mql5-programs on a chart
Allow managing the chart using
a keyboard ("Home", "End",
"PageUp", "+", "-", "Up arrow",
etc.). Setting
CHART_KEYBOARD_CONTROL to
CHART_KEYBOARD_CONTROL bool
false disables chart scrolling
and scaling while leaving intact
the ability to receive the keys
pressing events in
OnChartEvent().
Display textual descriptions of
CHART_SHOW_OBJECT_DESCR objects (not available for all bool
objects)
Property
ID Description
Type
Showing the "One click trading"
CHART_SHOW_ONE_CLICK bool
panel on a chart
CHART_IS_MAXIMIZED Chart window is maximized bool
CHART_IS_MINIMIZED Chart window is minimized bool
The chart window is docked. If
set to false, the chart can be
CHART_IS_DOCKED bool
dragged outside the terminal
area
The left coordinate of the
CHART_FLOAT_LEFT undocked chart window int
relative to the virtual screen
The top coordinate of the
CHART_FLOAT_TOP undocked chart window int
relative to the virtual screen
The right coordinate of the
CHART_FLOAT_RIGHT undocked chart window int
relative to the virtual screen
The bottom coordinate of the
CHART_FLOAT_BOTTOM undocked chart window int
relative to the virtual screen

 
MQL4 Reference / Constants, Enumerations and Structures / Chart Constants / Types of Chart Events

Types of Chart Events


There are 9 types of events that can be processed using the predefined function
OnChartEvent(). For custom events 65535 identifiers are provided in the range of
CHARTEVENT_CUSTOM to CHARTEVENT_CUSTOM_LAST inclusive. To generate a custom
event, the EventChartCustom() function should be used.
ENUM_CHART_EVENT
ID Description
CHARTEVENT_KEYDOWN Keystrokes
CHARTEVENT_MOUSE_MOVE Mouse move, mouse clicks (if CHART_EVENT_MOUSE_MOVE=true
is set for the chart)
CHARTEVENT_OBJECT_CREATE Graphical object created (if CHART_EVENT_OBJECT_CREATE=true
is set for the chart)
CHARTEVENT_OBJECT_CHANGE Graphical object property changed via the properties dialog
CHARTEVENT_OBJECT_DELETE Graphical object deleted (if CHART_EVENT_OBJECT_DELETE=true
is set for the chart)
CHARTEVENT_CLICK Clicking on a chart
CHARTEVENT_OBJECT_CLICK Clicking on a graphical object
CHARTEVENT_OBJECT_DRAG Drag and drop of a graphical object
CHARTEVENT_OBJECT_ENDEDIT End of text editing in the graphical object Edit
CHARTEVENT_CHART_CHANGE Change of the chart size or modification of chart properties
through the Properties dialog
CHARTEVENT_CUSTOM Initial number of an event from a range of custom events
CHARTEVENT_CUSTOM_LAST The final number of an event from a range of custom events

For each type of event, the input parameters of the OnChartEvent() function have
definite values that are required for the processing of this event. The events and values
passed through this parameters are listed in the below table.
Event Value of the id parameter Value of the lparam Value
parameter dpara
Event of a keystroke CHARTEVENT_KEYDOWN code of a pressed Repea
key numb
the
repea
of the
down
Mouse events (if CHARTEVENT_MOUSE_MOVE the X coordinate the Y
CHART_EVENT_MOUSE_MOVE=true is
set for the chart)
Event Value of the id parameter Value of the lparam Value
parameter dpara
event of graphical object creation CHARTEVENT_OBJECT_CREATE
(if
CHART_EVENT_OBJECT_CREATE=true
is set for the chart)
Event of change of an object CHARTEVENT_OBJECT_CHANGE
property via the properties dialog

Event of graphical object deletion CHARTEVENT_OBJECT_DELETE


(if
CHART_EVENT_OBJECT_DELETE=true
is set for the chart)
Event of a mouse click on the chart CHARTEVENT_CLICK the X coordinate the Y
Event of a mouse click in a graphical CHARTEVENT_OBJECT_CLICK the X coordinate the Y
object belonging to the chart

Event of a graphical object dragging CHARTEVENT_OBJECT_DRAG


using the mouse
Event of the finished text editing in CHARTEVENT_OBJECT_ENDEDIT
the entry box of the LabelEdit
graphical object

Event of change of the chart size or CHARTEVENT_CHART_CHANGE


modification of chart properties
through the Properties dialog
ID of the user event under the N CHARTEVENT_CUSTOM+N Value set by the Value
number EventChartCustom() Event
function functi

Example:
#define KEY_NUMPAD_5 12 #define KEY_LEFT 37
#define KEY_UP 38
#define KEY_RIGHT 39
#define KEY_DOWN 40
#define KEY_NUMLOCK_DOWN 98
#define KEY_NUMLOCK_LEFT 100
#define KEY_NUMLOCK_5 101
#define KEY_NUMLOCK_RIGHT 102
#define KEY_NUMLOCK_UP 104
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
Print("The Expert Advisor with name ",MQLInfoString(MQL_PROGRAM_NAME)," is running
//--- enable object create events
ChartSetInteger(ChartID(),CHART_EVENT_OBJECT_CREATE,true);
//--- enable object delete events
ChartSetInteger(ChartID(),CHART_EVENT_OBJECT_DELETE,true);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, // Event identifier
const long& lparam, // Event parameter of long type
const double& dparam, // Event parameter of double type
const string& sparam) // Event parameter of string type
{
//--- the left mouse button has been pressed on the chart
if(id==CHARTEVENT_CLICK)
{
Print("The coordinates of the mouse click on the chart are: x = ",lparam," y =
}
//--- the mouse has been clicked on the graphic object
if(id==CHARTEVENT_OBJECT_CLICK)
{
Print("The mouse has been clicked on the object with name '"+sparam+"'");
}
//--- the key has been pressed
if(id==CHARTEVENT_KEYDOWN)
{
switch(int(lparam))
{
case KEY_NUMLOCK_LEFT: Print("The KEY_NUMLOCK_LEFT has been pressed"); br
case KEY_LEFT: Print("The KEY_LEFT has been pressed"); br
case KEY_NUMLOCK_UP: Print("The KEY_NUMLOCK_UP has been pressed"); br
case KEY_UP: Print("The KEY_UP has been pressed"); br
case KEY_NUMLOCK_RIGHT: Print("The KEY_NUMLOCK_RIGHT has been pressed"); br
case KEY_RIGHT: Print("The KEY_RIGHT has been pressed"); br
case KEY_NUMLOCK_DOWN: Print("The KEY_NUMLOCK_DOWN has been pressed"); br
case KEY_DOWN: Print("The KEY_DOWN has been pressed"); br
case KEY_NUMPAD_5: Print("The KEY_NUMPAD_5 has been pressed"); br
case KEY_NUMLOCK_5: Print("The KEY_NUMLOCK_5 has been pressed"); br
default: Print("Some not listed key has been pressed");
}
ChartRedraw();
}
//--- the object has been deleted
if(id==CHARTEVENT_OBJECT_DELETE)
{
Print("The object with name ",sparam," has been deleted");
}
//--- the object has been created
if(id==CHARTEVENT_OBJECT_CREATE)
{
Print("The object with name ",sparam," has been created");
}
//--- the object has been moved or its anchor point coordinates has been changed
if(id==CHARTEVENT_OBJECT_DRAG)
{
Print("The anchor point coordinates of the object with name ",sparam," has been
}
//--- the text in the Edit of object has been changed
if(id==CHARTEVENT_OBJECT_ENDEDIT)
{
Print("The text in the Edit field of the object with name ",sparam," has been c
}
}

For CHARTEVENT_MOUSE_MOVE event the sparam string parameter contains information


about state of the keyboard and mouse buttons:
Bit Description
1 State of the left mouse button
2 State of the right mouse button
3 State of the SHIFT button
4 State of the CTRL button
5 State of the middle mouse button
6 State of the first extra mouse button
7 State of the second extra mouse button

Example:
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- enable CHART_EVENT_MOUSE_MOVE messages
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);
}
//+------------------------------------------------------------------+
//| MouseState |
//+------------------------------------------------------------------+
string MouseState(uint state)
{
string res;
res+="\nML: " +(((state& 1)== 1)?"DN":"UP"); // mouse left
res+="\nMR: " +(((state& 2)== 2)?"DN":"UP"); // mouse right
res+="\nMM: " +(((state&16)==16)?"DN":"UP"); // mouse middle
res+="\nMX: " +(((state&32)==32)?"DN":"UP"); // mouse first X key
res+="\nMY: " +(((state&64)==64)?"DN":"UP"); // mouse second X key
res+="\nSHIFT: "+(((state& 4)== 4)?"DN":"UP"); // shift key
res+="\nCTRL: " +(((state& 8)== 8)?"DN":"UP"); // control key
return(res);
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &
{
if(id==CHARTEVENT_MOUSE_MOVE)
Comment("POINT: ",(int)lparam,",",(int)dparam,"\n",MouseState((uint)sparam));
}

See also
Event Handling Functions, Working with events
MQL4 Reference / Constants, Enumerations and Structures / Chart
Constants / Chart Timeframes

Chart Timeframes
All predefined timeframes of charts have unique
identifiers. The PERIOD_CURRENT identifier means the
current period of a chart, at which a mql4-program is
running.
ENUM_TIMEFRAMES
ID Value Description
PERIOD_CURRENT 0 Current timeframe
PERIOD_M1 1 1 minute
PERIOD_M5 5 5 minutes
PERIOD_M15 15 15 minutes
PERIOD_M30 30 30 minutes
PERIOD_H1 60 1 hour
PERIOD_H4 240 4 hours
PERIOD_D1 1440 1 day
PERIOD_W1 10080 1 week
PERIOD_MN1 43200 1 month

The ENUM_TIMEFRAMES enumeration contains the values


of standard timeframes, online charts of financial
instruments can be plotted only on these time intervals.
Below are non-standard timeframes, in MQL4 they are
constants.
Constant Value Description
Constant Value Description
PERIOD_M2 2 2 minutes
PERIOD_M3 3 3 minutes
PERIOD_M4 4 4 minutes
PERIOD_M6 6 6 minutes
PERIOD_M10 10 10 minutes
PERIOD_M12 12 12 minutes
PERIOD_M20 20 20 minutes
PERIOD_H2 120 2 hours
PERIOD_H3 180 3 hours
PERIOD_H6 360 6 hours
PERIOD_H8 480 8 hours
PERIOD_H12 720 12 hours

These periods can be used for working with offline charts.


Note
The constants of non-standard timeframes are included
in the MQL4 language to enable translation and
compilation of MQL5 programs, where these timeframes
are standard and are included in the ENUM_TIMEFRAMES
enumeration.
See also
PeriodSeconds(), Period(), Date and Time, Visibility of
objects
MQL4 Reference / Constants, Enumerations and Structures / Chart Constants / Chart Properties

Chart Properties
Identifiers of ENUM_CHART_PROPERTY enumerations are used as parameters of
functions for working with charts. The abbreviation of r/o in the "Property Type"
column means that this property is read-only and cannot be changed. The w/o
abbreviation in the "Property Type" column means that this property is write-only and
it cannot be received. When accessing certain properties, it's necessary to specify an
additional parameter-modifier (modifier), which serves to indicate the number of
chart subwindows. 0 means the main window.
For functions ChartSetInteger() and ChartGetInteger()
ENUM_CHART_PROPERTY_INTEGER
ID Description Property Type
CHART_BRING_TO_TOP Show chart on top of other bool   w/o
charts
CHART_MOUSE_SCROLL Scrolling the chart horizontally bool
using the left mouse button.
Vertical scrolling is also
available if the value of any
following properties is set to
true: CHART_SCALEFIX,
CHART_SCALEFIX_11 or
CHART_SCALE_PT_PER_BAR
CHART_EVENT_MOUSE_MOVE Send notifications of mouse bool
move and mouse click events
(CHARTEVENT_MOUSE_MOVE)
to all mql4 programs on a chart
CHART_EVENT_OBJECT_CREATE Send a notification of an event bool
of new object creation
(CHARTEVENT_OBJECT_CREATE)
to all mql4-programs on a chart
CHART_EVENT_OBJECT_DELETE Send a notification of an event bool
of object deletion
(CHARTEVENT_OBJECT_DELETE)
to all mql4-programs on a chart
CHART_MODE Chart type (candlesticks, bars enum     ENUM_CHART_MODE
or line)
CHART_FOREGROUND Price chart in the foreground bool
CHART_SHIFT Mode of price chart indent from bool
the right border
CHART_AUTOSCROLL Mode of automatic moving to bool
the right border of the chart
ID Description Property Type
CHART_QUICK_NAVIGATION Allow the chart to intercept bool
Space and Enter key strokes to
activate the quick navigation
bar. The quick navigation bar
automatically appears at the
bottom of the chart after
double-clicking the mouse or
pressing Space/Enter. It allows
you to quickly change a symbol,
timeframe and first visible bar
date.
CHART_SCALE Scale int        from 0 to 5
CHART_SCALEFIX Fixed scale mode bool
CHART_SCALEFIX_11 Scale 1:1 mode bool
CHART_SCALE_PT_PER_BAR Scale to be specified in points bool
per bar
CHART_SHOW_OHLC Show OHLC values in the upper bool
left corner
CHART_SHOW_BID_LINE Display Bid values as a bool
horizontal line in a chart
CHART_SHOW_ASK_LINE Display Ask values as a bool
horizontal line in a chart
CHART_SHOW_LAST_LINE Display Last values as a bool
horizontal line in a chart
CHART_SHOW_PERIOD_SEP Display vertical separators bool
between adjacent periods
CHART_SHOW_GRID Display grid in the chart bool
CHART_SHOW_VOLUMES Display volume in the chart enum    
ENUM_CHART_VOLUME_MODE
CHART_SHOW_OBJECT_DESCR Display textual descriptions of bool
objects (not available for all
objects)
CHART_VISIBLE_BARS The number of bars on the int r/o
chart that can be displayed
CHART_WINDOWS_TOTAL The total number of chart int r/o
windows, including indicator
subwindows
CHART_WINDOW_IS_VISIBLE Visibility of subwindows bool r/o   modifier -
subwindow number
CHART_WINDOW_HANDLE Chart window handle (HWND) int r/o
ID Description Property Type
CHART_WINDOW_YDISTANCE The distance between the int r/o     modifier -
upper frame of the indicator subwindow number
subwindow and the upper
frame of the main chart
window, along the vertical Y
axis, in pixels. In case of a
mouse event, the cursor
coordinates are passed in terms
of the coordinates of the main
chart window, while the
coordinates of graphical
objects in an indicator
subwindow are set relative to
the upper left corner of the
subwindow.
The value is required for
converting the absolute
coordinates of the main chart
to the local coordinates of a
subwindow for correct work
with the graphical objects,
whose coordinates are set
relative to   the upper left
corner of the subwindow
frame.
CHART_FIRST_VISIBLE_BAR Number of the first visible bar int r/o
in the chart. Indexing of bars is
the same as for timeseries.
CHART_WIDTH_IN_BARS Chart width in bars int r/o
CHART_WIDTH_IN_PIXELS Chart width in pixels int r/o
CHART_HEIGHT_IN_PIXELS Chart height in pixels int      modifier - subwindow
number
CHART_COLOR_BACKGROUND Chart background color color
CHART_COLOR_FOREGROUND Color of axes, scales and OHLC color
line
CHART_COLOR_GRID Grid color color
CHART_COLOR_VOLUME Color of volumes and order color
opening levels
CHART_COLOR_CHART_UP Color for the up bar, shadows color
and body borders of bull
candlesticks
CHART_COLOR_CHART_DOWN Color for the down bar, color
shadows and body borders of
bear candlesticks
ID Description Property Type
CHART_COLOR_CHART_LINE Line chart color and color of color
"Doji" Japanese candlesticks
CHART_COLOR_CANDLE_BULL Body color of a bull candlestick color
CHART_COLOR_CANDLE_BEAR Body color of a bear color
candlestick
CHART_COLOR_BID Bid price level color color
CHART_COLOR_ASK Ask price level color color
CHART_COLOR_LAST Line color of the last executed color
deal price (Last)
CHART_COLOR_STOP_LEVEL Color of stop order levels (Stop color
Loss and Take Profit)
CHART_SHOW_TRADE_LEVELS Displaying trade levels in the bool
chart (levels of open orders,
Stop Loss, Take Profit and
pending orders)
CHART_DRAG_TRADE_LEVELS Permission to drag trading bool
levels on a chart with a mouse.
The drag mode is enabled by
default (true value)
CHART_SHOW_DATE_SCALE Showing the time scale on a bool
chart
CHART_SHOW_PRICE_SCALE Showing the price scale on a bool
chart
CHART_IS_OFFLINE Flag, indicating that chart bool   r/o
opened in offline mode

For functions ChartSetDouble() and ChartGetDouble()


ENUM_CHART_PROPERTY_DOUBLE
ID Description Property Type
CHART_SHIFT_SIZE The size of the zero bar indent from double   (from 10 to 50
the right border in percents percents)
CHART_FIXED_POSITION Chart fixed position from the left double
border in percent value. Chart fixed
position is marked by a small gray
triangle on the horizontal time axis. It
is displayed only if the automatic
chart scrolling to the right on tick
incoming is disabled (see
CHART_AUTOSCROLL property). The
bar on a fixed position remains in the
same place when zooming in and out.
CHART_FIXED_MAX Fixed  chart maximum double
ID Description Property Type
CHART_FIXED_MIN Fixed  chart minimum double
CHART_POINTS_PER_BAR Scale in points per bar double
CHART_PRICE_MIN Chart minimum double r/o   modifier -
subwindow number
CHART_PRICE_MAX Chart maximum double r/o   modifier -
subwindow number

For functions ChartSetString() and ChartGetString()


ENUM_CHART_PROPERTY_STRING
ID Description Property Type
CHART_COMMENT Text of a comment in a chart string

Example:
int chartMode=ChartGetInteger(0,CHART_MODE); switch(chartMode)
{
case(CHART_BARS): Print("CHART_BARS"); break;
case(CHART_CANDLES): Print("CHART_CANDLES");break;
default:Print("CHART_LINE");
}
bool shifted=ChartGetInteger(0,CHART_SHIFT);
if(shifted) Print("CHART_SHIFT = true");
else Print("CHART_SHIFT = false");
bool autoscroll=ChartGetInteger(0,CHART_AUTOSCROLL);
if(autoscroll) Print("CHART_AUTOSCROLL = true");
else Print("CHART_AUTOSCROLL = false");
int chartHandle=ChartGetInteger(0,CHART_WINDOW_HANDLE);
Print("CHART_WINDOW_HANDLE = ",chartHandle);
int windows=ChartGetInteger(0,CHART_WINDOWS_TOTAL);
Print("CHART_WINDOWS_TOTAL = ",windows);
if(windows>1)
{
for(int i=0;i<windows;i++)
{
int height=ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,i);
double priceMin=ChartGetDouble(0,CHART_PRICE_MIN,i);
double priceMax=ChartGetDouble(0,CHART_PRICE_MAX,i);
Print(i+": CHART_HEIGHT_IN_PIXELS = ",height," pixels");
Print(i+": CHART_PRICE_MIN = ",priceMin);
Print(i+": CHART_PRICE_MAX = ",priceMax);
}
}

See also
Examples of Working with the Chart
MQL4 Reference / Constants, Enumerations and Structures / Chart Constants /
Positioning Constants

Positioning Constants
Three identifiers from the ENUM_CHART_POSITION list are the
possible values of the position parameter for the ChartNavigate()
function.
ENUM_CHART_POSITION
ID Description
CHART_BEGIN Chart beginning (the oldest prices)
CHART_CURRENT_POS Current position
CHART_END Chart end (the latest prices)

Example:
long handle=ChartOpen("EURUSD",PERIOD_H12); if(handle!=0)
{
ChartSetInteger(handle,CHART_AUTOSCROLL,false);
ChartSetInteger(handle,CHART_SHIFT,true);
ChartSetInteger(handle,CHART_MODE,CHART_LINE);
ResetLastError();
bool res=ChartNavigate(handle,CHART_END,150);
if(!res) Print("Navigate failed. Error = ",GetLastError());
ChartRedraw();
}
MQL4 Reference / Constants, Enumerations and Structures / Chart Constants / Chart
Representation

Chart Representation
Price charts can be displayed in three ways:
as bars;
as candlesticks;
as a line.
The specific way of displaying the price chart is set by the function
ChartSetInteger(chart_handle,CHART_MODE, chart_mode), where
chart_mode is one of the values of the ENUM_CHART_MODE
enumeration.
ENUM_CHART_MODE
ID Description
CHART_BARS Display as a sequence of bars
CHART_CANDLES Display as Japanese candlesticks
CHART_LINE Display as a line drawn by Close prices

To specify the mode of displaying volumes in the price chart the


function ChartSetInteger(chart_handle, CHART_SHOW_VOLUMES,
volume_mode) is used, where volume_mode is one of values of the
ENUM_CHART_VOLUME_MODE enumeration.
ENUM_CHART_VOLUME_MODE
ID Description
CHART_VOLUME_HIDE Volumes are not shown
CHART_VOLUME_TICK Tick volumes

Example:
//--- Get the handle of the current chart long handle=ChartID();
if(handle>0) // If it succeeded, additionally customize
{
//--- Disable autoscroll
ChartSetInteger(handle,CHART_AUTOSCROLL,false);
//--- Set the indent of the right border of the chart
ChartSetInteger(handle,CHART_SHIFT,true);
//--- Display as candlesticks
ChartSetInteger(handle,CHART_MODE,CHART_CANDLES);
//--- Scroll by 100 bars from the beginning of history
ChartNavigate(handle,CHART_CURRENT_POS,100);
//--- Set the tick volume display mode
ChartSetInteger(handle,CHART_SHOW_VOLUMES,CHART_VOLUME_TICK);
}

See also
ChartOpen, ChartID
MQL4 Reference / Constants, Enumerations and Structures / Chart Constants / Examples of Working with the
Chart

Examples of Working with the Chart


This section contains examples of working with chart properties. One or two complete
functions are displayed for each property. These functions allow setting/receiving the
value of the property. These functions can be used "as is" in custom mql4 applications.
The screenshot below demonstrates the graphic panel illustrating how changing of the
chart property changes its appearance. Clicking Next button allows setting the new value
of the appropriate property and view the changes in the chart window.

The panel's source code is located below.

Chart Properties and Sample Functions for Working with Them


CHART_BRING_TO_TOP shows the chart on top of all others.
//+----------------------------------------------------------------------+ //| Send co
//+----------------------------------------------------------------------+
bool ChartBringToTop(const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- show the chart on top of all others
if(!ChartSetInteger(chart_ID,CHART_BRING_TO_TOP,0,true))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_MOUSE_SCROLL is a property for scrolling the chart using left mouse button.
//+--------------------------------------------------------------------------+
//| The function defines if scrolling the chart using left mouse button is |
//| enabled. |
//+--------------------------------------------------------------------------+
bool ChartMouseScrollGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_MOUSE_SCROLL,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+--------------------------------------------------------------------+
//| The function enables/disables scrolling the chart using left mouse |
//| button. |
//+--------------------------------------------------------------------+
bool ChartMouseScrollSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_MOUSE_SCROLL,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_EVENT_MOUSE_MOVE is a property of sending messages concerning move
events and mouse clicks to mql4 applications (CHARTEVENT_MOUSE_MOVE).
//+------------------------------------------------------------------+
//| Check if messages concerning move events and mouse clicks |
//| are sent to all mql4 applications on the chart. |
//+------------------------------------------------------------------+
bool ChartEventMouseMoveGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_EVENT_MOUSE_MOVE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+------------------------------------------------------------------------------+
//| The function enables/disables the mode of sending messages concerning move |
//| events and mouse clicks to mql4 applications on the |
//| chart. |
//+------------------------------------------------------------------------------+
bool ChartEventMouseMoveSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_EVENT_MOUSE_MOVE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_EVENT_OBJECT_CREATE is a property of sending messages concerning the
event of a graphic object creation to mql4 applications
(CHARTEVENT_OBJECT_CREATE).
//+---------------------------------------------------------------------+
//| Check if messages concerning the event of a graphic object creation |
//| are sent to all mql4 applications on the chart. |
//+---------------------------------------------------------------------+
bool ChartEventObjectCreateGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_EVENT_OBJECT_CREATE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+--------------------------------------------------------------------------+
//| The function enables/disables the mode of sending messages concerning |
//| the event of a graphic object creation to all mql4 applications on the |
//| chart. |
//+--------------------------------------------------------------------------+
bool ChartEventObjectCreateSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_EVENT_OBJECT_CREATE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_EVENT_OBJECT_DELETE is a property of sending messages concerning the
event of a graphic object deletion to mql4 applications
(CHARTEVENT_OBJECT_DELETE).
//+---------------------------------------------------------------------+
//| Check if messages concerning the event of a graphic object deletion |
//| are sent to all mql4 applications on the chart. |
//+---------------------------------------------------------------------+
bool ChartEventObjectDeleteGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_EVENT_OBJECT_DELETE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+--------------------------------------------------------------------------+
//| The function enables/disables the mode of sending messages concerning |
//| the event of a graphic object deletion to all mql4 applications on the |
//| chart. |
//+--------------------------------------------------------------------------+
bool ChartEventObjectDeleteSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_EVENT_OBJECT_DELETE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_MODE type of the chart (candlesticks, bars or line).
//+------------------------------------------------------------------+
//| Get chart display type (candlesticks, bars or |
//| line). |
//+------------------------------------------------------------------+
ENUM_CHART_MODE ChartModeGet(const long chart_ID=0)
{
//--- prepare the variable to get the property value
long result=WRONG_VALUE;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_MODE,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((ENUM_CHART_MODE)result);
}
//+------------------------------------------------------------------+
//| Set chart display type (candlesticks, bars or |
//| line). |
//+------------------------------------------------------------------+
bool ChartModeSet(const long value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_MODE,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_FOREGROUND is a property of displaying a price chart in the foreground.
//+------------------------------------------------------------------+
//| The function defines if a price chart is displayed in the |
//| foreground. |
//+------------------------------------------------------------------+
bool ChartForegroundGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_FOREGROUND,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+---------------------------------------------------------------------------+
//| The function enables/disables the mode of displaying a price chart on the |
//| foreground. |
//+---------------------------------------------------------------------------+
bool ChartForegroundSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_FOREGROUND,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHIFT mode of shift of the price chart from the right border.
//+----------------------------------------------------------------------------------
//| The function defines if the mode of shift of the price chart from the right borde
//| is enabled.
//+----------------------------------------------------------------------------------
bool ChartShiftGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHIFT,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+--------------------------------------------------------------------------+
//| The function enables/disables the mode of displaying a price chart with |
//| a shift from the right border. |
//+--------------------------------------------------------------------------+
bool ChartShiftSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHIFT,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_AUTOSCROLL the mode of automatic shift to the right border of the chart.
//+---------------------------------------------------------------------+
//| The function defines if the mode of the autoscroll |
//| of the chart to the right in case of new ticks' arrival is enabled. |
//+---------------------------------------------------------------------+
bool ChartAutoscrollGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_AUTOSCROLL,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| The function enables/disables the mode of the autoscroll |
//| of the chart to the right in case of new ticks' arrival. |
//+------------------------------------------------------------------+
bool ChartAutoscrollSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_AUTOSCROLL,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SCALE chart scale property.
//+------------------------------------------------------------------+
//| Get chart scale (from 0 to 5). |
//+------------------------------------------------------------------+
int ChartScaleGet(const long chart_ID=0)
{
//--- prepare the variable to get the property value
long result=-1;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SCALE,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((int)result);
}
//+------------------------------------------------------------------+
//| Set chart scale (from 0 to 5). |
//+------------------------------------------------------------------+
bool ChartScaleSet(const long value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SCALE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SCALEFIX the mode of fixed chart scale.
//+------------------------------------------------------------------+
//| The function defines if the fixed scale mode is enabled. |
//+------------------------------------------------------------------+
bool ChartScaleFixGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SCALEFIX,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| The function enables/disables the fixed scale mode. |
//+------------------------------------------------------------------+
bool ChartScaleFixSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SCALEFIX,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SCALEFIX_11 1:1 chart scale mode.
//+------------------------------------------------------------------+
//| The function defines if "1:1" scale is enabled. |
//+------------------------------------------------------------------+
bool ChartScaleFix11Get(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SCALEFIX_11,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| The function enables/disables "1:1" scale mode |
//+------------------------------------------------------------------+
bool ChartScaleFix11Set(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SCALEFIX_11,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SCALE_PT_PER_BAR the mode of specifying the chart scale in points per bar.
//+------------------------------------------------------------------------------+
//| The function defines if the mode of specifying the chart scale in points per |
//| bar is enabled. |
//+------------------------------------------------------------------------------+
bool ChartScalePerBarGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SCALE_PT_PER_BAR,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+----------------------------------------------------------------------------------
//| The function enables/disables the mode of specifying the chart scale in points pe
//| bar.
//+----------------------------------------------------------------------------------
bool ChartScalePerBarSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SCALE_PT_PER_BAR,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_OHLC the property of displaying OHLC values in the upper left corner.
//+------------------------------------------------------------------+
//| The function defines if the mode of displaying OHLC values |
//| in the upper left corner is enabled. |
//+------------------------------------------------------------------+
bool ChartShowOHLCGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_OHLC,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+--------------------------------------------------------------------------+
//| The function enables/disables the mode of displaying OHLC values in the |
//| upper left corner of the chart. |
//+--------------------------------------------------------------------------+
bool ChartShowOHLCSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_OHLC,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_BID_LINE the property of displaying Bid value as a horizontal line on
the chart.
//+-----------------------------------------------------------------------------+
//| The function defines if the mode of displaying Bid value line on the chart |
//| is enabled. |
//+-----------------------------------------------------------------------------+
bool ChartShowBidLineGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_BID_LINE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+--------------------------------------------------------------------+
//| The function enables/disables the mode of displaying Bid line on a |
//| chart. |
//+--------------------------------------------------------------------+
bool ChartShowBidLineSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_BID_LINE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_ASK_LINE the property of displaying Ask value as a horizontal line on
a chart.
//+-----------------------------------------------------------------------+
//| The function defines if the mode of displaying Ask value line on the |
//| chart. |
//+-----------------------------------------------------------------------+
bool ChartShowAskLineGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_ASK_LINE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+-----------------------------------------------------------------------+
//| The function enables/disables the mode of displaying Ask line on the |
//| chart. |
//+-----------------------------------------------------------------------+
bool ChartShowAskLineSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_ASK_LINE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_LAST_LINE the property of displaying Last value as a horizontal line
on a chart.
//+---------------------------------------------------------------------------------+
//| The function defines if the mode of displaying the line for the last performed |
//| deal's price is enabled. |
//+---------------------------------------------------------------------------------+
bool ChartShowLastLineGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_LAST_LINE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+----------------------------------------------------------------------------------
//| The function enables/disables the mode of displaying the line for the last perfor
//| deal's price.
//+----------------------------------------------------------------------------------
bool ChartShowLastLineSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_LAST_LINE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_PERIOD_SEP the property of displaying vertical separators between
adjacent periods.
//+------------------------------------------------------------------+
//| The function defines if the mode of displaying vertical |
//| separators between adjacent periods is enabled. |
//+------------------------------------------------------------------+
bool ChartShowPeriodSeparatorGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_PERIOD_SEP,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| The function enables/disables the mode of displaying vertical |
//| separators between adjacent periods. |
//+------------------------------------------------------------------+
bool ChartShowPeriodSepapatorSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_PERIOD_SEP,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_GRID the property of displaying the chart grid.
//+------------------------------------------------------------------+
//| The function defines if the chart grid is displayed. |
//+------------------------------------------------------------------+
bool ChartShowGridGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_GRID,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| The function enables/disables the chart grid. |
//+------------------------------------------------------------------+
bool ChartShowGridSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set the property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_GRID,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_VOLUMES the property of displaying the volumes on a chart.
//+------------------------------------------------------------------------+
//| The function defines if the volumes are displayed on a chart (are not |
//| displayed, tick ones are displayed, actual ones are displayed). |
//+------------------------------------------------------------------------+
ENUM_CHART_VOLUME_MODE ChartShowVolumesGet(const long chart_ID=0)
{
//--- prepare the variable to get the property value
long result=WRONG_VALUE;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_VOLUMES,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((ENUM_CHART_VOLUME_MODE)result);
}
//+------------------------------------------------------------------+
//| The function sets the mode of displaying the volumes on a chart. |
//+------------------------------------------------------------------+
bool ChartShowVolumesSet(const long value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_VOLUMES,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_OBJECT_DESCR the property of graphical object pop-up descriptions.
//+-------------------------------------------------------------------+
//| The function defines if pop-up descriptions |
//| of graphical objects are displayed when hovering mouse over them. |
//+-------------------------------------------------------------------+
bool ChartShowObjectDescriptionGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_OBJECT_DESCR,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+--------------------------------------------------------------------------+
//| The function enables/disables the mode of displaying pop-up descriptions |
//| of graphical objects when hovering mouse over them. |
//+--------------------------------------------------------------------------+
bool ChartShowObjectDescriptionSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_OBJECT_DESCR,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_VISIBLE_BARS defines the number of bars on a chart that are available for
display.
//+-----------------------------------------------------------------------+
//| The function receives the number of bars that are displayed (visible) |
//| in the chart window. |
//+-----------------------------------------------------------------------+
int ChartVisibleBars(const long chart_ID=0)
{
//--- prepare the variable to get the property value
long result=-1;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_VISIBLE_BARS,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((int)result);
}

 
CHART_WINDOWS_TOTAL defines the total number of chart windows including
indicator subwindows.
//+--------------------------------------------------------------------------+
//| The function gets the total number of chart windows including indicator |
//| subwindows. |
//+--------------------------------------------------------------------------+
int ChartWindowsTotal(const long chart_ID=0)
{
//--- prepare the variable to get the property value
long result=-1;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_WINDOWS_TOTAL,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((int)result);
}

 
CHART_WINDOW_IS_VISIBLE defines the subwindow's visibility.
//+------------------------------------------------------------------+
//| The function defines if the current chart window or subwindow |
//| is visible. |
//+------------------------------------------------------------------+
bool ChartWindowsIsVisible(bool &result,const long chart_ID=0,const int sub_window=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_WINDOW_IS_VISIBLE,sub_window,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}

 
CHART_WINDOW_HANDLE returns the chart handle.
//+------------------------------------------------------------------+
//| The function gets the chart handle |
//+------------------------------------------------------------------+
int ChartWindowsHandle(const long chart_ID=0)
{
//--- prepare the variable to get the property value
long result=-1;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_WINDOW_HANDLE,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((int)result);
}

 
CHART_WINDOW_YDISTANCE defines the distance in pixels between the upper frame
of the indicator subwindow and the upper frame of the chart's main window.
//+------------------------------------------------------------------+
//| The function gets the distance in pixels between the upper frame |
//| of the subwindow and the upper frame of the chart's main window. |
//+------------------------------------------------------------------+
int ChartWindowsYDistance(const long chart_ID=0,const int sub_window=0)
{
//--- prepare the variable to get the property value
long result=-1;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_WINDOW_YDISTANCE,sub_window,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((int)result);
}

 
CHART_FIRST_VISIBLE_BAR returns the number of the first visible bar on the chart
(bar indexing corresponds to the time series).
//+----------------------------------------------------------------------------+
//| The function receives the number of the first visible bar on the chart. |
//| Indexing is performed like in time series, last bars have smaller indices. |
//+----------------------------------------------------------------------------+
int ChartFirstVisibleBar(const long chart_ID=0)
{
//--- prepare the variable to get the property value
long result=-1;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_WINDOW_YDISTANCE,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((int)result);
}

 
CHART_WIDTH_IN_BARS returns the chart width in bars.
//+------------------------------------------------------------------+
//| The function receives the chart width in bars. |
//+------------------------------------------------------------------+
int ChartWidthInBars(const long chart_ID=0)
{
//--- prepare the variable to get the property value
long result=-1;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_WIDTH_IN_BARS,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((int)result);
}

 
CHART_WIDTH_IN_PIXELS returns the chart width in pixels.
//+------------------------------------------------------------------+
//| The function receives the chart width in pixels. |
//+------------------------------------------------------------------+
int ChartWidthInPixels(const long chart_ID=0)
{
//--- prepare the variable to get the property value
long result=-1;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_WIDTH_IN_PIXELS,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((int)result);
}

 
CHART_HEIGHT_IN_PIXELS chart height property in pixels.
//+------------------------------------------------------------------+
//| The function receives the chart height value in pixels. |
//+------------------------------------------------------------------+
int ChartHeightInPixelsGet(const long chart_ID=0,const int sub_window=0)
{
//--- prepare the variable to get the property value
long result=-1;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_HEIGHT_IN_PIXELS,sub_window,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((int)result);
}
//+------------------------------------------------------------------+
//| The function sets the chart height value in pixels. |
//+------------------------------------------------------------------+
bool ChartHeightInPixelsSet(const int value,const long chart_ID=0,const int sub_windo
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_HEIGHT_IN_PIXELS,sub_window,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_BACKGROUND - chart background color.
//+------------------------------------------------------------------+
//| The function receives chart background color. |
//+------------------------------------------------------------------+
color ChartBackColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive chart background color
if(!ChartGetInteger(chart_ID,CHART_COLOR_BACKGROUND,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets chart background color. |
//+------------------------------------------------------------------+
bool ChartBackColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set the chart background color
if(!ChartSetInteger(chart_ID,CHART_COLOR_BACKGROUND,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_FOREGROUND color of axes, scale and OHLC line.
//+------------------------------------------------------------------+
//| The function receives the color of axes, scale and OHLC line. |
//+------------------------------------------------------------------+
color ChartForeColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive the color of axes, scale and OHLC line
if(!ChartGetInteger(chart_ID,CHART_COLOR_FOREGROUND,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets the color of axes, scale and OHLC line. |
//+------------------------------------------------------------------+
bool ChartForeColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set the color of axes, scale and OHLC line
if(!ChartSetInteger(chart_ID,CHART_COLOR_FOREGROUND,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_GRID chart grid color.
//+------------------------------------------------------------------+
//| The function receives chart grid color. |
//+------------------------------------------------------------------+
color ChartGridColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive chart grid color
if(!ChartGetInteger(chart_ID,CHART_COLOR_GRID,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets chart grid color. |
//+------------------------------------------------------------------+
bool ChartGridColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set chart grid color
if(!ChartSetInteger(chart_ID,CHART_COLOR_GRID,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_VOLUME - color of volumes and order opening levels.
//+------------------------------------------------------------------+
//| The function receives color of volumes and market entry |
//| levels. |
//+------------------------------------------------------------------+
color ChartVolumeColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive color of volumes and market entry levels
if(!ChartGetInteger(chart_ID,CHART_COLOR_VOLUME,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets the color of volumes and market entry |
//| levels. |
//+------------------------------------------------------------------+
bool ChartVolumeColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set color of volumes and market entry levels
if(!ChartSetInteger(chart_ID,CHART_COLOR_VOLUME,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_CHART_UP color of up bar, its shadow and border of a bullish
candlestick's body.
//+------------------------------------------------------------------+
//| The function receives color of up bar, its shadow and |
//| border of a bullish candlestick's body. |
//+------------------------------------------------------------------+
color ChartUpColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive the color of up bar, its shadow and border of bullish candlestick's bod
if(!ChartGetInteger(chart_ID,CHART_COLOR_CHART_UP,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets color of up bar, its shadow and |
//| border of a bullish candlestick's body. |
//+------------------------------------------------------------------+
bool ChartUpColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set the color of up bar, its shadow and border of body of a bullish candlestick
if(!ChartSetInteger(chart_ID,CHART_COLOR_CHART_UP,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_CHART_DOWN color of down bar, its shadow and border of bearish
candlestick's body.
//+------------------------------------------------------------------+
//| The function receives color of up bar, its shadow and |
//| border of a bearish candlestick's body. |
//+------------------------------------------------------------------+
color ChartDownColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive the color of down bar, its shadow and border of bearish candlestick's b
if(!ChartGetInteger(chart_ID,CHART_COLOR_CHART_DOWN,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets color of down bar, its shadow and |
//| border of a bearish candlestick's body. |
//+------------------------------------------------------------------+
bool ChartDownColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set the color of down bar, its shadow and border of bearish candlestick's body
if(!ChartSetInteger(chart_ID,CHART_COLOR_CHART_DOWN,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_CHART_LINE color of the chart line and Doji candlesticks.
//+------------------------------------------------------------------------+
//| The function receives color of the chart line and Doji candlesticks. |
//+------------------------------------------------------------------------+
color ChartLineColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive color of the chart line and Doji candlesticks
if(!ChartGetInteger(chart_ID,CHART_COLOR_CHART_LINE,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets the color of the chart line and Doji |
//| candlesticks. |
//+------------------------------------------------------------------+
bool ChartLineColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set color of the chart line and Doji candlesticks
if(!ChartSetInteger(chart_ID,CHART_COLOR_CHART_LINE,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_CANDLE_BULL color of bullish candlestick's body.
//+------------------------------------------------------------------+
//| The function receives color of bullish candlestick's body. |
//+------------------------------------------------------------------+
color ChartBullColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive the color of bullish candlestick's body
if(!ChartGetInteger(chart_ID,CHART_COLOR_CANDLE_BULL,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets color of bullish candlestick's body. |
//+------------------------------------------------------------------+
bool ChartBullColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set the color of bullish candlestick's body
if(!ChartSetInteger(chart_ID,CHART_COLOR_CANDLE_BULL,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_CANDLE_BEAR color of bearish candlestick's body.
//+------------------------------------------------------------------+
//| The function receives color of bearish candlestick's body. |
//+------------------------------------------------------------------+
color ChartBearColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive the color of bearish candlestick's body
if(!ChartGetInteger(chart_ID,CHART_COLOR_CANDLE_BEAR,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets color of bearish candlestick's body. |
//+------------------------------------------------------------------+
bool ChartBearColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set the color of bearish candlestick's body
if(!ChartSetInteger(chart_ID,CHART_COLOR_CANDLE_BEAR,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_BID Bid price line color.
//+------------------------------------------------------------------+
//| The function receives the color of Bid line. |
//+------------------------------------------------------------------+
color ChartBidColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive the color of Bid price line
if(!ChartGetInteger(chart_ID,CHART_COLOR_BID,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets the color of Bid line. |
//+------------------------------------------------------------------+
bool ChartBidColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set the color of Bid price line
if(!ChartSetInteger(chart_ID,CHART_COLOR_BID,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_ASK Ask price line color.
//+------------------------------------------------------------------+
//| The function receives the color of Ask line. |
//+------------------------------------------------------------------+
color ChartAskColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive the color of Ask price line
if(!ChartGetInteger(chart_ID,CHART_COLOR_ASK,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets the color of Ask line. |
//+------------------------------------------------------------------+
bool ChartAskColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set the color of Ask price line
if(!ChartSetInteger(chart_ID,CHART_COLOR_ASK,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_LAST color of the last performed deal's price line (Last).
//+----------------------------------------------------------------------+
//| The function receives color of the last performed deal's price line. |
//+----------------------------------------------------------------------+
color ChartLastColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive color of the last performed deal's price line (Last)
if(!ChartGetInteger(chart_ID,CHART_COLOR_LAST,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets color of the last performed deal's price |
//| line. |
//+------------------------------------------------------------------+
bool ChartLastColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set color of the last performed deal's price line (Last)
if(!ChartSetInteger(chart_ID,CHART_COLOR_LAST,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_COLOR_STOP_LEVEL stop order level color (Stop Loss and Take Profit).
//+--------------------------------------------------------------------+
//| The function receives colors of Stop Loss and Take Profit levels. |
//+--------------------------------------------------------------------+
color ChartStopLevelColorGet(const long chart_ID=0)
{
//--- prepare the variable to receive the color
long result=clrNONE;
//--- reset the error value
ResetLastError();
//--- receive the color of stop order levels (Stop Loss and Take Profit)
if(!ChartGetInteger(chart_ID,CHART_COLOR_STOP_LEVEL,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return((color)result);
}
//+------------------------------------------------------------------+
//| The function sets Stop Loss and Take Profit level colors. |
//+------------------------------------------------------------------+
bool ChartStopLevelColorSet(const color clr,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set the color of stop order levels (Stop Loss and Take Profit)
if(!ChartSetInteger(chart_ID,CHART_COLOR_STOP_LEVEL,clr))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_TRADE_LEVELS property of displaying trade levels on the chart (levels
of open orders, Stop Loss, Take Profit and pending orders).
//+---------------------------------------------------------------------+
//| The function defines if trading levels are displayed on the chart. |
//+---------------------------------------------------------------------+
bool ChartShowTradeLevelsGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_TRADE_LEVELS,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| The function enables/disables trading levels display mode. |
//+------------------------------------------------------------------+
bool ChartShowTradeLevelsSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_TRADE_LEVELS,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_DRAG_TRADE_LEVELS property of enabling the ability to drag trading levels
on a chart using mouse.
//+---------------------------------------------------------------------------+
//| The function defines if dragging trading levels on a chart using mouse |
//| is allowed. |
//+---------------------------------------------------------------------------+
bool ChartDragTradeLevelsGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_DRAG_TRADE_LEVELS,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| The function enables/disables the mode of dragging trade levels |
//| on the chart using mouse. |
//+------------------------------------------------------------------+
bool ChartDragTradeLevelsSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_DRAG_TRADE_LEVELS,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_DATE_SCALE property of displaying the time scale on a chart.
//+--------------------------------------------------------------------+
//| The function defines if the time scale is displayed on the chart. |
//+--------------------------------------------------------------------+
bool ChartShowDateScaleGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_DATE_SCALE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+-----------------------------------------------------------------------------+
//| The function enables/disables the mode of displaying the time scale on a |
//| chart. |
//+-----------------------------------------------------------------------------+
bool ChartShowDateScaleSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_DATE_SCALE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHOW_PRICE_SCALE property of displaying the price scale on a chart.
//+--------------------------------------------------------------------+
//| The function defines if the price scale is displayed on the chart. |
//+--------------------------------------------------------------------+
bool ChartShowPriceScaleGet(bool &result,const long chart_ID=0)
{
//--- prepare the variable to get the property value
long value;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetInteger(chart_ID,CHART_SHOW_PRICE_SCALE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- store the value of the chart property in memory
result=value;
//--- successful execution
return(true);
}
//+----------------------------------------------------------------------------+
//| The function enables/disables the mode of displaying the price scale on a |
//| chart. |
//+----------------------------------------------------------------------------+
bool ChartShowPriceScaleSet(const bool value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetInteger(chart_ID,CHART_SHOW_PRICE_SCALE,0,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_SHIFT_SIZE shift size of the zero bar from the right border in percentage
values.
//+---------------------------------------------------------------------------+
//| The function receives shift size of the zero bar from the right border |
//| of the chart in percentage values (from 10% up to 50%). |
//+---------------------------------------------------------------------------+
double ChartShiftSizeGet(const long chart_ID=0)
{
//--- prepare the variable to get the result
double result=EMPTY_VALUE;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetDouble(chart_ID,CHART_SHIFT_SIZE,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return(result);
}
//+----------------------------------------------------------------------------------
//| The function sets the shift size of the zero bar from the right
//| border of the chart in percentage values (from 10% up to 50%). To enable the shif
//| mode, CHART_SHIFT property value should be set to
//| true.
//+----------------------------------------------------------------------------------
bool ChartShiftSizeSet(const double value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetDouble(chart_ID,CHART_SHIFT_SIZE,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_IS_OFFLINE checks offline mode of the chart.
//+------------------------------------------------------------------+
//| The function checks offline mode of the chart |
//+------------------------------------------------------------------+
bool CheckChartOffline(const long chart_ID=0)
{
bool offline=ChartGetInteger(chart_ID,CHART_IS_OFFLINE);
return(offline);
}

 
CHART_FIXED_POSITION chart fixed position from the left border in percentage
value.
//+--------------------------------------------------------------------------+
//| The function receives the location of the chart fixed position from the |
//| left border in percentage value. |
//+--------------------------------------------------------------------------+
double ChartFixedPositionGet(const long chart_ID=0)
{
//--- prepare the variable to get the result
double result=EMPTY_VALUE;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetDouble(chart_ID,CHART_FIXED_POSITION,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return(result);
}
//+---------------------------------------------------------------------+
//| The function sets the location of the chart fixed position from the |
//| left border in percentage value. To view the location of the |
//| chart fixed position, the value of |
//| CHART_AUTOSCROLL property should be set to false. |
//+---------------------------------------------------------------------+
bool ChartFixedPositionSet(const double value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetDouble(chart_ID,CHART_FIXED_POSITION,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_FIXED_MAX property of the chart's fixed maximum.
//+------------------------------------------------------------------+
//| The function receives the value of chart's fixed maximum. |
//+------------------------------------------------------------------+
double ChartFixedMaxGet(const long chart_ID=0)
{
//--- prepare the variable to get the result
double result=EMPTY_VALUE;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetDouble(chart_ID,CHART_FIXED_MAX,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return(result);
}
//+------------------------------------------------------------------+
//| The function sets the value of chart's fixed maximum. |
//| To change the value of the property, |
//| CHART_SCALEFIX property value should be preliminarily set to |
//| true. |
//+------------------------------------------------------------------+
bool ChartFixedMaxSet(const double value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetDouble(chart_ID,CHART_FIXED_MAX,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_FIXED_MIN property of the chart's fixed minimum.
//+------------------------------------------------------------------+
//| The function receives the value of chart's fixed minimum. |
//+------------------------------------------------------------------+
double ChartFixedMinGet(const long chart_ID=0)
{
//--- prepare the variable to get the result
double result=EMPTY_VALUE;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetDouble(chart_ID,CHART_FIXED_MIN,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return(result);
}
//+------------------------------------------------------------------+
//| The function sets the value of chart's fixed minimum. |
//| To change the value of the property, |
//| CHART_SCALEFIX property value should be preliminarily set to |
//| true. |
//+------------------------------------------------------------------+
bool ChartFixedMinSet(const double value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetDouble(chart_ID,CHART_FIXED_MIN,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_POINTS_PER_BAR value of scale in points per bar.
//+---------------------------------------------------------------------------+
//| The function receives the value of the chart scale in points per bar. |
//+---------------------------------------------------------------------------+
double ChartPointsPerBarGet(const long chart_ID=0)
{
//--- prepare the variable to get the result
double result=EMPTY_VALUE;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetDouble(chart_ID,CHART_POINTS_PER_BAR,0,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return(result);
}
//+----------------------------------------------------------------------+
//| The function sets the value of the chart scale in points per bar. |
//| To view the result of this property's value change, |
//| the value of |
//| CHART_SCALE_PT_PER_BAR property should be preliminarily set to true. |
//+----------------------------------------------------------------------+
bool ChartPointsPerBarSet(const double value,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetDouble(chart_ID,CHART_POINTS_PER_BAR,value))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
CHART_PRICE_MIN returns the value of the chart minimum.
//+---------------------------------------------------------------------------------+
//| The function receives the value of the chart minimum in the main window or a |
//| subwindow. |
//+---------------------------------------------------------------------------------+
double ChartPriceMin(const long chart_ID=0,const int sub_window=0)
{
//--- prepare the variable to get the result
double result=EMPTY_VALUE;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetDouble(chart_ID,CHART_PRICE_MIN,sub_window,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return(result);
}

 
CHART_PRICE_MAX returns the value of the chart maximum.
//+--------------------------------------------------------------------------------+
//| The function receives the value of the chart maximum in the main window or a |
//| subwindow. |
//+--------------------------------------------------------------------------------+
double ChartPriceMax(const long chart_ID=0,const int sub_window=0)
{
//--- prepare the variable to get the result
double result=EMPTY_VALUE;
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetDouble(chart_ID,CHART_PRICE_MAX,sub_window,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
}
//--- return the value of the chart property
return(result);
}

 
CHART_COMMENT comment on the chart.
//+----------------------------------------------------------------------+
//| The function receives comment in the upper left corner of the chart. |
//+----------------------------------------------------------------------+
bool ChartCommentGet(string &result,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- receive the property value
if(!ChartGetString(chart_ID,CHART_COMMENT,result))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| The function sets comment in the upper left corner of the |
//| chart. |
//+------------------------------------------------------------------+
bool ChartCommentSet(const string str,const long chart_ID=0)
{
//--- reset the error value
ResetLastError();
//--- set property value
if(!ChartSetString(chart_ID,CHART_COMMENT,str))
{
//--- display the error message in Experts journal
Print(__FUNCTION__+", Error Code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}

 
Panel for chart properties
//--- connect the library of control elements
#include <ChartObjects\[Link]>
//--- predefined constants
#define X_PROPERTY_NAME_1 10 // х coordinate of the property name in the first co
#define X_PROPERTY_VALUE_1 225 // х coordinate of the property value in the first c
#define X_PROPERTY_NAME_2 345 // х coordinate of the property name in the second a
#define X_PROPERTY_VALUE_2 550 // х coordinate of the property value in the second
#define X_BUTTON_1 285 // х coordinate of the button in the first column
#define X_BUTTON_2 700 // х coordinate of the button in the second column
#define Y_PROPERTY_1 30 // y coordinate of the beginning of the first and se
#define Y_PROPERTY_2 286 // y coordinate of the beginning of the third column
#define Y_DISTANCE 16 // y axial distance between the lines
#define LAST_PROPERTY_NUMBER 111 // number of the last graphical property
//--- input parameters
input color InpFirstColor=clrDodgerBlue; // Color of odd lines
input color InpSecondColor=clrGoldenrod; // Color of even lines
//--- variables and arrays
CChartObjectLabel ExtLabelsName[]; // labels for displaying property names
CChartObjectLabel ExtLabelsValue[]; // labels for displaying property values
CChartObjectButton ExtButtons[]; // buttons
int ExtNumbers[]; // property indices
string ExtNames[]; // property names
uchar ExtDataTypes[]; // property data types (integer, double, string)
uint ExtGroupTypes[]; // array that stores the data on belonging of pr
uchar ExtDrawTypes[]; // array that stores the data on the type of pro
double ExtMaxValue[]; // maximum property values that are possible whe
double ExtMinValue[]; // minimum property values that are possible whe
double ExtStep[]; // steps for changing properties
int ExtCount; // total number of all properties
color ExtColors[2]; // array of colors for displaying lines
string ExtComments[2]; // array of comments (for CHART_COMMENT property
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- display a comment on the chart
Comment("SomeComment");
//--- store colors in the array to be able to switch between them later
ExtColors[0]=InpFirstColor;
ExtColors[1]=InpSecondColor;
//--- store comments in the array to be able to switch between them later
ExtComments[0]="FirstComment";
ExtComments[1]="SecondComment";
//--- prepare and display the control panel for managing chart properties
if(!PrepareControls())
return(INIT_FAILED);
//--- successful execution
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Deinitialization function of the expert |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- remove the comment on the chart
Comment("");
}
//+------------------------------------------------------------------+
//| Handler of a chart event |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//--- check the event of clicking the chart object
if(id==CHARTEVENT_OBJECT_CLICK)
{
//--- divide the object name by separator
string obj_name[];
StringSplit(sparam,'_',obj_name);
//--- check if the object is a button
if(obj_name[0]=="Button")
{
//--- receive button index
int index=(int)StringToInteger(obj_name[1]);
//--- unpress the button
ExtButtons[index].State(false);
//--- set the new value of the property depending on its type
if(ExtDataTypes[index]=='I')
ChangeIntegerProperty(index);
if(ExtDataTypes[index]=='D')
ChangeDoubleProperty(index);
if(ExtDataTypes[index]=='S')
ChangeStringProperty(index);
}
}
//--- re-draw property values
RedrawProperties();
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Change the integer property of the chart |
//+------------------------------------------------------------------+
void ChangeIntegerProperty(const int index)
{
//--- receive the current property value
long value=ChartGetInteger(0,(ENUM_CHART_PROPERTY_INTEGER)ExtNumbers[index]);
//--- define the following property value
switch(ExtDrawTypes[index])
{
case 'C':
value=GetNextColor((color)value);
break;
default:
value=(long)GetNextValue((double)value,index);
break;
}
//--- set the new property value
ChartSetInteger(0,(ENUM_CHART_PROPERTY_INTEGER)ExtNumbers[index],0,value);
}
//+------------------------------------------------------------------+
//| Change double property of the chart |
//+------------------------------------------------------------------+
void ChangeDoubleProperty(const int index)
{
//--- receive the current property value
double value=ChartGetDouble(0,(ENUM_CHART_PROPERTY_DOUBLE)ExtNumbers[index]);
//--- define the following property value
value=GetNextValue(value,index);
//--- set the new property value
ChartSetDouble(0,(ENUM_CHART_PROPERTY_DOUBLE)ExtNumbers[index],value);
}
//+------------------------------------------------------------------+
//| Change string property of the chart |
//+------------------------------------------------------------------+
void ChangeStringProperty(const int index)
{
//--- static variable for switching inside ExtComments array
static uint comment_index=1;
//--- change index for receiving another comment
comment_index=1-comment_index;
//--- set the new property value
ChartSetString(0,(ENUM_CHART_PROPERTY_STRING)ExtNumbers[index],ExtComments[comment
}
//+------------------------------------------------------------------+
//| Define the next property value |
//+------------------------------------------------------------------+
double GetNextValue(const double value,const int index)
{
if(value+ExtStep[index]<=ExtMaxValue[index])
return(value+ExtStep[index]);
else
return(ExtMinValue[index]);
}
//+------------------------------------------------------------------+
//| Receive the next color for color type property |
//+------------------------------------------------------------------+
color GetNextColor(const color clr)
{
//--- return the following color value
switch(clr)
{
case clrWhite: return(clrRed);
case clrRed: return(clrGreen);
case clrGreen: return(clrBlue);
case clrBlue: return(clrBlack);
default: return(clrWhite);
}
}
//+------------------------------------------------------------------+
//| Re-draw property values |
//+------------------------------------------------------------------+
void RedrawProperties(void)
{
//--- property value text
string text;
long value;
//--- loop of the number of properties
for(int i=0;i<ExtCount;i++)
{
text="";
switch(ExtDataTypes[i])
{
case 'I':
//--- receive the current property value
if(!ChartGetInteger(0,(ENUM_CHART_PROPERTY_INTEGER)ExtNumbers[i],0,value)
break;
//--- integer property text
switch(ExtDrawTypes[i])
{
//--- color property
case 'C':
text=(string)((color)value);
break;
//--- boolean property
case 'B':
text=(string)((bool)value);
break;
//--- ENUM_CHART_MODE enumeration property
case 'M':
text=EnumToString((ENUM_CHART_MODE)value);
break;
//--- ENUM_CHART_VOLUME_MODE enumeration property
case 'V':
text=EnumToString((ENUM_CHART_VOLUME_MODE)value);
break;
//--- int type number
default:
text=IntegerToString(value);
break;
}
break;
case 'D':
//--- double property text
text=DoubleToString(ChartGetDouble(0,(ENUM_CHART_PROPERTY_DOUBLE)ExtNumbe
break;
case 'S':
//--- string property text
text=ChartGetString(0,(ENUM_CHART_PROPERTY_STRING)ExtNumbers[i]);
break;
}
//--- display property value
ExtLabelsValue[i].Description(text);
}
}
//+------------------------------------------------------------------+
//| Create the panel for managing chart properties |
//+------------------------------------------------------------------+
bool PrepareControls(void)
{
//--- allocate memory for arrays with a reserve
MemoryAllocation(LAST_PROPERTY_NUMBER+1);
//--- variables
int i=0; // loop variable
int col_1=0; // number of properties in the first column
int col_2=0; // number of properties in the second column
int col_3=0; // number of properties in the third column
//--- current number of properties - 0
ExtCount=0;
//--- looking for properties in the loop
while(i<=LAST_PROPERTY_NUMBER)
{
//--- store the current number of the property
ExtNumbers[ExtCount]=i;
//--- increase the value of the loop variable
i++;
//--- check if there is a property with such a number
if(CheckNumber(ExtNumbers[ExtCount],ExtNames[ExtCount],ExtDataTypes[ExtCount],E
{
//--- create control elements for the property
switch(ExtGroupTypes[ExtCount])
{
case 1:
//--- create labels and a button for the property
if(!ShowProperty(ExtCount,0,X_PROPERTY_NAME_1,X_PROPERTY_VALUE_1,X_BUT
return(false);
//--- number of the elements in the first column has increased
col_1++;
break;
case 2:
//--- create labels and a button for the property
if(!ShowProperty(ExtCount,1,X_PROPERTY_NAME_2,X_PROPERTY_VALUE_2,X_BUT
return(false);
//--- number of the elements in the second column has increased
col_2++;
break;
case 3:
//--- create only labels for the property
if(!ShowProperty(ExtCount,2,X_PROPERTY_NAME_2,X_PROPERTY_VALUE_2,0,Y_P
return(false);
//--- number of the elements in the third column has increased
col_3++;
break;
}
//--- define maximum and minimum property value and step
GetMaxMinStep(ExtNumbers[ExtCount],ExtMaxValue[ExtCount],ExtMinValue[ExtCoun
//--- increase the number of properties
ExtCount++;
}
}
//--- free the memory not used by arrays
MemoryAllocation(ExtCount);
//--- re-draw property values
RedrawProperties();
ChartRedraw();
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Allocate memory for arrays |
//+------------------------------------------------------------------+
void MemoryAllocation(const int size)
{
ArrayResize(ExtLabelsName,size);
ArrayResize(ExtLabelsValue,size);
ArrayResize(ExtButtons,size);
ArrayResize(ExtNumbers,size);
ArrayResize(ExtNames,size);
ArrayResize(ExtDataTypes,size);
ArrayResize(ExtGroupTypes,size);
ArrayResize(ExtDrawTypes,size);
ArrayResize(ExtMaxValue,size);
ArrayResize(ExtMinValue,size);
ArrayResize(ExtStep,size);
}
//+------------------------------------------------------------------+
//| Check if the property index belongs to the one of |
//| ENUM_CHART_PROPERTIES enumerations |
//+------------------------------------------------------------------+
bool CheckNumber(const int ind,string &name,uchar &data_type,uint &group_type,uchar &
{
//--- check if the property is of integer type
ResetLastError();
name=EnumToString((ENUM_CHART_PROPERTY_INTEGER)ind);
if(_LastError==0)
{
data_type='I'; // property from ENUM_CHART_PROPERTY_INTEGE
GetTypes(ind,group_type,draw_type); // define property display parameters
return(true);
}
//--- check if the property is of double type
ResetLastError();
name=EnumToString((ENUM_CHART_PROPERTY_DOUBLE)ind);
if(_LastError==0)
{
data_type='D'; // property from ENUM_CHART_PROPERTY_DOUBLE
GetTypes(ind,group_type,draw_type); // define property display parameters
return(true);
}
//--- check if the property is of string type
ResetLastError();
name=EnumToString((ENUM_CHART_PROPERTY_STRING)ind);
if(_LastError==0)
{
data_type='S'; // property from ENUM_CHART_PROPERTY_STRING
GetTypes(ind,group_type,draw_type); // define property display parameters
return(true);
}
//--- property does not belong to any enumeration
return(false);
}
//+------------------------------------------------------------------+
//| Define the group the property should be stored in, |
//| as well as its display type |
//+------------------------------------------------------------------+
void GetTypes(const int property_number,uint &group_type,uchar &draw_type)
{
//--- check if the property belongs to the third group
//--- third group properties are displayed in the second column starting from CHART_B
if(CheckThirdGroup(property_number,group_type,draw_type))
return;
//--- check if the property belongs to the second group
//--- second group properties are displayed at the beginning of the second column
if(CheckSecondGroup(property_number,group_type,draw_type))
return;
//--- if you find yourself here, the property belongs to the first group (first colum
CheckFirstGroup(property_number,group_type,draw_type);
}
//+----------------------------------------------------------------------+
//| The function checks if the property belongs to the third group and |
//| defines its display type in case of a positive answer |
//+----------------------------------------------------------------------+
bool CheckThirdGroup(const int property_number,uint &group_type,uchar &draw_type)
{
//--- check if the property belongs to the third group
switch(property_number)
{
//--- boolean properties
case CHART_WINDOW_IS_VISIBLE:
draw_type='B';
break;
//--- integer properties
case CHART_VISIBLE_BARS:
case CHART_WINDOWS_TOTAL:
case CHART_WINDOW_HANDLE:
case CHART_WINDOW_YDISTANCE:
case CHART_FIRST_VISIBLE_BAR:
case CHART_WIDTH_IN_BARS:
case CHART_WIDTH_IN_PIXELS:
draw_type='I';
break;
//--- double properties
case CHART_PRICE_MIN:
case CHART_PRICE_MAX:
draw_type='D';
break;
//--- in fact, this property is a command of displaying the chart on top of
//--- there is no need to apply this panel, as the window will always be
//--- on top of other ones before we use it
case CHART_BRING_TO_TOP:
draw_type=' ';
break;
//--- property does not belong to the third group
default:
return(false);
}
//--- property belongs to the third group
group_type=3;
return(true);
}
//+----------------------------------------------------------------------+
//| The function checks if the property belongs to the second group and |
//| defines its display type in case of a positive answer |
//+----------------------------------------------------------------------+
bool CheckSecondGroup(const int property_number,uint &group_type,uchar &draw_type)
{
//--- check if the property belongs to the second group
switch(property_number)
{
//--- ENUM_CHART_MODE type property
case CHART_MODE:
draw_type='M';
break;
//--- ENUM_CHART_VOLUME_MODE type property
case CHART_SHOW_VOLUMES:
draw_type='V';
break;
//--- string property
case CHART_COMMENT:
draw_type='S';
break;
//--- color property
case CHART_COLOR_BACKGROUND:
case CHART_COLOR_FOREGROUND:
case CHART_COLOR_GRID:
case CHART_COLOR_VOLUME:
case CHART_COLOR_CHART_UP:
case CHART_COLOR_CHART_DOWN:
case CHART_COLOR_CHART_LINE:
case CHART_COLOR_CANDLE_BULL:
case CHART_COLOR_CANDLE_BEAR:
case CHART_COLOR_BID:
case CHART_COLOR_ASK:
case CHART_COLOR_LAST:
case CHART_COLOR_STOP_LEVEL:
draw_type='C';
break;
//--- property does not belong to the second group
default:
return(false);
}
//--- property belongs to the second group
group_type=2;
return(true);
}
//+-----------------------------------------------------------------------+
//| This function is called only if it is already known that |
//| the property does not belong to the second and third property groups |
//+-----------------------------------------------------------------------+
void CheckFirstGroup(const int property_number,uint &group_type,uchar &draw_type)
{
//--- the property belongs to the first group
group_type=1;
//--- define property display type
switch(property_number)
{
//--- integer properties
case CHART_SCALE:
case CHART_HEIGHT_IN_PIXELS:
draw_type='I';
return;
//--- double properties
case CHART_SHIFT_SIZE:
case CHART_FIXED_POSITION:
case CHART_FIXED_MAX:
case CHART_FIXED_MIN:
case CHART_POINTS_PER_BAR:
draw_type='D';
return;
//--- only boolean properties have remained
default:
draw_type='B';
return;
}
}
//+------------------------------------------------------------------+
//| Create a label and a button for the property |
//+------------------------------------------------------------------+
bool ShowProperty(const int ind,const int type,const int x1,const int x2,
const int xb,const int y,const bool btn)
{
//--- static array for switching inside ExtColors color array
static uint color_index[3]={1,1,1};
//--- change index for receiving another color
color_index[type]=1-color_index[type];
//--- display labels and a button (if btn=true) for the property
if(!LabelCreate(ExtLabelsName[ind],"name_"+(string)ind,ExtNames[ind],ExtColors[col
return(false);
if(!LabelCreate(ExtLabelsValue[ind],"value_"+(string)ind,"",ExtColors[color_index[
return(false);
if(btn && !ButtonCreate(ExtButtons[ind],(string)ind,xb,y+1))
return(false);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Create a label |
//+------------------------------------------------------------------+
bool LabelCreate(CChartObjectLabel &lbl,const string name,const string text,
const color clr,const int x,const int y)
{
if(![Link](0,"Label_"+name,0,x,y)) return(false);
if(![Link](text)) return(false);
if(![Link](10)) return(false);
if(![Link](clr)) return(false);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Create the button |
//+------------------------------------------------------------------+
bool ButtonCreate(CChartObjectButton &btn,const string name,
const int x,const int y)
{
if(![Link](0,"Button_"+name,0,x,y,50,15)) return(false);
if(![Link]("Next")) return(false);
if(![Link](10)) return(false);
if(![Link](clrBlack)) return(false);
if(![Link](clrWhite)) return(false);
if(![Link](clrBlack)) return(false);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Define maximum and minimum property value and step |
//+------------------------------------------------------------------+
void GetMaxMinStep(const int property_number,double &max,double &min,double &step)
{
double value;
//--- set values depending on the property type
switch(property_number)
{
case CHART_SCALE:
max=5;
min=0;
step=1;
break;
case CHART_MODE:
case CHART_SHOW_VOLUMES:
max=2;
min=0;
step=1;
break;
case CHART_SHIFT_SIZE:
max=50;
min=10;
step=2.5;
break;
case CHART_FIXED_POSITION:
max=90;
min=0;
step=15;
break;
case CHART_POINTS_PER_BAR:
max=19;
min=1;
step=3;
break;
case CHART_FIXED_MAX:
value=ChartGetDouble(0,CHART_FIXED_MAX);
max=value*1.25;
min=value;
step=value/32;
break;
case CHART_FIXED_MIN:
value=ChartGetDouble(0,CHART_FIXED_MIN);
max=value;
min=value*0.75;
step=value/32;
break;
case CHART_HEIGHT_IN_PIXELS:
max=700;
min=520;
step=30;
break;
//--- default values
default:
max=1;
min=0;
step=1;
}
}
MQL4 Reference / Constants, Enumerations and Structures / Objects Constants

Object Constants
There are 40 graphical objects that can be created and displayed
in the price chart. All constants for working with objects are
divided into 9 groups:
Object types Identifiers of graphical objects;
Object properties setting and getting properties of graphical
objects;
Methods of object binding constants of object positioning in the
chart;
Binding corner setting the corner relative to which an object is
positioned on chart;
Visibility of objects setting timeframes in which an object is
visible;
Gann objects trend constants for Gann fan and Gann grid;
Web colors constants of predefined web colors;
Wingdings codes of characters of the Wingdings font.
 
What's new in MQL5
Added new objects and analytical tools. The most notable of them
is the OBJ_CHART graphical object which is actually a full-fledged
chart. It allows creating an unlimited number of nested charts, set
all the necessary properties (color scheme, timeframe, symbol)
and even impose indicators on them.
Added new properties allowing you to manage a chart object
location and visibility more accurately.
ID Description Property Type
ID Description Property Type
Fill an object with
color (for
OBJ_RECTANGLE,
OBJ_TRIANGLE,
OBJ_ELLIPSE,
OBJ_CHANNEL,
OBJPROP_FILL bool
OBJ_STDDEVCHANNEL,
OBJ_REGRESSION)
OBJ_ELLIPSE,
OBJ_CHANNEL,
OBJ_STDDEVCHANNEL,
OBJ_REGRESSION)
OBJPROP_SELECTABLE Object availability bool
Time of object
OBJPROP_CREATETIME datetime    r/o
creation
OBJPROP_RAY_LEFT Ray goes to the left bool
Location of the anchor
ENUM_ARROW_ANCHOR
OBJPROP_ANCHOR point of a graphical
ENUM_ANCHOR_POINT
object
Button state (pressed
OBJPROP_STATE bool
/ depressed))
ID of the "Chart"
object (OBJ_CHART).
It allows working with
the properties of this
OBJPROP_CHART_ID object like with a long  r/o
normal chart using the
functions described in
Chart Operations, but
there some exceptions
Timeframe for the
OBJPROP_PERIOD ENUM_TIMEFRAMES
Chart object
Displaying the time
OBJPROP_DATE_SCALE scale for the Chart bool
object
ID Description Property Type
Displaying the price
OBJPROP_PRICE_SCALE scale for the Chart bool
object
The scale for the int   value in the range
OBJPROP_CHART_SCALE
Chart object 0-5
MQL4 Reference / Constants, Enumerations and Structures / Objects
Constants / Object Types

Object Types
When a graphical object is created using the
ObjectCreate() function, it's necessary to specify the type
of object being created, which can be one of the values
of the ENUM_OBJECT enumeration. Object type identifiers
are used in ObjectCreate(), ObjectsDeleteAll() and
ObjectType() functions.
Further specifications of object properties are possible
using functions for working with graphical objects.
ENUM_OBJECT
ID   Description
OBJ_VLINE Vertical Line
OBJ_HLINE Horizontal Line
OBJ_TREND Trend Line
OBJ_TRENDBYANGLE Trend Line By Angle
OBJ_CYCLES Cycle Lines
OBJ_CHANNEL Equidistant Channel
OBJ_STDDEVCHANNEL Standard Deviation Channel
OBJ_REGRESSION Linear Regression Channel
OBJ_PITCHFORK Andrews Pitchfork
OBJ_GANNLINE Gann Line
OBJ_GANNFAN Gann Fan
OBJ_GANNGRID Gann Grid
ID   Description
OBJ_FIBO Fibonacci Retracement
OBJ_FIBOTIMES Fibonacci Time Zones
OBJ_FIBOFAN Fibonacci Fan
OBJ_FIBOARC Fibonacci Arcs
OBJ_FIBOCHANNEL Fibonacci Channel
OBJ_EXPANSION Fibonacci Expansion
OBJ_RECTANGLE Rectangle
OBJ_TRIANGLE Triangle
OBJ_ELLIPSE Ellipse
OBJ_ARROW_THUMB_UP Thumbs Up
OBJ_ARROW_THUMB_DOWN Thumbs Down
OBJ_ARROW_UP Arrow Up
OBJ_ARROW_DOWN Arrow Down
OBJ_ARROW_STOP Stop Sign
OBJ_ARROW_CHECK Check Sign
OBJ_ARROW_LEFT_PRICE Left Price Label
OBJ_ARROW_RIGHT_PRICE Right Price Label
OBJ_ARROW_BUY Buy Sign
OBJ_ARROW_SELL Sell Sign
OBJ_ARROW Arrow
OBJ_TEXT Text
OBJ_LABEL Label
OBJ_BUTTON Button
ID   Description
OBJ_BITMAP Bitmap
OBJ_BITMAP_LABEL Bitmap Label
OBJ_EDIT Edit
OBJ_EVENT The "Event" object
corresponding to an event in
the economic calendar
OBJ_RECTANGLE_LABEL The "Rectangle label" object
for creating and designing
the custom graphical
interface.
MQL4 Reference / Constants, Enumerations and Structures / Objects Constants / Object Types / OBJ_VLINE

OBJ_VLINE
Vertical Line.

Example
The following script creates and moves the vertical line on the chart. Special functions
have been developed to create and change graphical object's properties. You can use
these functions "as is" in your own applications.
#property strict //--- description
#property description "Script draws \"Vertical Line\" graphical object."
#property description "Anchor point date is set in percentage of"
#property description "the chart window width in bars."
//--- display window of the input parameters during the script's launch
#property script_show_inputs
//--- input parameters of the script
input string InpName="VLine"; // Line name
input int InpDate=25; // Event date, %
input color InpColor=clrRed; // Line color
input ENUM_LINE_STYLE InpStyle=STYLE_DASH; // Line style
input int InpWidth=1; // Line width
input bool InpBack=false; // Background line
input bool InpSelection=true; // Highlight to move
input bool InpHidden=true; // Hidden in the object list
input long InpZOrder=0; // Priority for mouse click
//+------------------------------------------------------------------+
//| Create the vertical line |
//+------------------------------------------------------------------+
bool VLineCreate(const long chart_ID=0, // chart's ID
const string name="VLine", // line name
const int sub_window=0, // subwindow index
datetime time=0, // line time
const color clr=clrRed, // line color
const ENUM_LINE_STYLE style=STYLE_SOLID, // line style
const int width=1, // line width
const bool back=false, // in the background
const bool selection=true, // highlight to move
const bool hidden=true, // hidden in the object lis
const long z_order=0) // priority for mouse click
{
//--- if the line time is not set, draw it via the last bar
if(!time)
time=TimeCurrent();
//--- reset the error value
ResetLastError();
//--- create a vertical line
if(!ObjectCreate(chart_ID,name,OBJ_VLINE,sub_window,time,0))
{
Print(__FUNCTION__,
": failed to create a vertical line! Error code = ",GetLastError());
return(false);
}
//--- set line color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set line display style
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set line width
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the line by mouse
//--- when creating a graphical object using ObjectCreate function, the object cannot
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Move the vertical line |
//+------------------------------------------------------------------+
bool VLineMove(const long chart_ID=0, // chart's ID
const string name="VLine", // line name
datetime time=0) // line time
{
//--- if line time is not set, move the line to the last bar
if(!time)
time=TimeCurrent();
//--- reset the error value
ResetLastError();
//--- move the vertical line
if(!ObjectMove(chart_ID,name,0,time,0))
{
Print(__FUNCTION__,
": failed to move the vertical line! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Delete the vertical line |
//+------------------------------------------------------------------+
bool VLineDelete(const long chart_ID=0, // chart's ID
const string name="VLine") // line name
{
//--- reset the error value
ResetLastError();
//--- delete the vertical line
if(!ObjectDelete(chart_ID,name))
{
Print(__FUNCTION__,
": failed to delete the vertical line! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- check correctness of the input parameters
if(InpDate<0 || InpDate>100)
{
Print("Error! Incorrect values of input parameters!");
return;
}
//--- number of visible bars in the chart window
int bars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);
//--- array for storing the date values to be used
//--- for setting and changing line anchor point's coordinates
datetime date[];
//--- memory allocation
ArrayResize(date,bars);
//--- fill the array of dates
ResetLastError();
if(CopyTime(Symbol(),Period(),0,bars,date)==-1)
{
Print("Failed to copy time values! Error code = ",GetLastError());
return;
}
//--- define points for drawing the line
int d=InpDate*(bars-1)/100;
//--- create a vertical line
if(!VLineCreate(0,InpName,0,date[d],InpColor,InpStyle,InpWidth,InpBack,
InpSelection,InpHidden,InpZOrder))
return;
//--- redraw the chart and wait for 1 second
ChartRedraw();
Sleep(1000);
//--- now, move the line
//--- loop counter
int h_steps=bars/2;
//--- move the line
for(int i=0;i<h_steps;i++)
{
//--- use the following value
if(d<bars-1)
d+=1;
//--- move the point
if(!VLineMove(0,InpName,date[d]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
// 0.03 seconds of delay
Sleep(30);
}
//--- 1 second of delay
Sleep(1000);
//--- delete the channel from the chart
VLineDelete(0,InpName);
ChartRedraw();
//--- 1 second of delay
Sleep(1000);
//---
}
MQL4 Reference / Constants, Enumerations and Structures / Objects Constants / Object Types / OBJ_HLINE

OBJ_HLINE
Horizontal Line.

Example
The following script creates and moves the horizontal line on the chart. Special
functions have been developed to create and change graphical object's properties. You
can use these functions "as is" in your own applications.
#property strict //--- description
#property description "Script draws \"Horizontal Line\" graphical object."
#property description "Anchor point price is set in percentage of the height of"
#property description "the chart window."
//--- display window of the input parameters during the script's launch
#property script_show_inputs
//--- input parameters of the script
input string InpName="HLine"; // Line name
input int InpPrice=25; // Line price, %
input color InpColor=clrRed; // Line color
input ENUM_LINE_STYLE InpStyle=STYLE_DASH; // Line style
input int InpWidth=1; // Line width
input bool InpBack=false; // Background line
input bool InpSelection=true; // Highlight to move
input bool InpHidden=true; // Hidden in the object list
input long InpZOrder=0; // Priority for mouse click
//+------------------------------------------------------------------+
//| Create the horizontal line |
//+------------------------------------------------------------------+
bool HLineCreate(const long chart_ID=0, // chart's ID
const string name="HLine", // line name
const int sub_window=0, // subwindow index
double price=0, // line price
const color clr=clrRed, // line color
const ENUM_LINE_STYLE style=STYLE_SOLID, // line style
const int width=1, // line width
const bool back=false, // in the background
const bool selection=true, // highlight to move
const bool hidden=true, // hidden in the object lis
const long z_order=0) // priority for mouse click
{
//--- if the price is not set, set it at the current Bid price level
if(!price)
price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- reset the error value
ResetLastError();
//--- create a horizontal line
if(!ObjectCreate(chart_ID,name,OBJ_HLINE,sub_window,0,price))
{
Print(__FUNCTION__,
": failed to create a horizontal line! Error code = ",GetLastError());
return(false);
}
//--- set line color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set line display style
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set line width
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the line by mouse
//--- when creating a graphical object using ObjectCreate function, the object cannot
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Move horizontal line |
//+------------------------------------------------------------------+
bool HLineMove(const long chart_ID=0, // chart's ID
const string name="HLine", // line name
double price=0) // line price
{
//--- if the line price is not set, move it to the current Bid price level
if(!price)
price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- reset the error value
ResetLastError();
//--- move a horizontal line
if(!ObjectMove(chart_ID,name,0,0,price))
{
Print(__FUNCTION__,
": failed to move the horizontal line! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Delete a horizontal line |
//+------------------------------------------------------------------+
bool HLineDelete(const long chart_ID=0, // chart's ID
const string name="HLine") // line name
{
//--- reset the error value
ResetLastError();
//--- delete a horizontal line
if(!ObjectDelete(chart_ID,name))
{
Print(__FUNCTION__,
": failed to delete a horizontal line! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- check correctness of the input parameters
if(InpPrice<0 || InpPrice>100)
{
Print("Error! Incorrect values of input parameters!");
return;
}
//--- price array size
int accuracy=1000;
//--- array for storing the price values to be used
//--- for setting and changing line anchor point's coordinates
double price[];
//--- memory allocation
ArrayResize(price,accuracy);
//--- fill the array of prices
//--- find the highest and lowest values of the chart
double max_price=ChartGetDouble(0,CHART_PRICE_MAX);
double min_price=ChartGetDouble(0,CHART_PRICE_MIN);
//--- define a change step of a price and fill the array
double step=(max_price-min_price)/accuracy;
for(int i=0;i<accuracy;i++)
price[i]=min_price+i*step;
//--- define points for drawing the line
int p=InpPrice*(accuracy-1)/100;
//--- create a horizontal line
if(!HLineCreate(0,InpName,0,price[p],InpColor,InpStyle,InpWidth,InpBack,
InpSelection,InpHidden,InpZOrder))
{
return;
}
//--- redraw the chart and wait for 1 second
ChartRedraw();
Sleep(1000);
//--- now, move the line
//--- loop counter
int v_steps=accuracy/2;
//--- move the line
for(int i=0;i<v_steps;i++)
{
//--- use the following value
if(p<accuracy-1)
p+=1;
//--- move the point
if(!HLineMove(0,InpName,price[p]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
}
//--- 1 second of delay
Sleep(1000);
//--- delete from the chart
HLineDelete(0,InpName);
ChartRedraw();
//--- 1 second of delay
Sleep(1000);
//---
}
MQL4 Reference / Constants, Enumerations and Structures / Objects Constants / Object Types / OBJ_TREND

OBJ_TREND
Trend Line.

Note
For Trend Line, it is possible to specify the mode of continuation of its display to the
right (OBJPROP_RAY_RIGHT property).
Example
The following script creates and moves the trend line on the chart. Special functions
have been developed to create and change graphical object's properties. You can use
these functions "as is" in your own applications.
#property strict //--- description
#property description "Script draws \"Trend Line\" graphical object."
#property description "Anchor point coordinates are set in percentage of"
#property description "the chart window size."
//--- display window of the input parameters during the script's launch
#property script_show_inputs
//--- input parameters of the script
input string InpName="Trend"; // Line name
input int InpDate1=35; // 1 st point's date, %
input int InpPrice1=60; // 1 st point's price, %
input int InpDate2=65; // 2 nd point's date, %
input int InpPrice2=40; // 2 nd point's price, %
input color InpColor=clrRed; // Line color
input ENUM_LINE_STYLE InpStyle=STYLE_DASH; // Line style
input int InpWidth=1; // Line width
input bool InpBack=false; // Background line
input bool InpSelection=true; // Highlight to move
input bool InpRayRight=false; // Line's continuation to the right
input bool InpHidden=true; // Hidden in the object list
input long InpZOrder=0; // Priority for mouse click
//+------------------------------------------------------------------+
//| Create a trend line by the given coordinates |
//+------------------------------------------------------------------+
bool TrendCreate(const long chart_ID=0, // chart's ID
const string name="TrendLine", // line name
const int sub_window=0, // subwindow index
datetime time1=0, // first point time
double price1=0, // first point price
datetime time2=0, // second point time
double price2=0, // second point price
const color clr=clrRed, // line color
const ENUM_LINE_STYLE style=STYLE_SOLID, // line style
const int width=1, // line width
const bool back=false, // in the background
const bool selection=true, // highlight to move
const bool ray_right=false, // line's continuation to t
const bool hidden=true, // hidden in the object lis
const long z_order=0) // priority for mouse click
{
//--- set anchor points' coordinates if they are not set
ChangeTrendEmptyPoints(time1,price1,time2,price2);
//--- reset the error value
ResetLastError();
//--- create a trend line by the given coordinates
if(!ObjectCreate(chart_ID,name,OBJ_TREND,sub_window,time1,price1,time2,price2))
{
Print(__FUNCTION__,
": failed to create a trend line! Error code = ",GetLastError());
return(false);
}
//--- set line color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set line display style
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set line width
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the line by mouse
//--- when creating a graphical object using ObjectCreate function, the object cannot
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- enable (true) or disable (false) the mode of continuation of the line's display
ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,ray_right);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Move trend line anchor point |
//+------------------------------------------------------------------+
bool TrendPointChange(const long chart_ID=0, // chart's ID
const string name="TrendLine", // line name
const int point_index=0, // anchor point index
datetime time=0, // anchor point time coordinate
double price=0) // anchor point price coordinate
{
//--- if point position is not set, move it to the current bar having Bid price
if(!time)
time=TimeCurrent();
if(!price)
price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- reset the error value
ResetLastError();
//--- move trend line's anchor point
if(!ObjectMove(chart_ID,name,point_index,time,price))
{
Print(__FUNCTION__,
": failed to move the anchor point! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| The function deletes the trend line from the chart. |
//+------------------------------------------------------------------+
bool TrendDelete(const long chart_ID=0, // chart's ID
const string name="TrendLine") // line name
{
//--- reset the error value
ResetLastError();
//--- delete a trend line
if(!ObjectDelete(chart_ID,name))
{
Print(__FUNCTION__,
": failed to delete a trend line! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Check the values of trend line's anchor points and set default |
//| values for empty ones |
//+------------------------------------------------------------------+
void ChangeTrendEmptyPoints(datetime &time1,double &price1,
datetime &time2,double &price2)
{
//--- if the first point's time is not set, it will be on the current bar
if(!time1)
time1=TimeCurrent();
//--- if the first point's price is not set, it will have Bid value
if(!price1)
price1=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- if the second point's time is not set, it is located 9 bars left from the secon
if(!time2)
{
//--- array for receiving the open time of the last 10 bars
datetime temp[10];
CopyTime(Symbol(),Period(),time1,10,temp);
//--- set the second point 9 bars left from the first one
time2=temp[0];
}
//--- if the second point's price is not set, it is equal to the first point's one
if(!price2)
price2=price1;
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- check correctness of the input parameters
if(InpDate1<0 || InpDate1>100 || InpPrice1<0 || InpPrice1>100 ||
InpDate2<0 || InpDate2>100 || InpPrice2<0 || InpPrice2>100)
{
Print("Error! Incorrect values of input parameters!");
return;
}
//--- number of visible bars in the chart window
int bars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);
//--- price array size
int accuracy=1000;
//--- arrays for storing the date and price values to be used
//--- for setting and changing line anchor points' coordinates
datetime date[];
double price[];
//--- memory allocation
ArrayResize(date,bars);
ArrayResize(price,accuracy);
//--- fill the array of dates
ResetLastError();
if(CopyTime(Symbol(),Period(),0,bars,date)==-1)
{
Print("Failed to copy time values! Error code = ",GetLastError());
return;
}
//--- fill the array of prices
//--- find the highest and lowest values of the chart
double max_price=ChartGetDouble(0,CHART_PRICE_MAX);
double min_price=ChartGetDouble(0,CHART_PRICE_MIN);
//--- define a change step of a price and fill the array
double step=(max_price-min_price)/accuracy;
for(int i=0;i<accuracy;i++)
price[i]=min_price+i*step;
//--- define points for drawing the line
int d1=InpDate1*(bars-1)/100;
int d2=InpDate2*(bars-1)/100;
int p1=InpPrice1*(accuracy-1)/100;
int p2=InpPrice2*(accuracy-1)/100;
//--- create a trend line
if(!TrendCreate(0,InpName,0,date[d1],price[p1],date[d2],price[p2],InpColor,InpStyl
InpWidth,InpBack,InpSelection,InpRayRight,InpHidden,InpZOrder))
{
return;
}
//--- redraw the chart and wait for 1 second
ChartRedraw();
Sleep(1000);
//--- now, move the line's anchor points
//--- loop counter
int v_steps=accuracy/5;
//--- move the first anchor point vertically
for(int i=0;i<v_steps;i++)
{
//--- use the following value
if(p1>1)
p1-=1;
//--- move the point
if(!TrendPointChange(0,InpName,0,date[d1],price[p1]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
}
//--- move the second anchor point vertically
for(int i=0;i<v_steps;i++)
{
//--- use the following value
if(p2<accuracy-1)
p2+=1;
//--- move the point
if(!TrendPointChange(0,InpName,1,date[d2],price[p2]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
}
//--- half a second of delay
Sleep(500);
//--- loop counter
int h_steps=bars/2;
//--- move both anchor points horizontally at the same time
for(int i=0;i<h_steps;i++)
{
//--- use the following values
if(d1<bars-1)
d1+=1;
if(d2>1)
d2-=1;
//--- shift the points
if(!TrendPointChange(0,InpName,0,date[d1],price[p1]))
return;
if(!TrendPointChange(0,InpName,1,date[d2],price[p2]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
// 0.03 seconds of delay
Sleep(30);
}
//--- 1 second of delay
Sleep(1000);
//--- delete a trend line
TrendDelete(0,InpName);
ChartRedraw();
//--- 1 second of delay
Sleep(1000);
//---
}
MQL4 Reference / Constants, Enumerations and Structures / Objects Constants / Object Types /
OBJ_TRENDBYANGLE

OBJ_TRENDBYANGLE
Trend Line By Angle.

Note
For Trend Line By Angle, it is possible to specify the mode of continuation of its display
to the right (OBJPROP_RAY_RIGHT property).
Both angle and the second anchor point's coordinates can be used to set the slope of
the line.
Example
The following script creates and moves the trend line on the chart. Special functions
have been developed to create and change graphical object's properties. You can use
these functions "as is" in your own applications.
#property strict //--- description
#property description "Script draws \"Trend Line By Angle\" graphical object."
#property description "Anchor point coordinates are set in percentage of the size of"
#property description "the chart window."
//--- display window of the input parameters during the script's launch
#property script_show_inputs
//--- input parameters of the script
input string InpName="Trend"; // Line name
input int InpDate1=50; // 1 st point's date, %
input int InpPrice1=75; // 1 st point's price, %
input int InpAngle=0; // Line's slope angle
input color InpColor=clrRed; // Line color
input ENUM_LINE_STYLE InpStyle=STYLE_DASH; // Line style
input int InpWidth=1; // Line width
input bool InpBack=false; // Background line
input bool InpSelection=true; // Highlight to move
input bool InpRayRight=true; // Line's continuation to the right
input bool InpHidden=true; // Hidden in the object list
input long InpZOrder=0; // Priority for mouse click
//+------------------------------------------------------------------+
//| Create a trend line by angle |
//+------------------------------------------------------------------+
bool TrendByAngleCreate(const long chart_ID=0, // chart's ID
const string name="TrendLine", // line name
const int sub_window=0, // subwindow index
datetime time=0, // point time
double price=0, // point price
const double angle=45.0, // slope angle
const color clr=clrRed, // line color
const ENUM_LINE_STYLE style=STYLE_SOLID, // line style
const int width=1, // line width
const bool back=false, // in the background
const bool selection=true, // highlight to move
const bool ray_right=true, // line's continuati
const bool hidden=true, // hidden in the obj
const long z_order=0) // priority for mous
{
//--- create the second point to facilitate dragging the trend line by mouse
datetime time2=0;
double price2=0;
//--- set anchor points' coordinates if they are not set
ChangeTrendEmptyPoints(time,price,time2,price2);
//--- reset the error value
ResetLastError();
//--- create a trend line using 2 points
if(!ObjectCreate(chart_ID,name,OBJ_TRENDBYANGLE,sub_window,time,price,time2,price2
{
Print(__FUNCTION__,
": failed to create a trend line! Error code = ",GetLastError());
return(false);
}
//--- change trend line's slope angle; when changing the angle, coordinates of the se
//--- point of the line are redefined automatically according to the angle's new valu
ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
//--- set line color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set line style
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set line width
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the line by mouse
//--- when creating a graphical object using ObjectCreate function, the object cannot
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- enable (true) or disable (false) the mode of continuation of the line's display
ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,ray_right);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Change trend line anchor point's coordinates |
//+------------------------------------------------------------------+
bool TrendPointChange(const long chart_ID=0, // chart's ID
const string name="TrendLine", // line name
datetime time=0, // anchor point time coordinate
double price=0) // anchor point price coordinate
{
//--- if point position is not set, move it to the current bar having Bid price
if(!time)
time=TimeCurrent();
if(!price)
price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- reset the error value
ResetLastError();
//--- move trend line's anchor point
if(!ObjectMove(chart_ID,name,0,time,price))
{
Print(__FUNCTION__,
": failed to move the anchor point! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Change trend line's slope angle |
//+------------------------------------------------------------------+
bool TrendAngleChange(const long chart_ID=0, // chart's ID
const string name="TrendLine", // trend line name
const double angle=45) // trend line's slope angle
{
//--- reset the error value
ResetLastError();
//--- change trend line's slope angle
if(!ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle))
{
Print(__FUNCTION__,
": failed to change the line's slope angle! Error code = ",GetLastError()
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Delete the trend line |
//+------------------------------------------------------------------+
bool TrendDelete(const long chart_ID=0, // chart's ID
const string name="TrendLine") // line name
{
//--- reset the error value
ResetLastError();
//--- delete a trend line
if(!ObjectDelete(chart_ID,name))
{
Print(__FUNCTION__,
": failed to delete a trend line! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Check the values of trend line's anchor points and set default |
//| values for empty ones |
//+------------------------------------------------------------------+
void ChangeTrendEmptyPoints(datetime &time1,double &price1,
datetime &time2,double &price2)
{
//--- if the first point's time is not set, it will be on the current bar
if(!time1)
time1=TimeCurrent();
//--- if the first point's price is not set, it will have Bid value
if(!price1)
price1=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- set coordinates of the second, auxiliary point
//--- the second point will be 9 bars left and have the same price
datetime second_point_time[10];
CopyTime(Symbol(),Period(),time1,10,second_point_time);
time2=second_point_time[0];
price2=price1;
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- check correctness of the input parameters
if(InpDate1<0 || InpDate1>100 || InpPrice1<0 || InpPrice1>100)
{
Print("Error! Incorrect values of input parameters!");
return;
}
//--- number of visible bars in the chart window
int bars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);
//--- price array size
int accuracy=1000;
//--- arrays for storing the date and price values to be used
//--- for setting and changing line anchor points' coordinates
datetime date[];
double price[];
//--- memory allocation
ArrayResize(date,bars);
ArrayResize(price,accuracy);
//--- fill the array of dates
ResetLastError();
if(CopyTime(Symbol(),Period(),0,bars,date)==-1)
{
Print("Failed to copy time values! Error code = ",GetLastError());
return;
}
//--- fill the array of prices
//--- find the highest and lowest values of the chart
double max_price=ChartGetDouble(0,CHART_PRICE_MAX);
double min_price=ChartGetDouble(0,CHART_PRICE_MIN);
//--- define a change step of a price and fill the array
double step=(max_price-min_price)/accuracy;
for(int i=0;i<accuracy;i++)
price[i]=min_price+i*step;
//--- define points for drawing the line
int d1=InpDate1*(bars-1)/100;
int p1=InpPrice1*(accuracy-1)/100;
//--- create a trend line
if(!TrendByAngleCreate(0,InpName,0,date[d1],price[p1],InpAngle,InpColor,InpStyle,
InpWidth,InpBack,InpSelection,InpRayRight,InpHidden,InpZOrder))
{
return;
}
//--- redraw the chart and wait for 1 second
ChartRedraw();
Sleep(1000);
//--- now, move and rotate the line
//--- loop counter
int v_steps=accuracy/2;
//--- move the anchor point and change the line's slope angle
for(int i=0;i<v_steps;i++)
{
//--- use the following value
if(p1>1)
p1-=1;
//--- move the point
if(!TrendPointChange(0,InpName,date[d1],price[p1]))
return;
if(!TrendAngleChange(0,InpName,18*(i+1)))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
}
//--- 1 second of delay
Sleep(1000);
//--- delete from the chart
TrendDelete(0,InpName);
ChartRedraw();
//--- 1 second of delay
Sleep(1000);
//---
}
MQL4 Reference / Constants, Enumerations and Structures / Objects Constants / Object Types / OBJ_CYCLES

OBJ_CYCLES
Cycle Lines.

Note
The distance between the lines is set by time coordinates of two anchor points of the
object.
Example
The following script creates and moves cycle lines on the chart. Special functions have
been developed to create and change graphical object's properties. You can use these
functions "as is" in your own applications.
#property strict //--- description
#property description "Script creates cycle lines on the chart."
#property description "Anchor point coordinates are set in percentage"
#property description "percentage of the chart window size."
//--- display window of the input parameters during the script's launch
#property script_show_inputs
//--- input parameters of the script
input string InpName="Cycles"; // Object name
input int InpDate1=10; // 1 st point's date, %
input int InpPrice1=45; // 1 st point's price, %
input int InpDate2=20; // 2 nd point's date, %
input int InpPrice2=55; // 2 nd point's price, %
input color InpColor=clrRed; // Color of cycle lines
input ENUM_LINE_STYLE InpStyle=STYLE_DOT; // Style of cycle lines
input int InpWidth=1; // Width of cycle lines
input bool InpBack=false; // Background object
input bool InpSelection=true; // Highlight to move
input bool InpHidden=true; // Hidden in the object list
input long InpZOrder=0; // Priority for mouse click
//+------------------------------------------------------------------+
//| Create cycle lines |
//+------------------------------------------------------------------+
bool CyclesCreate(const long chart_ID=0, // chart's ID
const string name="Cycles", // object name
const int sub_window=0, // subwindow index
datetime time1=0, // first point time
double price1=0, // first point price
datetime time2=0, // second point time
double price2=0, // second point price
const color clr=clrRed, // color of cycle lines
const ENUM_LINE_STYLE style=STYLE_SOLID, // style of cycle lines
const int width=1, // width of cycle lines
const bool back=false, // in the background
const bool selection=true, // highlight to move
const bool hidden=true, // hidden in the object li
const long z_order=0) // priority for mouse clic
{
//--- set anchor points' coordinates if they are not set
ChangeCyclesEmptyPoints(time1,price1,time2,price2);
//--- reset the error value
ResetLastError();
//--- create cycle lines by the given coordinates
if(!ObjectCreate(chart_ID,name,OBJ_CYCLES,sub_window,time1,price1,time2,price2))
{
Print(__FUNCTION__,
": failed to create cycle lines! Error code = ",GetLastError());
return(false);
}
//--- set color of the lines
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set display style of the lines
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set width of the lines
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the lines by mouse
//--- when creating a graphical object using ObjectCreate function, the object cannot
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Move the anchor point |
//+------------------------------------------------------------------+
bool CyclesPointChange(const long chart_ID=0, // chart's ID
const string name="Cycles", // object name
const int point_index=0, // anchor point index
datetime time=0, // anchor point time coordinate
double price=0) // anchor point price coordinate
{
//--- if point position is not set, move it to the current bar having Bid price
if(!time)
time=TimeCurrent();
if(!price)
price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- reset the error value
ResetLastError();
//--- move the anchor point
if(!ObjectMove(chart_ID,name,point_index,time,price))
{
Print(__FUNCTION__,
": failed to move the anchor point! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Delete the cycle lines |
//+------------------------------------------------------------------+
bool CyclesDelete(const long chart_ID=0, // chart's ID
const string name="Cycles") // object name
{
//--- reset the error value
ResetLastError();
//--- delete cycle lines
if(!ObjectDelete(chart_ID,name))
{
Print(__FUNCTION__,
": failed to delete cycle lines! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+-----------------------------------------------------------------------+
//| Check the values of cycle lines' anchor points and set default values |
//| values for empty ones |
//+-----------------------------------------------------------------------+
void ChangeCyclesEmptyPoints(datetime &time1,double &price1,
datetime &time2,double &price2)
{
//--- if the first point's time is not set, it will be on the current bar
if(!time1)
time1=TimeCurrent();
//--- if the first point's price is not set, it will have Bid value
if(!price1)
price1=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- if the second point's time is not set, it is located 9 bars left from the secon
if(!time2)
{
//--- array for receiving the open time of the last 10 bars
datetime temp[10];
CopyTime(Symbol(),Period(),time1,10,temp);
//--- set the second point 9 bars left from the first one
time2=temp[0];
}
//--- if the second point's price is not set, it is equal to the first point's one
if(!price2)
price2=price1;
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- check correctness of the input parameters
if(InpDate1<0 || InpDate1>100 || InpPrice1<0 || InpPrice1>100 ||
InpDate2<0 || InpDate2>100 || InpPrice2<0 || InpPrice2>100)
{
Print("Error! Incorrect values of input parameters!");
return;
}
//--- number of visible bars in the chart window
int bars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);
//--- price array size
int accuracy=1000;
//--- arrays for storing the date and price values to be used
//--- for setting and changing the coordinates of cycle lines' anchor points
datetime date[];
double price[];
//--- memory allocation
ArrayResize(date,bars);
ArrayResize(price,accuracy);
//--- fill the array of dates
ResetLastError();
if(CopyTime(Symbol(),Period(),0,bars,date)==-1)
{
Print("Failed to copy time values! Error code = ",GetLastError());
return;
}
//--- fill the array of prices
//--- find the highest and lowest values of the chart
double max_price=ChartGetDouble(0,CHART_PRICE_MAX);
double min_price=ChartGetDouble(0,CHART_PRICE_MIN);
//--- define a change step of a price and fill the array
double step=(max_price-min_price)/accuracy;
for(int i=0;i<accuracy;i++)
price[i]=min_price+i*step;
//--- define points for drawing cycle lines
int d1=InpDate1*(bars-1)/100;
int d2=InpDate2*(bars-1)/100;
int p1=InpPrice1*(accuracy-1)/100;
int p2=InpPrice2*(accuracy-1)/100;
//--- create a trend line
if(!CyclesCreate(0,InpName,0,date[d1],price[p1],date[d2],price[p2],InpColor,
InpStyle,InpWidth,InpBack,InpSelection,InpHidden,InpZOrder))
{
return;
}
//--- redraw the chart and wait for 1 second
ChartRedraw();
Sleep(1000);
//--- now, move the anchor points
//--- loop counter
int h_steps=bars/5;
//--- move the second anchor point
for(int i=0;i<h_steps;i++)
{
//--- use the following value
if(d2<bars-1)
d2+=1;
//--- move the point
if(!CyclesPointChange(0,InpName,1,date[d2],price[p2]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
// 0.05 seconds of delay
Sleep(50);
}
//--- 1 second of delay
Sleep(1000);
//--- loop counter
h_steps=bars/4;
//--- move the first anchor point
for(int i=0;i<h_steps;i++)
{
//--- use the following value
if(d1<bars-1)
d1+=1;
//--- move the point
if(!CyclesPointChange(0,InpName,0,date[d1],price[p1]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
// 0.05 seconds of delay
Sleep(50);
}
//--- 1 second of delay
Sleep(1000);
//--- delete the object from the chart
CyclesDelete(0,InpName);
ChartRedraw();
//--- 1 second of delay
Sleep(1000);
//---
}
MQL4 Reference / Constants, Enumerations and Structures / Objects Constants / Object Types / OBJ_CHANNEL

OBJ_CHANNEL
Equidistant Channel

Note
For an equidistant channel, it is possible to specify the mode of its continuation to the
right (OBJPROP_RAY_RIGHT property). The mode of filling the channel with color can
also be set.
Example
The following script creates and moves an equidistant channel on the chart. Special
functions have been developed to create and change graphical object's properties. You
can use these functions "as is" in your own applications.
#property strict //--- description
#property description "Script draws \"Equidistant Channel\" graphical object."
#property description "Anchor point coordinates are set in percentage of the size of"
#property description "the chart window."
//--- display window of the input parameters during the script's launch
#property script_show_inputs
//--- input parameters of the script
input string InpName="Channel"; // Channel name
input int InpDate1=25; // 1 st point's date, %
input int InpPrice1=60; // 1 st point's price, %
input int InpDate2=65; // 2 nd point's date, %
input int InpPrice2=80; // 2 nd point's price, %
input int InpDate3=30; // 3 rd point's date, %
input int InpPrice3=40; // 3 rd point's date, %
input color InpColor=clrRed; // Channel color
input ENUM_LINE_STYLE InpStyle=STYLE_DASH; // Style of channel lines
input int InpWidth=1; // Channel line width
input bool InpBack=false; // Background channel
input bool InpFill=false; // Filling the channel with color
input bool InpSelection=true; // Highlight to move
input bool InpRayRight=false; // Channel's continuation to the right
input bool InpHidden=true; // Hidden in the object list
input long InpZOrder=0; // Priority for mouse click
//+------------------------------------------------------------------+
//| Create an equidistant channel by the given coordinates |
//+------------------------------------------------------------------+
bool ChannelCreate(const long chart_ID=0, // chart's ID
const string name="Channel", // channel name
const int sub_window=0, // subwindow index
datetime time1=0, // first point time
double price1=0, // first point price
datetime time2=0, // second point time
double price2=0, // second point price
datetime time3=0, // third point time
double price3=0, // third point price
const color clr=clrRed, // channel color
const ENUM_LINE_STYLE style=STYLE_SOLID, // style of channel lines
const int width=1, // width of channel lines
const bool fill=false, // filling the channel wi
const bool back=false, // in the background
const bool selection=true, // highlight to move
const bool ray_right=false, // channel's continuation
const bool hidden=true, // hidden in the object l
const long z_order=0) // priority for mouse cli
{
//--- set anchor points' coordinates if they are not set
ChangeChannelEmptyPoints(time1,price1,time2,price2,time3,price3);
//--- reset the error value
ResetLastError();
//--- create a channel by the given coordinates
if(!ObjectCreate(chart_ID,name,OBJ_CHANNEL,sub_window,time1,price1,time2,price2,ti
{
Print(__FUNCTION__,
": failed to create an equidistant channel! Error code = ",GetLastError()
return(false);
}
//--- set channel color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set style of the channel lines
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set width of the channel lines
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of highlighting the channel for movin
//--- when creating a graphical object using ObjectCreate function, the object cannot
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- enable (true) or disable (false) the mode of continuation of the channel's disp
ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,ray_right);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Move the channel's anchor point |
//+------------------------------------------------------------------+
bool ChannelPointChange(const long chart_ID=0, // chart's ID
const string name="Channel", // channel name
const int point_index=0, // anchor point index
datetime time=0, // anchor point time coordinate
double price=0) // anchor point price coordinate
{
//--- if point position is not set, move it to the current bar having Bid price
if(!time)
time=TimeCurrent();
if(!price)
price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- reset the error value
ResetLastError();
//--- move the anchor point
if(!ObjectMove(chart_ID,name,point_index,time,price))
{
Print(__FUNCTION__,
": failed to move the anchor point! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Delete the channel |
//+------------------------------------------------------------------+
bool ChannelDelete(const long chart_ID=0, // chart's ID
const string name="Channel") // channel name
{
//--- reset the error value
ResetLastError();
//--- delete the channel
if(!ObjectDelete(chart_ID,name))
{
Print(__FUNCTION__,
": failed to delete the channel! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+-------------------------------------------------------------------------+
//| Check the values of the channel's anchor points and set default values |
//| for empty ones |
//+-------------------------------------------------------------------------+
void ChangeChannelEmptyPoints(datetime &time1,double &price1,datetime &time2,
double &price2,datetime &time3,double &price3)
{
//--- if the second (right) point's time is not set, it will be on the current bar
if(!time2)
time2=TimeCurrent();
//--- if the second point's price is not set, it will have Bid value
if(!price2)
price2=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- if the first (left) point's time is not set, it is located 9 bars left from the
if(!time1)
{
//--- array for receiving the open time of the last 10 bars
datetime temp[10];
CopyTime(Symbol(),Period(),time2,10,temp);
//--- set the first point 9 bars left from the second one
time1=temp[0];
}
//--- if the first point's price is not set, move it 300 points higher than the secon
if(!price1)
price1=price2+300*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
//--- if the third point's time is not set, it coincides with the first point's one
if(!time3)
time3=time1;
//--- if the third point's price is not set, it is equal to the second point's one
if(!price3)
price3=price2;
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- check correctness of the input parameters
if(InpDate1<0 || InpDate1>100 || InpPrice1<0 || InpPrice1>100 ||
InpDate2<0 || InpDate2>100 || InpPrice2<0 || InpPrice2>100 ||
InpDate3<0 || InpDate3>100 || InpPrice3<0 || InpPrice3>100)
{
Print("Error! Incorrect values of input parameters!");
return;
}
//--- number of visible bars in the chart window
int bars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);
//--- price array size
int accuracy=1000;
//--- arrays for storing the date and price values to be used
//--- for setting and changing channel anchor points' coordinates
datetime date[];
double price[];
//--- memory allocation
ArrayResize(date,bars);
ArrayResize(price,accuracy);
//--- fill the array of dates
ResetLastError();
if(CopyTime(Symbol(),Period(),0,bars,date)==-1)
{
Print("Failed to copy time values! Error code = ",GetLastError());
return;
}
//--- fill the array of prices
//--- find the highest and lowest values of the chart
double max_price=ChartGetDouble(0,CHART_PRICE_MAX);
double min_price=ChartGetDouble(0,CHART_PRICE_MIN);
//--- define a change step of a price and fill the array
double step=(max_price-min_price)/accuracy;
for(int i=0;i<accuracy;i++)
price[i]=min_price+i*step;
//--- define points for drawing the channel
int d1=InpDate1*(bars-1)/100;
int d2=InpDate2*(bars-1)/100;
int d3=InpDate3*(bars-1)/100;
int p1=InpPrice1*(accuracy-1)/100;
int p2=InpPrice2*(accuracy-1)/100;
int p3=InpPrice3*(accuracy-1)/100;
//--- create the equidistant channel
if(!ChannelCreate(0,InpName,0,date[d1],price[p1],date[d2],price[p2],date[d3],price
InpStyle,InpWidth,InpFill,InpBack,InpSelection,InpRayRight,InpHidden,InpZOrder)
{
return;
}
//--- redraw the chart and wait for 1 second
ChartRedraw();
Sleep(1000);
//--- now, move the channel's anchor points
//--- loop counter
int h_steps=bars/6;
//--- move the second anchor point
for(int i=0;i<h_steps;i++)
{
//--- use the following value
if(d2<bars-1)
d2+=1;
//--- move the point
if(!ChannelPointChange(0,InpName,1,date[d2],price[p2]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
// 0.05 seconds of delay
Sleep(50);
}
//--- 1 second of delay
Sleep(1000);
//--- move the first anchor point
for(int i=0;i<h_steps;i++)
{
//--- use the following value
if(d1>1)
d1-=1;
//--- move the point
if(!ChannelPointChange(0,InpName,0,date[d1],price[p1]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
// 0.05 seconds of delay
Sleep(50);
}
//--- 1 second of delay
Sleep(1000);
//--- loop counter
int v_steps=accuracy/10;
//--- move the third anchor point
for(int i=0;i<v_steps;i++)
{
//--- use the following value
if(p3>1)
p3-=1;
//--- move the point
if(!ChannelPointChange(0,InpName,2,date[d3],price[p3]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
}
//--- 1 second of delay
Sleep(1000);
//--- delete the channel from the chart
ChannelDelete(0,InpName);
ChartRedraw();
//--- 1 second of delay
Sleep(1000);
//---
}
MQL4 Reference / Constants, Enumerations and Structures / Objects Constants / Object Types /
OBJ_STDDEVCHANNEL

OBJ_STDDEVCHANNEL
Standard Deviation Channel.

Note
For Standard Deviation Channel, it is possible to specify the mode of continuation of its
display to the right (OBJPROP_RAY_RIGHT property). The mode of filling the channel
with color can also be set.
OBJPROP_DEVIATION property is used to change the value of the channel deviation.
Example
The following script creates and moves Standard Deviation Channel on the chart.
Special functions have been developed to create and change graphical object's
properties. You can use these functions "as is" in your own applications.
#property strict //--- description
#property description "Script draws \"Standard Deviation Channel\" graphical object."
#property description "Anchor point coordinates are set in percentage of the size of"
#property description "the chart window."
//--- display window of the input parameters during the script's launch
#property script_show_inputs
//--- input parameters of the script
input string InpName="StdDevChannel"; // Channel name
input int InpDate1=10; // 1 st point's date, %
input int InpDate2=40; // 2 nd point's date, %
input double InpDeviation=1.0; // Deviation
input color InpColor=clrRed; // Channel color
input ENUM_LINE_STYLE InpStyle=STYLE_DASHDOTDOT; // Style of channel lines
input int InpWidth=1; // Width of channel lines
input bool InpFill=false; // Filling the channel with color
input bool InpBack=false; // Background channel
input bool InpSelection=true; // Highlight to move
input bool InpRayRight=false; // Channel's continuation to the rig
input bool InpHidden=true; // Hidden in the object list
input long InpZOrder=0; // Priority for mouse click
//+------------------------------------------------------------------+
//| Create standard deviation channel by the given coordinates |
//+------------------------------------------------------------------+
bool StdDevChannelCreate(const long chart_ID=0, // chart's ID
const string name="Channel", // channel name
const int sub_window=0, // subwindow index
datetime time1=0, // first point time
datetime time2=0, // second point tim
const double deviation=1.0, // deviation
const color clr=clrRed, // channel color
const ENUM_LINE_STYLE style=STYLE_SOLID, // style of channel
const int width=1, // width of channel
const bool fill=false, // filling the chan
const bool back=false, // in the backgroun
const bool selection=true, // highlight to mov
const bool ray_right=false, // channel's contin
const bool hidden=true, // hidden in the ob
const long z_order=0) // priority for mou
{
//--- set anchor points' coordinates if they are not set
ChangeChannelEmptyPoints(time1,time2);
//--- reset the error value
ResetLastError();
//--- create a channel by the given coordinates
if(!ObjectCreate(chart_ID,name,OBJ_STDDEVCHANNEL,sub_window,time1,0,time2,0))
{
Print(__FUNCTION__,
": failed to create standard deviation channel! Error code = ",GetLastErr
return(false);
}
//--- set deviation value affecting the channel width
ObjectSetDouble(chart_ID,name,OBJPROP_DEVIATION,deviation);
//--- set channel color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set style of the channel lines
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set width of the channel lines
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of highlighting the channel for movin
//--- when creating a graphical object using ObjectCreate function, the object cannot
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- enable (true) or disable (false) the mode of continuation of the channel's disp
ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,ray_right);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Move the channel's anchor point |
//+------------------------------------------------------------------+
bool StdDevChannelPointChange(const long chart_ID=0, // chart's ID
const string name="Channel", // channel name
const int point_index=0, // anchor point index
datetime time=0) // anchor point time coord
{
//--- if point time is not set, move the point to the current bar
if(!time)
time=TimeCurrent();
//--- reset the error value
ResetLastError();
//--- move the anchor point
if(!ObjectMove(chart_ID,name,point_index,time,0))
{
Print(__FUNCTION__,
": failed to move the anchor point! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Change the channel's deviation |
//+------------------------------------------------------------------+
bool StdDevChannelDeviationChange(const long chart_ID=0, // chart's ID
const string name="Channel", // channel name
const double deviation=1.0) // deviation
{
//--- reset the error value
ResetLastError();
//--- change trend line's slope angle
if(!ObjectSetDouble(chart_ID,name,OBJPROP_DEVIATION,deviation))
{
Print(__FUNCTION__,
": failed to change channel deviation! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Delete the channel |
//+------------------------------------------------------------------+
bool StdDevChannelDelete(const long chart_ID=0, // chart's ID
const string name="Channel") // channel name
{
//--- reset the error value
ResetLastError();
//--- delete the channel
if(!ObjectDelete(chart_ID,name))
{
Print(__FUNCTION__,
": failed to delete the channel! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+-------------------------------------------------------------------------+
//| Check the values of the channel's anchor points and set default values |
//| for empty ones |
//+-------------------------------------------------------------------------+
void ChangeChannelEmptyPoints(datetime &time1,datetime &time2)
{
//--- if the second point's time is not set, it will be on the current bar
if(!time2)
time2=TimeCurrent();
//--- if the first point's time is not set, it is located 9 bars left from the second
if(!time1)
{
//--- array for receiving the open time of the last 10 bars
datetime temp[10];
CopyTime(Symbol(),Period(),time2,10,temp);
//--- set the first point 9 bars left from the second one
time1=temp[0];
}
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- check correctness of the input parameters
if(InpDate1<0 || InpDate1>100 ||
InpDate2<0 || InpDate2>100)
{
Print("Error! Incorrect values of input parameters!");
return;
}
//--- number of visible bars in the chart window
int bars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);
//--- price array size
int accuracy=1000;
//--- arrays for storing the date and price values to be used
//--- for setting and changing channel anchor points' coordinates
datetime date[];
double price[];
//--- memory allocation
ArrayResize(date,bars);
ArrayResize(price,accuracy);
//--- fill the array of dates
ResetLastError();
if(CopyTime(Symbol(),Period(),0,bars,date)==-1)
{
Print("Failed to copy time values! Error code = ",GetLastError());
return;
}
//--- fill the array of prices
//--- find the highest and lowest values of the chart
double max_price=ChartGetDouble(0,CHART_PRICE_MAX);
double min_price=ChartGetDouble(0,CHART_PRICE_MIN);
//--- define a change step of a price and fill the array
double step=(max_price-min_price)/accuracy;
for(int i=0;i<accuracy;i++)
price[i]=min_price+i*step;
//--- define points for drawing the channel
int d1=InpDate1*(bars-1)/100;
int d2=InpDate2*(bars-1)/100;
//--- create standard deviation channel
if(!StdDevChannelCreate(0,InpName,0,date[d1],date[d2],InpDeviation,InpColor,InpSty
InpWidth,InpFill,InpBack,InpSelection,InpRayRight,InpHidden,InpZOrder))
{
return;
}
//--- redraw the chart and wait for 1 second
ChartRedraw();
Sleep(1000);
//--- now, move the channel horizontally to the right and expand it
//--- loop counter
int h_steps=bars/2;
//--- move the channel
for(int i=0;i<h_steps;i++)
{
//--- use the following values
if(d1<bars-1)
d1+=1;
if(d2<bars-1)
d2+=1;
//--- move the anchor points
if(!StdDevChannelPointChange(0,InpName,0,date[d1]))
return;
if(!StdDevChannelPointChange(0,InpName,1,date[d2]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
// 0.05 seconds of delay
Sleep(50);
}
//--- 1 second of delay
Sleep(1000);
//--- loop counter
double v_steps=InpDeviation*2;
//--- expand the channel
for(double i=InpDeviation;i<v_steps;i+=10.0/accuracy)
{
if(!StdDevChannelDeviationChange(0,InpName,i))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
}
//--- 1 second of delay
Sleep(1000);
//--- delete the channel from the chart
StdDevChannelDelete(0,InpName);
ChartRedraw();
//--- 1 second of delay
Sleep(1000);
//---
}
MQL4 Reference / Constants, Enumerations and Structures / Objects Constants / Object Types /
OBJ_REGRESSION

OBJ_REGRESSION
Linear Regression Channel.

Note
For Linear Regression Channel, it is possible to specify the mode of continuation of its
display to the right (OBJPROP_RAY_RIGHT property). The mode of filling the channel
with color can also be set.
Example
The following script creates and moves Linear Regression Channel on the chart. Special
functions have been developed to create and change graphical object's properties. You
can use these functions "as is" in your own applications.
#property strict //--- description
#property description "Script draws \"Linear Regression Channel\" graphical object."
#property description "Anchor point coordinates are set in percentage of the size of"
#property description "the chart window."
//--- display window of the input parameters during the script's launch
#property script_show_inputs
//--- input parameters of the script
input string InpName="Regression"; // Channel name
input int InpDate1=10; // 1 st point's date, %
input int InpDate2=40; // 2 nd point's date, %
input color InpColor=clrRed; // Channel color
input ENUM_LINE_STYLE InpStyle=STYLE_DASH; // Style of channel lines
input int InpWidth=1; // Width of channel lines
input bool InpFill=false; // Filling the channel with color
input bool InpBack=false; // Background channel
input bool InpSelection=true; // Highlight to move
input bool InpRayRight=false; // Channel's continuation to the right
input bool InpHidden=true; // Hidden in the object list
input long InpZOrder=0; // Priority for mouse click
//+------------------------------------------------------------------+
//| Create Linear Regression Channel by the given coordinates |
//+------------------------------------------------------------------+
bool RegressionCreate(const long chart_ID=0, // chart's ID
const string name="Regression", // channel name
const int sub_window=0, // subwindow index
datetime time1=0, // first point time
datetime time2=0, // second point time
const color clr=clrRed, // channel color
const ENUM_LINE_STYLE style=STYLE_SOLID, // style of channel li
const int width=1, // width of channel li
const bool fill=false, // filling the channel
const bool back=false, // in the background
const bool selection=true, // highlight to move
const bool ray_right=false, // channel's continuat
const bool hidden=true, // hidden in the objec
const long z_order=0) // priority for mouse
{
//--- set anchor points' coordinates if they are not set
ChangeRegressionEmptyPoints(time1,time2);
//--- reset the error value
ResetLastError();
//--- create a channel by the given coordinates
if(!ObjectCreate(chart_ID,name,OBJ_REGRESSION,sub_window,time1,0,time2,0))
{
Print(__FUNCTION__,
": failed to create linear regression channel! Error code = ",GetLastErro
return(false);
}
//--- set channel color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set style of the channel lines
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set width of the channel lines
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of highlighting the channel for movin
//--- when creating a graphical object using ObjectCreate function, the object cannot
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- enable (true) or disable (false) the mode of continuation of the channel's disp
ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,ray_right);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Move the channel's anchor point |
//+------------------------------------------------------------------+
bool RegressionPointChange(const long chart_ID=0, // chart's ID
const string name="Channel", // channel name
const int point_index=0, // anchor point index
datetime time=0) // anchor point time coordina
{
//--- if point time is not set, move the point to the current bar
if(!time)
time=TimeCurrent();
//--- reset the error value
ResetLastError();
//--- move the anchor point
if(!ObjectMove(chart_ID,name,point_index,time,0))
{
Print(__FUNCTION__,
": failed to move the anchor point! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Delete the channel |
//+------------------------------------------------------------------+
bool RegressionDelete(const long chart_ID=0, // chart's ID
const string name="Channel") // channel name
{
//--- reset the error value
ResetLastError();
//--- delete the channel
if(!ObjectDelete(chart_ID,name))
{
Print(__FUNCTION__,
": failed to delete the channel! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+-------------------------------------------------------------------------+
//| Check the values of the channel's anchor points and set default values |
//| for empty ones |
//+-------------------------------------------------------------------------+
void ChangeRegressionEmptyPoints(datetime &time1,datetime &time2)
{
//--- if the second point's time is not set, it will be on the current bar
if(!time2)
time2=TimeCurrent();
//--- if the first point's time is not set, it is located 9 bars left from the second
if(!time1)
{
//--- array for receiving the open time of the last 10 bars
datetime temp[10];
CopyTime(Symbol(),Period(),time2,10,temp);
//--- set the first point 9 bars left from the second one
time1=temp[0];
}
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- check correctness of the input parameters
if(InpDate1<0 || InpDate1>100 ||
InpDate2<0 || InpDate2>100)
{
Print("Error! Incorrect values of input parameters!");
return;
}
//--- number of visible bars in the chart window
int bars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);
//--- price array size
int accuracy=1000;
//--- arrays for storing the date and price values to be used
//--- for setting and changing channel anchor points' coordinates
datetime date[];
double price[];
//--- memory allocation
ArrayResize(date,bars);
ArrayResize(price,accuracy);
//--- fill the array of dates
ResetLastError();
if(CopyTime(Symbol(),Period(),0,bars,date)==-1)
{
Print("Failed to copy time values! Error code = ",GetLastError());
return;
}
//--- fill the array of prices
//--- find the highest and lowest values of the chart
double max_price=ChartGetDouble(0,CHART_PRICE_MAX);
double min_price=ChartGetDouble(0,CHART_PRICE_MIN);
//--- define a change step of a price and fill the array
double step=(max_price-min_price)/accuracy;
for(int i=0;i<accuracy;i++)
price[i]=min_price+i*step;
//--- define points for drawing the channel
int d1=InpDate1*(bars-1)/100;
int d2=InpDate2*(bars-1)/100;
//--- create linear regression channel
if(!RegressionCreate(0,InpName,0,date[d1],date[d2],InpColor,InpStyle,InpWidth,
InpFill,InpBack,InpSelection,InpRayRight,InpHidden,InpZOrder))
{
return;
}
//--- redraw the chart and wait for 1 second
ChartRedraw();
Sleep(1000);
//--- now, the channel horizontally to the right
//--- loop counter
int h_steps=bars/2;
//--- move the channel
for(int i=0;i<h_steps;i++)
{
//--- use the following values
if(d1<bars-1)
d1+=1;
if(d2<bars-1)
d2+=1;
//--- move the anchor points
if(!RegressionPointChange(0,InpName,0,date[d1]))
return;
if(!RegressionPointChange(0,InpName,1,date[d2]))
return;
//--- check if the script's operation has been forcefully disabled
if(IsStopped())
return;
//--- redraw the chart
ChartRedraw();
// 0.05 seconds of delay
Sleep(50);
}
//--- 1 second of delay
Sleep(1000);
//--- delete the channel from the chart
RegressionDelete(0,InpName);
ChartRedraw();
//--- 1 second of delay
Sleep(1000);
//---
}
MQL4 Reference / Constants, Enumerations and Structures / Objects Constants / Object Types / OBJ_PITCHFORK

OBJ_PITCHFORK
Andrews Pitchfork.

Note
For Andrews Pitchfork, it is possible to specify the mode of continuation of its display
to the right (OBJPROP_RAY_RIGHT property).
You can also specify the number of line-levels, their values and color.
Example
The following script creates and moves Andrews Pitchfork on the chart. Special
functions have been developed to create and change graphical object's properties. You
can use these functions "as is" in your own applications.
#property strict //--- description
#property description "Script draws \"Andrews Pitchfork\" graphical object."
#property description "Anchor point coordinates are set in percentage of"
#property description "the chart window size."
//--- display window of the input parameters during the script's launch
#property script_show_inputs
//--- input parameters of the script
input string InpName="Pitchfork"; // Pitchfork name
input int InpDate1=14; // 1 st point's date, %
input int InpPrice1=40; // 1 st point's price, %
input int InpDate2=18; // 2 nd point's date, %
input int InpPrice2=50; // 2 nd point's price, %
input int InpDate3=18; // 3 rd point's date, %
input int InpPrice3=30; // 3 rd point's price, %
input color InpColor=clrRed; // Pitchfork color
input ENUM_LINE_STYLE InpStyle=STYLE_SOLID; // Style of pitchfork lines
input int InpWidth=1; // Width of pitchfork lines
input bool InpBack=false; // Background pitchfork
input bool InpSelection=true; // Highlight to move
input bool InpRayRight=false; // Pitchfork's continuation to the right
input bool InpHidden=true; // Hidden in the object list
input long InpZOrder=0; // Priority for mouse click
//+------------------------------------------------------------------+
//| Create Andrews' Pitchfork by the given coordinates |
//+------------------------------------------------------------------+
bool PitchforkCreate(const long chart_ID=0, // chart's ID
const string name="Pitchfork", // pitchfork name
const int sub_window=0, // subwindow index
datetime time1=0, // first point time
double price1=0, // first point price
datetime time2=0, // second point time
double price2=0, // second point price
datetime time3=0, // third point time
double price3=0, // third point price
const color clr=clrRed, // color of pitchfork l
const ENUM_LINE_STYLE style=STYLE_SOLID, // style of pitchfork l
const int width=1, // width of pitchfork l
const bool back=false, // in the background
const bool selection=true, // highlight to move
const bool ray_right=false, // pitchfork's continua
const bool hidden=true, // hidden in the object
const long z_order=0) // priority for mouse c
{
//--- set anchor points' coordinates if they are not set
ChangeChannelEmptyPoints(time1,price1,time2,price2,time3,price3);
//--- reset the error value
ResetLastError();
//--- create Andrews' Pitchfork by the given coordinates
if(!ObjectCreate(chart_ID,name,OBJ_PITCHFORK,sub_window,time1,price1,time2,price2,
{
Print(__FUNCTION__,
": failed to create \"Andrews' Pitchfork\"! Error code = ",GetLastError()
return(false);
}
//--- set color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set the line style
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set width of the lines
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of highlighting the pitchfork for mov
//--- when creating a graphical object using ObjectCreate function, the object cannot
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- enable (true) or disable (false) the mode of continuation of the pitchfork's di
ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,ray_right);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Move Andrews' Pitchfork anchor point |
//+------------------------------------------------------------------+
bool PitchforkPointChange(const long chart_ID=0, // chart's ID
const string name="Pitchfork", // channel name
const int point_index=0, // anchor point index
datetime time=0, // anchor point time coordin
double price=0) // anchor point price coordi
{
//--- if point position is not set, move it to the current bar having Bid price
if(!time)
time=TimeCurrent();
if(!price)
price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- reset the error value
ResetLastError();
//--- move the anchor point
if(!ObjectMove(chart_ID,name,point_index,time,price))
{
Print(__FUNCTION__,
": failed to move the anchor point! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Delete Andrews Pitchfork |
//+------------------------------------------------------------------+
bool PitchforkDelete(const long chart_ID=0, // chart's ID
const string name="Pitchfork") // channel name
{
//--- reset the error value
ResetLastError();
//--- delete the channel
if(!ObjectDelete(chart_ID,name))
{
Print(__FUNCTION__,
": failed to delete \"Andrews' Pitchfork\"! Error code = ",GetLastError()
return(false);
}
//--- successful execution
return(true);
}
//+----------------------------------------------------------------------+
//| Check the values of Andrews' Pitchfork anchor points and set default |
//| values for empty ones |
//+----------------------------------------------------------------------+
void ChangeChannelEmptyPoints(datetime &time1,double &price1,datetime &time2,
double &price2,datetime &time3,double &price3)
{
//--- if the second (upper right) point's time is not set, it will be on the current
if(!time2)
time2=TimeCurrent();
//--- if the second point's price is not set, it will have Bid value
if(!price2)
price2=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- if the first (left) point's time is not set, it is located 9 bars left from the
if(!time1)
{
//--- array for receiving the open time of the last 10 bars
datetime temp[10];
CopyTime(Symbol(),Period(),time2,10,temp);
//--- set the first point 9 bars left from the second one
time1=temp[0];
}
//--- if the first point's price is not set, move it 200 points below the second one
if(!price1)
price1=price2-200*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
//--- if the third point's time is not set, it coincides with the second point's one
if(!time3)
time3=time2;
//--- if the third point's price is not set, move it 200 points lower than the first
if(!price3)
price3=price1-200*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
}
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- check correctness of the input parameters
if(InpDate1<0 || InpDate1>100 || InpPrice1<0 || InpPrice1>100 ||
InpDate2<0 || InpDate2>100 || InpPrice2<0 || InpPrice2>100 ||
InpDate3<0 || InpDate3>100 || InpPrice3<0 || InpPrice3>100)
{
Print("Error! Incorrect values of input parameters!");
return;
}
//--- number of visible bars in the chart window
int bars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);
//--- price array size
int accuracy=1000;
//--- arrays for storing the date and price values to be used
//--- for setting and changing the coordinates of Andrews' Pitchfork anchor points
datetime date[];
double price[];
//--- memory allocation
ArrayResize(date,bars);
ArrayResize(price,accuracy);
//--- fill the array of dates
ResetLastError();
if(CopyTime(Symbol(),Period(),0,bars,date)==-1)
{
Print("Failed to copy time values! Error code = ",GetLastError());
return;
}
//--- fill the array of prices
//--- find the highest and lowest values of the chart
double max_price=ChartGetDouble(0,CHART_PRICE_MAX);
double min_price=ChartGetDouble(0,CHART_PRICE_MIN);
//--- define a change step of a price and fill the array
double step=(max_price-min_price)/accuracy;
for(int i=0;i<accuracy;i++)
price[i]=min_price+i*step;
//--- define points for drawing Andrews' Pitchfork
int d1=InpDate1*(bars-1)/100;
int d2=InpDate2*(bars-1)/100;
int d3=InpDate3*(bars-1)/100;
int p1=InpPrice1*(accuracy-1)/100;
int p2=InpPrice2*(accuracy-1)/100;
int p3=InpPrice3*(accuracy-1)/100;
//--- create the pitchfork
if(!PitchforkCreate(0,InpName,0,date[d1],price[p1],date[d2],price[p2],date[d3],pri
InpColor,InpStyle,InpWidth,InpBack,InpSelection,InpRayRight,InpHidden,InpZOrder
{
return;
}
//--- redraw the chart and wait for