Sporadically opens trades when EA should be preventing this - mql4

Morning all,
I'm currently testing out a segment of my EA which is supposed to only open a trade (providing other conditions are met) on the opening of the candle bar, which in MQL4 language is LastActiontime=Time[0];.
It's working really well: it is only opening trades on the LastActiontime=Time[0]; time, and not opening any trades part way through the candlestick bar should the EA need to be reinitialised.
However, on some occasions (though not every occasion), when I close the trade party way through the current candlestick bar, it sporadically opens another trade and thus defying the "only opening a trade on the opening time of the candlestick bar" rule.
I have the the snippet, below. Does anyone know where I'm going wrong?
Notes:
The best way is to test this on a 1M chart so you're not waiting any
longer to confirm the EA works.
The EA will only allow one trade to be open, if there are any
trades open when the EA is reinitialised, it won't open a new
trade - this is by design so as to avoid overtrading.
Suggestions / thinking points
The EA may not be initialising fast enough to comply with the
oninit parameters, so does not recognise that the conditions before
another trade is initialised.
//+------------------------------------------------------------------+
//| initialization_test.mq4 |
//| Copyright 2020, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
datetime LastActiontime;
bool totalOrders = OrdersTotal();
double currencyConversion;
int OnInit()
{
//---
LastActiontime=Time[0];
if (totalOrders == 0){
totalOrders = true;
}
//---
return(INIT_SUCCEEDED);
}
void OnTick()
{
//---
int LotSize = 30;
int RewardFactor = 3;
int stopLossPoints = 200;
double entryPriceBid = MarketInfo(Symbol(),MODE_BID);
double spread = MarketInfo(Symbol(), MODE_SPREAD);
double tickvalue = MarketInfo(Symbol(), MODE_TICKVALUE);
color sellcolor = clrGreen;
bool Newbar = true;
if(LastActiontime!=Time[0])
if(OrdersTotal() == 0)
if(totalOrders == true){
bool OpenShort = OrderSend(Symbol(),OP_SELL,LotSize,MarketInfo(Symbol(),MODE_BID),100,((entryPriceBid/Point)+(stopLossPoints))*Point,((entryPriceBid/Point)-(stopLossPoints*RewardFactor))*Point,"Spread Charge £"+DoubleToStr((spread * tickvalue)*LotSize,2),Period(),0,sellcolor);
LastActiontime=Time[0];
}
}
//+------------------------------------------------------------------+
All the best,

Your code is not really best practice for what you are trying to achieve. The best method to only carry out operations at the start of a bar would be as follows:
void OnTick()
{
if(TimeBar==Time[0])
{
//Carry out any operations on each tick here
return;
}
if(TimeBar==0)
{
// Operations carried out on First Run only here
TimeBar=Time[0];
return;
}
// Operations at the start of a new bar here
TimeBar=Time[0];
return;
}

Related

Mql4 Meta trader4, I can not make the indicator shift left simultaneously with the candles when new bar is formed

Below is the current code.
The indicator compiles and runs
When running the waves move with the candles as new bar forms.
But when you turn the platform off for some time and then turn it back on The candles and sin waves are now no longer synchronized.
Somehow the subwindow rests back to when the platform was turned on.
So no one out of 92 looky-loos wants to tackle this problem. I tried to put 3 pictures on here to help explain, but the system here will not display the pictures. If you are a coder trying to help, copy the code here, and paste it into your platform. Run it. Mark a high peak or low trough with a text symbol that will not move and then put a vertical line through the text character and the candle above it. as the program proceeds the vertical line will move with the candles and the wave moves with the vertical line, the text marker stays put so you can see where you started. Then turn off your platform with the indicator still loaded, wait for several candle periods then turn the platform back on and you will see that the waves reset back to the right. the vertical line continued on with the appropriate candle and the text marker also reset to the right with the peak or valley of the sin wave.
//---- indicator settings
#property indicator_separate_window
#property indicator_buffers 8 // 7
#property indicator_color1 Red
#property indicator_color2 Orange
#property indicator_color3 Yellow
#property indicator_color4 Lime
#property indicator_color5 Blue
#property indicator_color6 DodgerBlue
#property indicator_color7 DarkViolet
#property indicator_color8 White
//---- indicator buffers
double ExtBuffer1[], ExtBuffer2[], ExtBuffer3[], ExtBuffer4[],
ExtBuffer5[],ExtBuffer6[], ExtBuffer7[], ExtBuffer8[];
double Dgr1[], Dgr2[], Dgr3[], Dgr4[], Dgr5[], Dgr6[], Dgr7[],
Dgr8[];
extern datetime StartTime=D'1999.11.10 00:00';
//+-------------------------------------------------------------+
//| Custom indicator initialization function |
//+-------------------------------------------------------------+
int init()
{
IndicatorBuffers(7); // 6
SetIndexStyle(0,DRAW_LINE); SetIndexBuffer(0,ExtBuffer1);
SetIndexShift(0,295);
SetIndexStyle(1,DRAW_LINE); SetIndexBuffer(1,ExtBuffer2);
SetIndexShift(1,264);
SetIndexStyle(2,DRAW_LINE); SetIndexBuffer(2,ExtBuffer3);
SetIndexShift(2,203);
SetIndexStyle(3,DRAW_LINE); SetIndexBuffer(3,ExtBuffer4);
SetIndexShift(3,166);
SetIndexStyle(4,DRAW_LINE); SetIndexBuffer(4,ExtBuffer5);
SetIndexShift(4,74);
SetIndexStyle(5,DRAW_LINE); SetIndexBuffer(5,ExtBuffer6);
SetIndexShift(5,102); // DodgerBlue
SetIndexStyle(6,DRAW_LINE); SetIndexBuffer(6,ExtBuffer7);
SetIndexShift(6,78); // Dark Violet
SetIndexStyle(7,DRAW_LINE);
SetIndexBuffer(7,ExtBuffer8); SetIndexShift(7,85); // White
SetLevelValue(0,0);
SetIndexStyle(0,DRAW_LINE,0,3); // 0
SetIndexStyle(2,DRAW_LINE,0,3); // 0
SetIndexStyle(3,DRAW_LINE,0,3); // 0
SetIndexStyle(4,DRAW_LINE,0,3); // 0
SetIndexStyle(5,DRAW_LINE,0,3); // 0
SetIndexStyle(6,DRAW_LINE,0,3); // 0
SetIndexStyle(7,DRAW_LINE,0,3); // 0
return(0);
}
//+-------------------------------------------------------------+
//| Accelerator/Decelerator Oscillator |
//+-------------------------------------------------------------+
int start()
{
int limit; // -----------------------------mine
int counted_bars=IndicatorCounted();
//---- last counted bar will be recounted
if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;
//-----------------------------------------mine
int Shift;
int i;
int b; // mine
Shift=iBarShift(Symbol(),PERIOD_CURRENT,StartTime);
ArrayResize(Dgr1,Shift+1);
ArrayResize(Dgr2,Shift+1);
ArrayResize(Dgr3,Shift+1);
ArrayResize(Dgr4,Shift+1);
ArrayResize(Dgr5,Shift+1);
ArrayResize(Dgr6,Shift+1);
ArrayResize(Dgr7,Shift+1);
ArrayResize(Dgr8,Shift+1);
MyCalc(Shift,1);
for(b=Shift; b<limit; b++) // mine
{
for(i=Shift; i>=0; i--) // >
{
ExtBuffer1[i]=Dgr1[i];
ExtBuffer2[i]=Dgr2[i];
ExtBuffer3[i]=Dgr3[i];
ExtBuffer4[i]=Dgr4[i];
ExtBuffer5[i]=Dgr5[i];
ExtBuffer6[i]=Dgr6[i];
ExtBuffer7[i]=Dgr7[i];
ExtBuffer8[i]=Dgr8[i];
}
} // mine
return(0);
}
//+-------------------------------------------------------------+
void MyCalc(int Shift, int Yhigh )
{
int i;
for(i=Shift;i>=0;i--)
{
Dgr1[i]=i*2.5; Dgr2[i]=i*2.5; Dgr3[i]=i*2.5; Dgr4[i]=i*2.5;
Dgr5[i]=i*2.5;
double val1=i*2.5;
double val2=i*2.5;
double val3=i*2.5;
double val4=i*2.5;
double val5=i*2.5;
double val6=i*2.5;
double val7=i*2.5;
double val8=i*2.5;
Dgr1[i]=MathSin(3.14159*val1/298)- 1/2 * Yhigh;
Dgr2[i]=MathSin(3.14159*val2/149)- 1/2 * Yhigh;
Dgr3[i]=MathSin(3.14159*val3/98)- 1/2 * Yhigh;
Dgr4[i]=MathSin(3.14159*val4/75)- 1/2 * Yhigh;
Dgr5[i]=.5*MathSin(3.14159*val5/60)- 1/2 * Yhigh;
Dgr6[i]=.5*MathSin(3.14159*val6/48)- 1/2 * Yhigh;
Dgr7[i]=.5*MathSin(3.14159*val7/42)- 1/2 * Yhigh;
Dgr8[i]=.5*MathSin(3.14159*val8/38)- 1/2 * Yhigh;
}
}
Your problem is that the indicator starts drawing at D'1999.11.10 00:00', however as this date is no doubt not available in your visible chart history, the indicator instead starts redrawing as the earliest available bar. This continues as you run the indicator, however when restarting MQL4, the visible bars is limited by your settings (Tools>Options>Charts>Max bars in chart) and upon reloading the indicator again reverts to start drawing at the earliest available bar which has now changed. As stated in my original comment, your calculation are not directly linked to candles so they will not shift consistently. If you wish to make them consistently, make the start point consistent somehow.

Limit bars used for an indicator?

Trying to find a way to limit the amount of bars the EA is looking at for the indicator Ichimoku Kinko Hyo, its looking at a silly amount of bars and erroring as not enough memory.
I have tried going into options and setting the max bars on chart and in history to 5000 but its not working.
Is there a way I can code this into the script to only use the last x amount of bars for the indicator?
2021.05.04 11:29:03.007 Not enough memory for 7994468 bars for indicator Ichimoku Kinko Hyo (USDJPY,M1)
the code is just pulling out the value for the senkou A and B lines;
SenkouA = NormalizeDouble(iIchimoku(Symbol(),PERIOD_CURRENT,9,26,52,MODE_SENKOUSPANA,0),_Digits); //value of senkouspanA at current candle
and same again but for span B
Yeah sure, just starting off really, trying too get it to store the value of the top and bottom of the sumo cloud before I move onto the next bits.
It works fine on strategy tester, but when I put it on a live chart it comes up with the error above, I assumed its because on strategy tester it only has the last bars that have been played, but on a live chart it has all the brokers history right? :
double SenkouA;
double SenkouB;
double Kumo_top;
double Kumo_btm;
void OnTick()
{
SenkouA = NormalizeDouble(iIchimoku(Symbol(),PERIOD_CURRENT,9,26,52,MODE_SENKOUSPANA,0),_Digits); //value of senkouspanA at current candle
SenkouB = NormalizeDouble(iIchimoku(Symbol(),PERIOD_CURRENT,9,26,52,MODE_SENKOUSPANB,0),_Digits); //value of senkouspanB at current candle
Kumo_top = MathMax(SenkouA,SenkouB);
Kumo_btm = MathMin(SenkouA,SenkouB);
Comment ("SenkouA = " + SenkouA + "\n" +
"SenkouB = " + SenkouB)
}
Try the following code (note this is an EA and should be in the Experts folder).
//+------------------------------------------------------------------+
//| test.mq4 |
//| Copyright 2021, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
double SenkouA=iIchimoku(NULL,0,9,26,52,MODE_SENKOUSPANA,0);
double SenkouB=iIchimoku(NULL,0,9,26,52,MODE_SENKOUSPANB,0);
double Kumo_top=MathMax(SenkouA,SenkouB);
double Kumo_btm=MathMin(SenkouA,SenkouB);
Comment ("SenkouA = "+DoubleToStr(SenkouA,Digits)+"\n"+"SenkouB = "+DoubleToStr(SenkouB,Digits));
//---
}

Calculate PipSize for Symbols in MT4

My Question is How can I calculate Pip Size in MT4 (without checking symbol name)?
My first Answer is based on checking symbol name:
Use the Digits variable for 5 or 4 digits symbols and set PipSize = 0.0001. if Symbols are JPY fractions, use another values and so on other symbols in Shares and Indices or Spot Metals (like Silver)
double pipSize = 0.0001;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
if(StringFind("-,XAUUSD,Gold,GOLD,Gold.m,GOLD.m,-",","+Symbol()+",")>0){
pipSize = 0.1; // updated
}else if(StringFind("-,XAGUSD,Silver,SILVER,Silver.m,SILVER.m,-",","+Symbol()+",")>0){
pipSize = 1/500;
}
//---
return(INIT_SUCCEEDED);
}
GOLD 1 pip is 0.10 not 0.01 (according to COMEX)
double PIP = Point()*(Digits%2==1 ? 10 : 1); // for forex only
The problem is that the pip size definition is subjective (or at best intersubjective). There is no way to automate this in MetaTrader unless you find a broker with tick size symbol parameter equal to your definition of the pip size for all trading instruments.

MQL4 iCustom returns always the same (wrong) value (0x7FFFFFFF)

I wrote a custom indicator Speed.mq4 as follows:
double SpeedBuffer[]; // a Custom Indicator BUFFER
int OnInit() {
SetIndexBuffer( 0, SpeedBuffer ); // an access INDEX 0->BUFFER
...
}
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 start;
if ( prev_calculated == 0 ) start = 1;
else start = prev_calculated - 1;
for ( int i = start; i < rates_total - 1 ; i++ ) { // CPU-WASTED BY AN INEFFICIENT BACK-STEPPING IN TIME
double curTypical = typical( high[i], low[i], close[i] );
double prevTypical = typical( high[i+1],low[i+1],close[i+1] ); // CPU-WASTED, NO NEED TO RECALC ...
double curSpeed = curTypical - prevTypical;
SpeedBuffer[i] = curSpeed;
}
//--- return value of prev_calculated for next call
return( rates_total );
}
The indicator works fine in the application and the chart is plotted correctly.
When I try retrieving the last value in the ExpertAdvisor I always receive the same value:
double speed = iCustom( NULL, 0, "Speed", 2, 0, 0 );
Print( "speed is: " + speed );
prints:
speed is: 2147483647
It's always the same number. I'm not sure where's the problem.
from the Print in the indicator I can see the values are calculated correctly. but when I use iCustom I receive only that value.
MQL4 Custom Indicator iCustom() mechanics
MQL4 and even the New-MQL4 ( sometime called an MQL4.5 ) use a rather complicated interfacing model to handle Expert Advisor call / Custom Indicator computations.
A first thing to realise is, that iCustom() is not a call to a function, but rather a method, that indirectly "asks" a by-a-filename referred Custom Indicator to retrieve one, specific, value from a "pre-calculated" DataSTORE.
While it may sound complicated, it is the very nature of a CPU-efficient calculation factory, that the Custom Indicators were designed for in the early days of MQL4 world.
iCustom() is thus just a syntax-sugar to initiate the retrieval method, that gets the relevant piece of pre-calculated value back into the hands of Expert Advisor.
Custom Indicators put all the pre-calculated values into BUFFER(s), co-aligned with the TimeSeries style of ordering the DataSTORE cells ( [0] == "Now, the current Bar", going forwards [1], [2], [3], ... deeper and deeper back into the history )
The iCustom() passes the shift value, as a number of bars -- i.e. how deep into the history the retrieving method has to go, so as to pick the requested value from the respective BUFFER, and also the BUFFER identification INDEX ( 0 in our case above, as there is just a single BUFFER, with INDEX == 0 ). This is used for the sake of the EA being fully agnostic of the Custom Indicator internal variable names et al.
Just ask which BufferINDEX for which BarNUMBER one wants the value to be read from.
The Buffer is the one, who is to be blamed for the (wrong) value
The first line of the code says:
double SpeedBuffer[]; // a Custom Indicator BUFFER
If not handled otherwise in OnInit(){} all cells in the SpeedBuffer will have
EMPTY_VALUE
Empty value in an indicator buffer has by default this value == 2147483647 (0x7FFFFFFF) as has been objected above.
Q.E.D.
One may state in OnInit(){ ArrayInitialize( SpeedBuffer, 0.123456 ); } to have any other value for a cell-initialisation ( that for a TimeSeries-alligned BUFFERs happens upon each new-Bar event ( all cells get reshuffled by one backwards & cell[0] becomes "empty", pre-loaded with a default value discussed here ) ).
One may also add a step in an indicator OnCalculate(){ ... SpeedBuffer[0] = -9.87654; ...} so as to avoid leaving the cell[0] in a context-inconsistent state, not in a "just"-initialised state / value.
Caller-side interface ( how to reduce a risk on a weak-integration interface )
Nevertheless, the responsibility of the value retrieval is on the Expert Advisor side, as it fills the parameters of the iCustom() interface-proxy.
One may use preventive steps as shown in >>> https://stackoverflow.com/a/26389823/3666197
to minimise a risk of improper parameters ordering / values once calling an external Custom Indicator(s) to retrieve a set of values.
This simple method may save you literally tens of man*days of testing/debugging once a rich-extern-parametrised Custom Indicator with several indicator buffers has fallen into suspects due to serving "wrong" numbers ( just due to iCustom() call parameters being "invisibly" out of proper order/context )
Another thing to keep in mind when a custom indicator shows different values on the chart then are reported to the ExpertAdvisor, is that the execution flow through OnCalculate() needs to be different for an ExpertAdvisor than it is for a chart; specifically, the chart initially kicks off a call to OnCalculate() with prev_calculated = 0, whereas an EA (whether run with Strategy Tester or live) will always have prev_calculated = rates_total-1, so that the number of bars to compute the indicator value for is rates_total - prev_calcualted = 1 (ie. just the current bar).
You do account for this in your code, by setting start, but in general for a complicated indicator (that often involves referencing more than just the previous bar) one needs to be mindful of this difference and never assume that if the indicator looks good on the chart that means it's actually working. It needs to be tested separately with an EA.
I reviewed my code and finally figured that:
double speed=iCustom(NULL,0,"Speed",2,0,0);
was using the last value, which was not yet calculated by the custom indicator,
changing it to:
double speed=iCustom(NULL,0,"Speed",2,0,1);
did the trick.

Distance between 2 arduino's using rf links

I currently have a setup where I send a char using a Tx of 434MHz and an Uno to a Mega with a Rx. The Mega counts how many times it receives the char and then if it falls below a certain number it triggers an alarm. Is this a viable way to measure the distance between two microcontrollers while indoors or is there a better way.
Transmitter (Mega)
#include <SoftwareSerial.h>
int rxPin=2; //Goes to the Receiver Pin
int txPin=5; //Make sure it is set to pin 5 going to input of receiver
SoftwareSerial txSerial = SoftwareSerial(rxPin, txPin);
SoftwareSerial rxSerial = SoftwareSerial(txPin, rxPin);
char sendChar ='H';
void setup() {
pinMode(rxPin, INPUT);
pinMode(txPin,OUTPUT);
txSerial.begin(2400);
rxSerial.begin(2400);
}
void loop() {
txSerial.println(sendChar);
Serial.print(sendChar);
}
Receiver
#include <SoftwareSerial.h>
//Make sure it is set to pin 5 going to the data input of the transmitter
int rxPin=5;
int txPin=3; //Don't need to make connections
int LED=13;
int BUZZ=9;
int t=0;
char incomingChar = 0;
int counter = 0;
SoftwareSerial rxSerial = SoftwareSerial(rxPin, txPin);
void setup() {
pinMode(rxPin, INPUT); //initilize rxpin as input
pinMode(BUZZ, OUTPUT); //initilize buzz for output
pinMode(LED, OUTPUT); //initilize led for output
rxSerial.begin(2400); //set baud rate for transmission
Serial.begin(2400); //see above
}
void loop() {
for(int i=0; i<200; i++) {
incomingChar = rxSerial.read(); //read incoming msg from tx
if (incomingChar =='H') {
counter++; //if we get bit "h" count it
}
delay(5); //delay of 10 secs
}
Serial.println(incomingChar);
Serial.println(counter); //prints the the bits we recieved
if(counter<55) {
//if we receive less than 100 bits than print out of range triggers alarm
Serial.println("out of range");
tone(BUZZ,5000,500);digitalWrite(LED,HIGH);
}
else {
noTone(BUZZ);digitalWrite(LED, LOW);
//if we get more than 100 bits than we are within range turn off alarm
Serial.println("in range");
}
counter = 0;
incomingChar=0;
}
In theory you could achieve distance measuring by making the uno send a message which the mega would echo back. That would give the uno a round-trip time for message propagation between the arduinos. You would have to approximate the processing delays. After that it is basic physics. That is basically the same as how radar works. The actual delay would be something like
troundtrip = tuno send + 2*tpropagation + tmega receive + tmega send + tuno receive
I am guessing the distance you are trying to achieve is in the order of meters. Required resolution is going to be an issue, because s = vt => t = s/v, where s is the distance between your arduinos and v = c in case of radio waves. As the transmission delays should stay constant, you have to be able to measure differences in the order of 1/c second intervals, basically. I am not very familiar with arduinos, so I do not know if they are capable of this kind of measurements.
I would suggest you use an ultrasonic range finder like the Maxbotix HRLV-EZ4 sold by Sparkfun.
It is within your price range and it should be able to measure distances up to 5m/195 inches with 1mm resolution.
It is actually possible to do it, I have seen it be done with other microcontrollers. Therefore using arduino you would have to solve the equations,fit in arduino language and make a lot of measurements to value discrepancies over communication itself. Do not forget about atmospheric attenuation wich need to be known and fit in the equations. Humidity may deviate electromagnetic waves.

Resources