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));
//---
}
Related
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.
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;
}
I've been trading with grid orders for some time now, but just realized there is a WindowPriceOnDropped() function that I'd like to incorporate.
My standard order placement is written like this. Here is sample code for 5 orders spaced 5 pips apart, all micro lots, with 50 pip stops and 100 pip take profits. The first order appears close to market, just 1 pip down, and the rest follow:
int start()
{
int ticket;
double point;
//----
point=MarketInfo(Symbol(),MODE_POINT);
//----
ticket=OrderSend(Symbol(),OP_BUYLIMIT,0.01,Ask-100*point,0,Ask-600*point,Ask+900*point,"[5] 1k, 1 pip down");
ticket=OrderSend(Symbol(),OP_BUYLIMIT,0.01,Ask-150*point,0,Ask-650*point,Ask+850*point,"[5] 1k, 1 pip down");
ticket=OrderSend(Symbol(),OP_BUYLIMIT,0.01,Ask-200*point,0,Ask-700*point,Ask+800*point,"[5] 1k, 1 pip down");
ticket=OrderSend(Symbol(),OP_BUYLIMIT,0.01,Ask-250*point,0,Ask-750*point,Ask+750*point,"[5] 1k, 1 pip down");
ticket=OrderSend(Symbol(),OP_BUYLIMIT,0.01,Ask-300*point,0,Ask-800*point,Ask+700*point,"[5] 1k, 1 pip down");
//----
return(0);
}
//+------------------------------------------------------------------+
I'm testing WindowPriceOnDropped(), like this:
#include <stdlib.mqh>
#include <WinUser32.mqh>
int start()
{
int ticket;
double point;
double Price = WindowPriceOnDropped();
//----
point=MarketInfo(Symbol(),MODE_POINT);
//----
ticket=OrderSend(Symbol(),OP_BUYLIMIT,0.01,Price*point,0,Price-500*point,Price+1000*point, "[5] 1k test");
//----
return(0);
}
//+------------------------------------------------------------------+
However, the order doesn't appear at all. Am I missing something? The only thing I've changed is "Price", which ought to store the point value on drop due to the WindowPriceOnDropped() function, as opposed to Ask minus point value. Why can't I simply substitute the variable for "Ask" if the logic remains the same?
Thank you.
WindowPriceOnDropped() returns a normalized value of the price, you can normalize again with NormalizeDouble(double, _Digits). So instead of Price*point use just Price or its normalized value.
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.
Does somebody know how to avoid the error array out of range when trying to display long number of bars (lets say 7000) in an indicator buffer?
I had a similar issue, that I always got "Array out of range" errors for one of my buffers. I checked with ArraySize(), which returned 0. In the end I just forgot to call SetIndexBuffer(...) for this buffer array in onInit() {...} of my indicator.
Since I was using an internal buffer without drawing lines, I used the IndicatorBuffers() function to increase the amount of buffers first and then registered my additonal buffer using SetIndexBuffer(...).
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
IndicatorBuffers(5);
//buffers with #properties settings
SetIndexBuffer(0,Buffer1);
SetIndexBuffer(1,Buffer2);
SetIndexBuffer(2,Buffer3);
SetIndexBuffer(3,Buffer4);
//additional buffer without #properties
SetIndexBuffer(4,AdditionalBuffer);
While the arrays (problem) look similar, there is a major difference
MQL4 Indicators use "other" mechanics for handling arrays than "ordinary" arrays have.
... Testing pass stopped due to a critical error in the EA
... array out of range in '!2015-09-08___!EA 2xAMA 01 2015-09-08_msMOD_0.00.mq4' (519,39)
Yes, MT4 throws Fatal Error on an attempt to handle a wrong ptr->array[aStaticSIZE] and one has to take due care to either avoid such case, or trim ptr ( alike in low-latency circular-buffer scenarios ) not to direct past the array boundary ( underflow / overflow ) or extend the array[] via ArrayResize() so as to keep pace with the ptr growth ( until memory allows ) ) on arrays declared as dynamic double Array[];, however MQL4 Technical Indicators have completely other situation.
Limits? Yes. . . . . . ( And one ought to review on each New-MQL4.56789 stealth update )
As of a "New"-MQL4.56789-Build-840, your "ordinary" array cannot have more than 2.147.483.647 elements, if O/S memory-pool manager allows, so you ought to have plenty of space, even if using higher dimensionality mappings { 2D | 3D | 4D }.
Years ago 've used many parallel 2D / 3D-arrays for fast and private ( safely encapsulated ) heap / stack-handlers for maintaining highly dynamic entities in scales of 100k+ rows / 2D-planes and all worked well-oiled in old-MQL4.
So some 7k+ elements should not make you any worries.
Indicators use array indirectly, via an automated Buffer-handler
In this sense, your code need not care about these issues.
/*
#property "pragmas" help MQL4-compiler decide about setup of internal handlers
so this part of code "speaks" to MetaLang.exe at compile-time*/
#property indicator_buffers 3 // .DEF N-Buffs
#property indicator_color1 White // .SET Buf[0].color
#property indicator_color2 SeaGreen // .SET Buf[1].color
#property indicator_color3 FireBrick // .SET Buf[2].color
#property indicator_width1 1 // .SET Buf[0].width
#property indicator_width2 2 // .SET Buf[1].width
#property indicator_width3 2 // .SET Buf[2].width
double buffer_line_up[], // .DEF Arrays as dynamic ...[]
buffer_line_dn[], // with human-readable-names
buffer_line_ax[]; // and MT4 will take care
int init() {
SetIndexBuffer( 0, buffer_line_ax ); // .ASSOC IndexBuffer.0<-array[]
SetIndexLabel( 0, "SuperTrend" );
SetIndexBuffer( 1, buffer_line_up ); // .ASSOC IndexBuffer.0<-array[]
SetIndexLabel( 1, "Up Trend" );
SetIndexStyle( 1, DRAW_LINE,
STYLE_SOLID,
1 + int( ATR_Multiplier / 5 ),
SeaGreen
);
SetIndexBuffer( 2, buffer_line_dn ); // .ASSOC IndexBuffer.0<-array[]
SetIndexLabel( 2, "Down Trend" );
SetIndexStyle( 2, DRAW_LINE,
STYLE_SOLID,
1 + int( ATR_Multiplier / 5 ),
FireBrick
);
SetIndexDrawBegin(0, ATR_Period ); // .DEF initial depth of Buffer before 1st GUI output
IndicatorShortName( "xxxx[" + ATR_Period + "," + ATR_Multiplier + "]" );
IndicatorDigits( MarketInfo( Symbol(), MODE_DIGITS ) );