Why [ MetaTrader 4 ] can't write/open a file in windows 10 with the FileWrite() function? - mql4

I tried implementing the solutions from this post
Cannot open file on Ubuntu
But to no avail. I keep getting a 5002 error. (failed to open file) after FileWrite()
Even when I try out the example script on https://docs.mql4.com/files/filewrite
I get the same error. I tried running MetaTrader Terminal 4 in administrator mode but to no avail either.Does anyone know a solution to this?
#property version "1.00"
#property strict
//--- show the window of input parameters when launching the script
#property script_show_inputs
//--- parameters for receiving data from the terminal
input string InpSymbolName = "EURUSD"; // Сurrency pair
input ENUM_TIMEFRAMES InpSymbolPeriod = PERIOD_H1; // Time frame
input int InpFastEMAPeriod = 12; // Fast EMA period
input int InpSlowEMAPeriod = 26; // Slow EMA period
input int InpSignalPeriod = 9; // Difference averaging period
input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; // Price type
//--- parameters for writing data to file
input string InpFileName = "MACD.csv"; // File name
input string InpDirectoryName = "Data"; // Folder name
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
bool sign_buff[]; // signal array (true - buy, false - sell)
datetime time_buff[]; // array of signals' appear time
int sign_size=0; // signal array size
double macd_buff[]; // array of indicator values
datetime date_buff[]; // array of indicator dates
int macd_size=0; // size of indicator arrays
//--- set indexing as time series
ArraySetAsSeries( sign_buff, true );
ArraySetAsSeries( time_buff, true );
ArraySetAsSeries( macd_buff, true );
ArraySetAsSeries( date_buff, true );
//--- reset last error code
ResetLastError();
//--- copying the time from last 1000 bars
int copied = CopyTime( NULL, 0, 0, 1000, date_buff );
if ( copied <= 0 )
{ PrintFormat( "Failed to copy time values. Error code = %d", GetLastError() );`
return;
}
//--- prepare macd_buff array
ArrayResize( macd_buff, copied );
//--- copy the values of main line of the iMACD indicator
for ( int i = 0; i< copied; i++ )
{ macd_buff[i] = iMACD( InpSymbolName, InpSymbolPeriod, InpFastEMAPeriod, InpSlowEMAPeriod, InpSignalPeriod, InpAppliedPrice, MODE_MAIN, i );
}
//--- get size
macd_size = ArraySize( macd_buff );
//--- analyze the data and save the indicator signals to the arrays
ArrayResize( sign_buff, macd_size - 1 );
ArrayResize( time_buff, macd_size - 1 );
for ( int i = 1; i < macd_size; i++ )
{
//--- buy signal
if ( macd_buff[i-1] < 0
&& macd_buff[i] >= 0 )
{
sign_buff[sign_size] = true;
time_buff[sign_size] = date_buff[i];
sign_size++;
}
//--- sell signal
if ( macd_buff[i-1] > 0
&& macd_buff[i] <= 0 )
{
sign_buff[sign_size] = false;
time_buff[sign_size] = date_buff[i];
sign_size++;
}
}
//--- open the file for writing the indicator values (if the file is absent, it will be created automatically)
ResetLastError();
int file_handle = FileOpen( InpDirectoryName // aDirNAME
+ "//" // aFileSystemTreeBranchSEPARATOR
+ InpFileName, // aFileNAME
FILE_READ|FILE_WRITE|FILE_CSV // fileIoMODE_FLAGs
);
if ( file_handle != INVALID_HANDLE )
{
PrintFormat( "%s file is available for writing", InpFileName );
PrintFormat( "File path: %s\\Files\\", TerminalInfoString( TERMINAL_DATA_PATH ) );
//--- first, write the number of signals
FileWrite( file_handle, sign_size );
//--- write the time and values of signals to the file
for ( int i = 0; i < sign_size; i++ )
FileWrite( file_handle, time_buff[i], sign_buff[i] );
//--- close the file
FileClose( file_handle );
PrintFormat( "Data is written, %s file is closed", InpFileName );
}
else
PrintFormat( "Failed to open %s file, Error code = %d", InpFileName, GetLastError() );
}

Alt. A)
the algo does not check for a positive presence of an InpDirectoryName node in the filesystem.
Alt. B)
in case the Alt. A) passes, there ought be used a compatible delimiter in aFilePATH + aFileNAME string, i.e. == "\\", ( aFileSystemTreeBranchSEPARATOR ref.: Help for details )
thena fileIO shall take place in \Terminal\Common\Files ( in case a FILE_COMMON bitmask flag was added (used) in the int open_flags parameter),
otherwise,the operations will take place in a (sub)-directory of a MetaTrader Terminal 4 local folder== MQL4\Files ( for a live ExpertAdvisor or Custom Indicator or Script mode of operations )or== MQL4\Tester\Files ( in case of using ExpertAdvisor or Custom Indicatorinside a back-testing framework of MT4 Strategy Tester).

Related

MQL4 storing indicator value

Does anyone know if it is possible to store the series of value of an indicator, over, for example 1 year, or of a boolean function calculated in an EA?
I would like tho store the value of a particular function calculated on the difference between two different EMA that I defined into an EA.
I need to store the value of this double function, calculated in my EA over few years (say from 2015 to 2017) and print it in some output file (.txt or some other formats)
int s15_60;
double B_M15_H1(int i) {
if (i>=0 && i<4 ) s15_60=0;
else if (i>=4 && i<8 ) s15_60=1;
else if (i>=8 && i<12 ) s15_60=2;
else if (i>=12 && i<16 ) s15_60=3;
else if (i>=16 && i<20 ) s15_60=4;
return NormalizeDouble(MathAbs(M15(i) - H1(s15_60)),Digits);
where M15 is a simple EMA calculated in the M15 timeframe, and H1 is the same EMA calculated in the H1 timeframe, and the double function is the distance between this two indicators calculated in M15 time steps.
My goal is to store this value in a output file for doing some statistical studies about this function.
EDIT:
This code works for my purpose:
#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- show the window of input parameters when launching the script
#property script_show_inputs
//--- parameters for writing data to file
input string InpFileName="BOX.csv"; // File name
input string InpDirectoryName="Data"; // Folder name
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
double H1 (int shift) {double val = iCustom(NULL,PERIOD_H1, "my_funct",100,2.0,30.0,2.0,2.0,0,1,0,shift); return(val);}
double H4 (int shift) {double val = iCustom(NULL,PERIOD_H4, "my_funct",100,2.0,30.0,2.0,2.0,0,1,0,shift); return(val);}
int s60_240;
double B_H1_H4(int i) {
if (i>=0 && i<4 ) s60_240=0;
else if (i>=4 && i<8 ) s60_240=1;
else if (i>=8 && i<12 ) s60_240=2;
else if (i>=12 && i<16 ) s60_240=3;
else if (i>=16 && i<20 ) s60_240=4;
return NormalizeDouble( 10000*MathAbs( H1(i) - H4(s60_240) ) , Digits);
}
void OnStart()
{
double box_buff[]; // array of indicator values
datetime date_buff[]; // array of indicator dates
//--- copying the time from last 1000 bars
int copied=CopyTime(NULL,PERIOD_H1,0,1000,date_buff);
ArraySetAsSeries(date_buff,true);
//--- prepare box_buff array
ArrayResize(box_buff,copied);
//--- copy the values of main line of the iCustom indicator
for(int i=0;i<copied;i++)
{
box_buff[i]=B_H1_H4(i);
}
//--- open the file for writing the indicator values (if the file is absent, it will be created automatically)
ResetLastError();
int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_WRITE|FILE_CSV);
if(file_handle!=INVALID_HANDLE)
{
PrintFormat("%s file is available for writing",InpFileName);
PrintFormat("File path: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH));
//--- first, write the number of signals
FileWrite(file_handle,copied);
//--- write the time and values of signals to the file
for(int i=0;i<copied;i++)
FileWrite(file_handle,date_buff[i],box_buff[i]);
//--- close the file
FileClose(file_handle);
PrintFormat("Data is written, %s file is closed",InpFileName);
}
else
PrintFormat("Failed to open %s file, Error code = %d",InpFileName,GetLastError());
}
Please provide your MCVE-code to see what you need. How would you like to store data and why you might need it? Indicator data is already stored in a buffer so simply call it using iCustom(). If you want to optimize your EA and indicator take much time to load and compute buffers - yes it is possible to compute indicator buffers once then write them into a file or DB and get before new optimization starts, in such case use CArrayObj or CArrayDouble as a dynamic array for storing large arrays

How to make an Indicator update only once and never change the appearance?

Is there a way to let the indicator update the chart once, and for the subsequent, it will remember the old results rather than update every tick or candle?
I am asking this question since I only let the start() run once with the following code:
bool first = True; // .DEF GLOBAL lock
int start(){
if ( first ){ // .TST ?
first = False; // .SET ! ( lock forever )
... // .RUN my code here
..
.
}
...
..
.
return( 0 );
}
and I set the indicator using buffer. After every candle update, the indicator moves to another candle beside (since the buffer array has updated)..
I would like them to stay at that candle forever. What should I do?
Such idea is perfectly doable:
Details depend on your actual use-case.
Given a bool first = True; // .DEF GLOBAL lock is being used on a global-scope, the locking mechanism is clear & fully under your control. Not the case for addressing the once pre-computed ( and pre-stored ) values, injected into the IndicatorBuffer[]-s, which is subject of the reversed-TimeBased-shifting, so that your most recent value, stored in the cell-index [0], will upon each aNewBarEVENT arrival grow old and shift to the "left" ( in time ), becoming [++i] upon each such new candle beginning.
Is this a problem?
If yes, one may change the methods for iCustom(...)-based indicator-value inspections.
It would be quite enough to freeze the time on a global-scope register or use a smart access-index function:
bool first = True; // .DEF GLOBAL lock
double iCustomFrozenInTime( const int cellINDEX = 0 ){
static int Bars_onFirst = Bars; // .DEF STATIC first_Bars
if ( first ){
Bars_onFirst = Bars; // .SET STATIC first_Bars
}
return( iCustom( _Symbol,
PERIOD_CURRENT,
...,
cellINDEX + ( Bars - Bars_onFirst )
)
);
}
int start(){
if ( first ){ // .TST ?
iCustomFrozenInTime(); // .SET ( Bars_onFirst )
first = False; // .SET ! ( lock forever )
... // .RUN my code here
..
.
}
...
..
. // .GET values literally "Frozen in Time"
aFrozenCELL_0 = iCustomFrozenInTime( 0 )
aFrozenCELL_1 = iCustomFrozenInTime( 1 );
aFrozenCELL_2 = iCustomFrozenInTime( 2 );
return( 0 );
}

How to loop through all Symbols and check the current bar and the previous one's High?

The problem is that when the i in the for loop reaches 15, I get an Array out of range error.
What I want to achieve is on every tick to check every Symbol in the MarketWatch and in each Symbol to check the current bar ( PERIOD_M5 ) and the previous one if there is a gap.
void OnTick()
{
int size = ArraySize( Symbols );
for( int i = 0; i < size; i++ )
{
int current_bar_index = iHighest( Symbols[i], PERIOD_M5, MODE_HIGH, 1, 0 );
int previous_bar_index = iHighest( Symbols[i], PERIOD_M5, MODE_HIGH, 1, 1 );
int current_bar_index_low = iLowest( Symbols[i], PERIOD_M5, MODE_LOW, 1, 0 );
int previous_bar_index_low = iLowest( Symbols[i], PERIOD_M5, MODE_LOW, 1, 1 );
double current_high = High[ current_bar_index];
double previous_high = High[previous_bar_index];
double current_low = Low[ current_bar_index_low];
double previous_low = Low[ previous_bar_index_low];
if ( current_low > ( previous_high + 0.00002 )
|| current_high < ( previous_low - 0.00002 )
)
{
Print( "There is a gap" );
}
}
}
Symbols[] is the array containing all the symbols. I loop through it and pass the current Symbol and get the index for the current bar and the previous one and then simply check if there is a gap.
The first problem is that passing every Symbol doesn't work. It gets only one and that's it. How can I achieve that and also, why I get an Array out of range error?
Let's start with the Array out of range error:
Given the MCVE was not present, let's assume, there is some fair declaration of the MQL4 code in the header or something like that.
So to diagnose this, add a trivial debug tool:
string SymbolsARRAY[] = { ..., // be carefull, some Brokers
..., // have quite strange names
...
};
for ( int cellPTR = 0;
cellPTR < ArraySize( SymbolsARRAY );
cellPTR++
)
PrintFormat( "%s[%d] = %s",
"SymbolsARRAY",
cellPTR,
SymbolsARRAY[cellPTR]
);
and post here the output.
Next, the GAP detection:
if you would not mind, checking a pair of M5-Bars for a GAP on each and every price QUOTE message arrival, is quite devastating the MQL4 computing resources. The GAP may principally appear only upon a new Bar starts ( and yet may disappear, during the Bar duration ).
Let's detect the initial GAP-condition ( it is similar to engulfing detection ):
if ( iLow( SymbolsARRAY[cellPTR], PERIOD_M5, 1 ) > iHigh( SymbolsARRAY[cellPTR], PERIOD_M5, 0 )
|| iHigh( SymbolsARRAY[cellPTR], PERIOD_M5, 1 ) < iLow( SymbolsARRAY[cellPTR], PERIOD_M5, 0 )
)
Print( "Initial GAP detected" );
Using this inside a detection of a new bar event may look like this:
void OnTick(){
// -----------------------------------------------------------------
// MINIMALISTIC CONTEXT-AWARE GAP DETECT/REMOVE
// -----------------------------------------------------------------
static bool aCurrentGAP = False;
static datetime aCurrentBAR = Time[0];
if ( aCurrentBAR != Time[0] ){
aCurrentBAR = Time[0];
// testInitGAP .........................present?
aCurrentGAP = testInitialGAP_onNewBarEVENT();
}
else {
if ( aCurrentGAP ){
// testInitGAP .....................disappeared?
aCurrentGAP = testInitialGAP_DISAPPEARED();
}
}
// -----------------------------------------------------------------
// MAIN COMPUTING & TRADING DUTIES OF EA-MQL4-CODE
// -----------------------------------------------------------------
...
}
about the error - when you receive it, it also can see the address of the code that generates it: number of line and symbol number in that line
about Symbol - as you may know, in MQL5 you can select all symbols from the market watch, in MQL4 such option is not available, as far as I remember, so I suspect your array of symbol names is empty or sth like that.
Could you show how you initialized that array? A correct way is the following one:
string Symbol[]={"EURUSD","AUDUSD","GBPUSD"};
also your code doesn't make any sense - when you select iHighest(*,*,*,i,j) - that means that EA-code checks i-elements, starting from j-th element ( 1, 0 ) means a current bar only, ( 1, 1 ) means to select just 1 bar, starting from bar 1, so still only 1 Bar is used.
For that it is much easier to have
double cur_high = iHigh( Symbol[i], 5, 0 ),
prev_high = iHigh( Symbol[i], 5, 1 );

Getting the max and min price of current chart

After performing
ChartNavigate(0, CHART_END, -5142);
I want to get the max and min price of that particular chart.
I tried
ChartGetDouble(0,CHART_PRICE_MAX,0,top)
ChartGetDouble(0,CHART_PRICE_MIN,0,top)
WindowPriceMax
WindowPriceMin
None of them gives me the price after the ChartNavigate.
What is the right way to do this?
New-MQL4.56789 features may surprise, nevertheless:
Step 0: always catch Chart_OkFLAG
bool Chart_OkFLAG;
double Chart_min,
Chart_MAX;
int Chart_ToBeMODIFIED = ChartID();
int Chart_ToBeMODIFIED_SubWinID = 0;
int Chart_nBarsRelativeSHIFT = 0;
Chart_OkFLAG = ChartNavigate( Chart_ToBeMODIFIED,
< CHART_BEGIN |
CHART_END |
CHART_CURRENT_POS >,
Chart_nBarsRelativeSHIFT
);
If OK: you won the first round, the GUI command has been accepted for being syntactically & context-wise correct. That does not mean, it was executed by the GUI processor. It was just let in, to the tail of the GUI-command-QUEUE.
Step 1: Enforce it's execution ( wise to think about deferring such processing to some safe place, after mission-critical elements have been fulfilled )
if ( Chart_OkFLAG ){
WindowRedraw(); // ol'-MQL4
ChartRedraw( Chart_ToBeMODIFIED ); // new-MQL4
Chart_min = ChartPriceMin( Chart_ToBeMODIFIED,
Chart_ToBeMODIFIED_SubWinID
);
Chart_MAX = ChartPriceMAX( Chart_ToBeMODIFIED,
Chart_ToBeMODIFIED_SubWinID
);
}
else{
// ERROR HANDLING onChartNavigate(T)ERROR
}
ALWAYS: do not hesitate to inline error handlers, even where MQL4 language seems straightforward ( you never know, when that effort pays off by avoiding hours of bug tracking )
double ChartPriceMin( const long Chart_ID = 0,
const int Chart_SubWindow_ID = 0
) {
double result = EMPTY_VALUE;
ResetLastError();
if ( !ChartGetDouble( Chart_ID,
CHART_PRICE_MIN,
Chart_SubWindow_ID,
result
)
){
PrintFormat( "ERROR: Code(%d) in [%s]",
GetLastError(),
__FUNCTION__,
);
}
return( result );
}
double ChartPriceMAX( const long Chart_ID = 0,
const int Chart_SubWindow_ID = 0
) {
double result = EMPTY_VALUE;
ResetLastError();
if ( !ChartGetDouble( Chart_ID,
CHART_PRICE_MAX,
Chart_SubWindow_ID,
result
)
){
PrintFormat( "ERROR: Code(%d) in [%s]",
GetLastError(),
__FUNCTION__,
);
}
return( result );
}

How to notify a number increase & decrease in MQL4 code?

can anyone help me, how to write MQL4 code to know if the result is increase OR decrease..
Example:
if a result was first 0.0543 and then it is increased to 0.1342 and later decreased to 0.10345, I want to implement it to my code below:
int start()
{
double val = iCustom( NULL, 0, "SS2009_B", 0, 0, 0 );
ObjectSet( "TimeLable11", OBJPROP_CORNER, obCorner );
ObjectSetText( "TimeLable11", "Result : " + val,
fsize,
"Microsoft Sans Serif",
Yellow
);
return( 0 );
}
I want the result to have an increasing OR a decreasing notification.
Example :
Result : 0.1849 Increasing
Result : 0.01324 Decreasing
To have a SIMPLE example:
//------------------------------------------------------------------
#property copyright "Copyright 2015"
//------------------------------------------------------------------
// Standard Variables (define a variable to store previous value)
//------------------------------------------------------------------
double viIndicatorValuePrev = 0.0000;
int start() {
double viIndicatorValueNow = iCustom(NULL,0,"SS2009_B",0,0,0);
//------------------------------------------------
//Decide on direction (increasing or decreasing)
//------------------------------------------------
string vsDirection = "Same";
if( viIndicatorValueNow>viIndicatorValuePrev)
vsDirection = "Increasing";
if( viIndicatorValueNow<viIndicatorValuePrev)
vsDirection = "Decreasing";
//------------------------------------------------
//------------------------------------------------
// Do your thing here (ie, display stuff)
//------------------------------------------------
ObjectSet( "TimeLable11", OBJPROP_CORNER, obCorner);
ObjectSetText(
"TimeLable11"
, "Result : " + viIndicatorValueNow + " (" + vsDirection + ")"
, fsize, "Microsoft Sans Serif", Yellow
);
//------------------------------------------------
// Store current value for future comparison
//------------------------------------------------
viIndicatorValuePrev = viIndicatorValueNow;
//------------------------------------------------
return(0);
}
Hope this example helps.
Solution to monitor & show delta per each aMarketEVENT call of start() ( upon aMarketQUOTE aka Tick arrival )
First you need a method to store and retain a value, that becomes "old", in the meantime, before the start() ( well actually an OnTick() in the new-MQL century ) is called next time.
A static double is a smart way to go:
static double previousVALUE = EMPTY; // initialised to EMPTY
Next, initialise it in accord with a forward-stepping logic of the Custom Indicator "SS2009_B"
if ( previousVALUE == EMPTY ) {
previousVALUE = iCustom( NULL, // a Symbol
0, // a TimeFRAME
"SS2009_B",
0,
0, // a Buffer# to get value from
1 // step-back one Bar
);
}
For syntax details, review MQL4 documentation
double iCustom(
string symbol, // symbol
int timeframe, // timeframe
string name, // path/name of the custom indicator compiled program
... // custom indicator input parameterA (if
... // custom indicator input parameterB (if
... // custom indicator input parameterC (if necessary)
int mode, // line index
int shift // shift
);
Finally calculate delta & show it on UI & shuffle to get ready for a next call
double currentVALUE = iCustom( NULL, 0, "SS2009_B", 0, 0, 0);
double deltaVALUE = previousVALUE - currentVALUE;
previousVALUE = currentVALUE; // shuffle [1]<-[0] before RET/next call
if ( deltaVALUE > 0 ){
ObjectSetText( "TimeLabel11",
"RESULT: " + NormalizeDouble( deltaVALUE, Digits ) + "|^|",
fsize,
"Courier New",
Yellow // can be deltaVALUE specific too :o)
);
}
if ( deltaVALUE < 0 ){
ObjectSetText( "TimeLabel11",
"RESULT: " + NormalizeDouble( deltaVALUE, Digits ) + "|v|",
fsize,
"Courier New",
Cyan // can be deltaVALUE specific too :o)
);
}
A few remarks on precision of float numbers
You may notice a use of NormalizeDouble()
This is rather important step, to avoid problems with comparison of floats.
If the precision of standard floats ( MQL4 double ) is not sufficient, you may opt-in to use extended precision numbers in MQL4. Check documentation for that.
However, always be carefull on float comparisons.
Best practice, to be on a safer side, is to use both NormalizeDouble() ( as a prevention )
and
comparing to some thresholdDELTA like if ( MathAbs( floatA - floatB ) < anEqualityTresholdDELTA ){ ... } rather than if ( floatA == floatB ) {...}

Resources