Is there a way that i can find numbers that are the nearest to each other in a array - mql4

My logic in my code right now is this
Step1. Scan for 100 candlesstick or more from the past
Step2. Collect and store the date of all 100 to find out the high of each candlestick
Step3. Go through all the candlestick high data and find the one that are near each other (Still dont know how i would do that)
Step4. Plot HLine
Now the first problem im having is how would i code it where i would be able to find which candlestick numbers are close to each other in order to plot the HLine.
extern int candleCount = 100;
int totalHigh;
int FinishingTotalHigh;
int totalLow;
int FinishingTotalLow;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
totalHigh = 0;
totalLow = 0;
// Initializing the variables.
double Highest = High[0];
double Lowest = Low[0];
Alert("");
Alert("");
Alert("");
Alert("");
Alert("");
// Scan the 100 candles and update the values of the highest and lowest.
for (int i = 0; i <= candleCount; i++)
{
//Alert(i+"Index Data: "+High[i]);
totalHigh = High[i] + totalHigh;
totalLow = Low[i] + totalLow;
if (High[i] > Highest) Highest = High[i];
if (Low[i] < Lowest) Lowest = Low[i];
}
FinishingTotalHigh = totalHigh/candleCount;
FinishingTotalLow = totalLow/candleCount;
// Print the result.
Alert("Highest price found is "+Highest);
Alert("Lowest price found is "+Lowest);
Alert("TotalHigh: "+FinishingTotalHigh);
Alert("TotalLow: "+FinishingTotalLow);
}
//+------------------------------------------------------------------+

Related

Sort ATR by hour

Hello Im wondering if there is a way I can somehow view ATR by hour, so when it calculates results in has 24 different values from 00:00 to 23:00. I would like the average to be of the ranges for that hour only in the lookback period. (for example hour 02:00 compares it range to the other 02:00 ranges in the look back period)
Original ATR Code
//| ATR.mq4 |
//| Copyright 2005-2014, MetaQuotes Software Corp. |
//| http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright "2005-2014, MetaQuotes Software Corp."
#property link "http://www.mql4.com"
#property description "Average True Range"
#property strict
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 DodgerBlue
//--- input parameter
input int InpAtrPeriod=14; // ATR Period
//--- buffers
double ExtATRBuffer[];
double ExtTRBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit(void)
{
string short_name;
//--- 1 additional buffer used for counting.
IndicatorBuffers(2);
IndicatorDigits(Digits);
//--- indicator line
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtATRBuffer);
SetIndexBuffer(1,ExtTRBuffer);
//--- name for DataWindow and indicator subwindow label
short_name="ATR("+IntegerToString(InpAtrPeriod)+")";
IndicatorShortName(short_name);
SetIndexLabel(0,short_name);
//--- check for input parameter
if(InpAtrPeriod<=0)
{
Print("Wrong input parameter ATR Period=",InpAtrPeriod);
return(INIT_FAILED);
}
//---
SetIndexDrawBegin(0,InpAtrPeriod);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Average True Range |
//+------------------------------------------------------------------+
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[])
{
int i,limit;
//--- check for bars count and input parameter
if(rates_total<=InpAtrPeriod || InpAtrPeriod<=0)
return(0);
//--- counting from 0 to rates_total
ArraySetAsSeries(ExtATRBuffer,false);
ArraySetAsSeries(ExtTRBuffer,false);
ArraySetAsSeries(open,false);
ArraySetAsSeries(high,false);
ArraySetAsSeries(low,false);
ArraySetAsSeries(close,false);
//--- preliminary calculations
if(prev_calculated==0)
{
ExtTRBuffer[0]=0.0;
ExtATRBuffer[0]=0.0;
//--- filling out the array of True Range values for each period
for(i=1; i<rates_total; i++)
ExtTRBuffer[i]=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);
//--- first AtrPeriod values of the indicator are not calculated
double firstValue=0.0;
for(i=1; i<=InpAtrPeriod; i++)
{
ExtATRBuffer[i]=0.0;
firstValue+=ExtTRBuffer[i];
}
//--- calculating the first value of the indicator
firstValue/=InpAtrPeriod;
ExtATRBuffer[InpAtrPeriod]=firstValue;
limit=InpAtrPeriod+1;
}
else
limit=prev_calculated-1;
//--- the main loop of calculations
for(i=limit; i<rates_total; i++)
{
ExtTRBuffer[i]=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);
ExtATRBuffer[i]=ExtATRBuffer[i-1]+(ExtTRBuffer[i]-ExtTRBuffer[i-InpAtrPeriod])/InpAtrPeriod;
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+````

What is the PineScript equivalent of MQL4's _Point?

I am trying to convert this indicator to PineScript. Couldn't figure out how to get Point variable. Is there any way to achieve the same thing in PineScript?
_Point official definition:
The _Point variable contains the point size of the current symbol in the quote currency.
https://docs.mql4.com/predefined/_point
Updated: Added the indicator code
//| Ticks Volume Indicator |
//| Copyright В© William Blau |
//| Coded/Verified by Profitrader |
//+------------------------------------------------------------------+
#property copyright "Copyright В© 2006, Profitrader."
#property link "profitrader#inbox.ru"
//-----
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Blue
//---- input parameters
extern int r=12;
extern int s=12;
extern int u=5;
//---- buffers
double TVI[];
double UpTicks[];
double DownTicks[];
double EMA_UpTicks[];
double EMA_DownTicks[];
double DEMA_UpTicks[];
double DEMA_DownTicks[];
double TVI_calculate[];
double MyPoint;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init() {
IndicatorShortName("TVI("+r+","+s+","+u+")");
IndicatorBuffers(8);
SetIndexBuffer(0,TVI);
SetIndexBuffer(1,UpTicks);
SetIndexBuffer(2,DownTicks);
SetIndexBuffer(3,EMA_UpTicks);
SetIndexBuffer(4,EMA_DownTicks);
SetIndexBuffer(5,DEMA_UpTicks);
SetIndexBuffer(6,DEMA_DownTicks);
SetIndexBuffer(7,TVI_calculate);
SetIndexStyle(0,DRAW_LINE);
SetIndexLabel(0,"TVI");
if (Digits == 5 || (Digits == 3 && StringFind(Symbol(), "JPY") != -1))
MyPoint = Point*10;
else if (Digits == 6 || (Digits == 4 && StringFind(Symbol(), "JPY") != -1))
MyPoint = Point*100;
else
MyPoint = Point;
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit() {
return(0);
}
//+------------------------------------------------------------------+
//| Ticks Volume Indicator |
//+------------------------------------------------------------------+
int start() {
int i,counted_bars=IndicatorCounted();
//---- check for possible errors
if(counted_bars<0) return(-1);
//---- last counted bar will be recounted
if(counted_bars>0) counted_bars--;
int limit=Bars-counted_bars;
//----
for(i=0; i=0; i--) {
EMA_UpTicks[i]=iMAOnArray(UpTicks,0,r,0,MODE_EMA,i);
EMA_DownTicks[i]=iMAOnArray(DownTicks,0,r,0,MODE_EMA,i);
}
for(i=limit-1; i>=0; i--) {
DEMA_UpTicks[i]=iMAOnArray(EMA_UpTicks,0,s,0,MODE_EMA,i);
DEMA_DownTicks[i]=iMAOnArray(EMA_DownTicks,0,s,0,MODE_EMA,i);
}
for(i=0; i=0; i--) {
if (iClose(NULL,0,i)==0)
TVI[i]=EMPTY_VALUE;
else
TVI[i]=iMAOnArray(TVI_calculate,0,u,0,MODE_EMA,i);
}
//----
return(0);
}
//+------------------------------------------------------------------+

Why is iCustom() returning default empty value (2147483647) for my indicator?

I built my own custom indicator that calculates the approximate slope and acceleration of a chart using the previous X number of bars.
When I attach the indicator to a chart it works as expected, but when I try to retrieve the latest value within an EA using iCustom() it only returns 2147483647.
I've already tried using different values for the iCustom() shift parameter without success.
double SlopeBuffer[];
double AccelerationBuffer[];
extern int delta;
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,SlopeBuffer);
SetIndexBuffer(1,AccelerationBuffer);
//---
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[])
{
//---
int i, counted_bars;
counted_bars = IndicatorCounted();
i = Bars - counted_bars - delta; // Here I offset the initial bar by the delta(period)
// so that the first bar has delta previous bars on the chart.
while(i>=0){
double Ex = 0; //intermediate calculation variables...
double Ey = 0;
double Exy = 0;
double Exx = 0;
for(int n=0;n<delta;n++){ // This for loop iterates over the previous delta bars
Ex += n; // to calculate various sigma variables used to find the
Ey += Close[i+delta-n-1]; // slope.
Exy += n*Close[i+delta-n-1];
Exx += n*n;
}
double slope = 100*(delta*Exy - Ex*Ey)/(delta*Exx - Ex*Ex); // final slope calculation.
SlopeBuffer[i] = slope; // add to the buffer.
AccelerationBuffer[i] = (slope - SlopeBuffer[i+1]); // calculate acceleration
i--; // and adding to buffer.
}
//--- return value of prev_calculated for next call
return(rates_total);
}
I figured out the issue.
This line was the culprit.
i = Bars - counted_bars - delta;
Once the indicator had "caught up" with all of the completed bars on the chart that would leave i equal to 1 - delta which would be negative. The result was that the while loop would never run.

Embedding a MQL4 custom indicator code in an Expert Advisor

This is my first post on Stackoverflow although I've visited here for years.
I have read the message guidelines so I'll be as succinct and specific as possible.
I have been attempting to embed the code of a Custom Indicator directly in an Expert Advisor without having to call iCustom:
iCustom(Symbol(),60,"MB",3D,0,1)>0;
Thus far I've failed and whilst I believe it is probably a trivial thing to do for many, if you don't know, you don't know.
The iCustom code in question is the following and I'd be grateful for any assistance:
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_color2 Red
#property indicator_width1 5
#property indicator_width2 5
extern int 3D= 5
double AIAIAI[];
double B1B1B1[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
SetIndexBuffer( 0, AIAIAI );
SetIndexEmptyValue( 0, 0.0 );
SetIndexStyle( 0, DRAW_ARROW );
SetIndexArrow( 0, 250 );
SetIndexLabel( 0, NULL );
SetIndexBuffer( 1, B1B1B1);
SetIndexEmptyValue( 1, 0.0 );
SetIndexStyle( 1, DRAW_ARROW );
SetIndexArrow( 1, 250 );
SetIndexLabel( 1, NULL );
IndicatorDigits( 5 );
//---- name for DataWindow and indicator subwindow label
IndicatorShortName( MB(" + 3D+ ")" );
return( 0 );
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
return( 0 );
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars = IndicatorCounted();
if (counted_bars < 0) return (-1);
if (counted_bars > 0) counted_bars--;
int intLimit = Bars - counted_bars;
int LO, HI;
for( int NINI = intLimit; NINI >= 0; NINI-- )
{
AIAIAI[NINI] = 0.0;
B1B1B1[NINI] = 0.0;
LO = iLowest( Symbol(), Period(), MODE_LOW, 3D, NINI );
if ( LO == NINI )
{
AIAIAI[NINI] = Low[NINI];
}
HI = iHighest( Symbol(), Period(), MODE_HIGH, 3D, NINI );
if ( HI == NINI )
{
B1B1B1[NINI] = High[NINI];
}
}
return( 0 );
}
Thank you
The best way to package the indicator code with the compiled EA is to include it as a resource and continue to call it using icustom. When you do it this way, there is no need to refactor and extract indicator logic.
The syntax is as follows:
#resource "MyCustomIndicator.ex4"
double my_custom_zero_buffer(string symbol, int period, int setting, int i)
{
return iCustom(symbol, period, "::MyCustomIndicator.ex4", setting, 0, i);
}
When you compile this EA the Indicator will also be compiled and packaged together so you can use/distribute it without exposing the indicator logic
If you use the indicator as an example only, that is probably not a good indicator as it does not use buffers and overall very simple indicator. It should be quite easy to recompute the buffer value from the ea when you need it.
double iCustomValue(const int param,const int buffer,const int shift)
{
switch(buffer)
{
case 0:
if(iLowest(_Symbol,0,MODE_LOW,param,shift)==shift)
return iLow(_Symbol,0,shift);
break;
case 1:
if(iHighest(_Symbol,0,MODE_HIGH,param,shift)==shift)
return iLow(_Symbol,0,shift);
break;
}
return(0.0);
}
and use the function instead of your indicator. For more complicated indicators - keep in mind that calling indicators is slower of course but allows to test easier.

Why do I get array our of range in MQL4?

I am trying to make an indicator that shows when x candles of the same color appear on the chart. But I am getting an array out of range error.
There is a up and down array buffer (an arrow pointing up or down)
minCandles is an extern integer that determines after how many bars to point the arrow.
the bear part works but from right to left.
I think the problem may be in down[i] = Low[i] but I don't know why.
Here is the code:
//+------------------------------------------------------------------+
//| SlayEm.mq4 |
//| Copyright 2016, Sebastian Bonilla. |
//| https://www.sebastianbonilla.me |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Sebastian Bonilla."
#property link "https://www.sebastianbonilla.me"
#property description "show X amount of candles of the same color."
#property version "1.00"
#property strict
#property indicator_chart_window
//--- input parameters
extern int minCandles = 4;
double up[];
double down[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,up); //assign up to the first buffer
SetIndexStyle(0,DRAW_ARROW);
SetIndexArrow(0,233);
SetIndexLabel(0, "Up Arrow");
//stuff for 1
SetIndexBuffer(1,down); //assign down to the second buffer
SetIndexStyle(1,DRAW_ARROW);
SetIndexArrow(1,234);
SetIndexLabel(1, "Down Arrow");
//---
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[])
{//------------------------------------------
int limit = MathMax(rates_total-prev_calculated,2);
int i;
int bull_count = 0;
int bear_count = 0;
for (i = 1; i < limit; i++){
//--bears-----------------------------------------------------------------------------------
if(Open[i] >= Open[i-1]){
bear_count++;
if (bear_count > minCandles) up[i] = High[i];
}
else bear_count = 0; // this by itself works but from right to left
// --- bulls ----------------------------------------
if(Open[i] < Open[i-1]){
bull_count++;
if (bull_count > minCandles) down[i] = Low[i];
}
else bull_count = 0; //this part creates the array out of range error*/
}
Comment((string)bear_count+ " --- ", (string)bull_count +" --- ", (string)i);
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
There are a few strange things behind the writing a fast and efficient [ Custom Indicator ] MQL4-code.
First, the real-time headache coming from a design decision to accumulate all the computational efforts from all the present [ Custom Indicator ] into a single thread.
While this is hidden, it increases the pressure to minimise all execution latencies at a cost of the colculus being operated in segmented mini-batches, from the deepest history ( the bars farthest back to the left ) proceeding iteratively forwards to the right, towards the current Bar.
One might get confused from the concept of reversed-numbering of the Bars, starting from [0]-for the most recent Bar ( the live Bar ), counting up, while going deeper and deeper towards the history on the far left.
If it were not enough, there are some additional prohibited things inside a [ Custom Indicator ], but as your web-page shows that you provide [ Custom Indicator ] programming on a commercial basis, it is worthless to repeat 'em here again.
Production-grade code for [Custom Indicator] ought have at least:
protective fuses
minimised main duty-cycle overheads
zero raw-Comment()-s to avoid damages to GUI/MMI
#property strict
//--- input parameters
extern int minCandles = 4;
//--- input PROTECTIVE FUSES:
int minCandlesFUSED = MathMax( 2, minCandles ); // assign no less than 2 irrespective of the extern
double up[];
double down[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit() {
// indicator buffers mapping
SetIndexBuffer( 0, up ); // assign up[] to the first buffer
SetIndexStyle( 0, DRAW_ARROW );
SetIndexArrow( 0, 233 );
SetIndexLabel( 0, "Up Arrow" );
// stuff for 1
SetIndexBuffer( 1, down ); // assign down[] to the second buffer
SetIndexStyle( 1, DRAW_ARROW );
SetIndexArrow( 1, 234 );
SetIndexLabel( 1, "Down Arrow" );
// RET
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[]
) {
// ------------------------------------------
int limit = rates_total
- prev_calculated
+ minCandlesFUSED;
if ( Bars + limit < minCandlesFUSED + 1 ) return( 0 ); // --> JIT/RET( 0 )
// ^--------------------^--- MEANING-FULL value, ref prev_calculated mechanisation
// makes no sense to start indicator w/o at least minCandlesFUSED + 1 Bars ready
int bull_count = 0;
int bear_count = 0;
for ( int i = limit + 1; // iterator .SET to start [limit + 1] Bars back in time (towards left), moving forwards -> [0]
i > 0; // iterator .PRE-CONDITION to keep looping while i > [0] points to already exist. Bars->[1], leaving [0] out
i-- // iterator .DEC on loop-end, before re-testing next loop .PRE-CONDITION
){
// --------------------------------------------------------------BEARS
if ( Open[i] >= Open[i-1] ){
bear_count++;
if ( bear_count > minCandlesFUSED ) up[i] = High[i]; // ref. above the
}
else bear_count = 0; // this by itself works
// --------------------------------------------------------------BULLS
if ( Open[i] < Open[i-1] ){
bull_count++;
if ( bull_count > minCandlesFUSED ) down[i] = Low[i];
}
else bull_count = 0; // this part creates the array out of range error*/
}
Comment( (string)bear_count // rather use StringFormat( "TEMPLATE: %d UP --- %d DN --- ", bear_count,
+ " --- ", // bull_count
(string)bull_count // )
+ " --- "
);
return( rates_total ); // return( rates_total ) value becomes -> prev_calculated for the next call
}
//+------------------------------------------------------------------+

Resources