iCustom() function return value is different from an actual indicator in MQL5
iCustom() function return value is different from an actual indicator in MQL5
Loading saved threads...
Janybek Kubat · External communityPost link
External question — Stack Overflow Stack Exchange
Author: Janybek Kubat
Original post: https://stackoverflow.com/questions/76951723
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
I am testing ea using iCustom function to pull data from indicator. But I found some discrepancies in the data that indicator gave on the chart vs iCustom function on the same date. I thought that my ea had some bug and run the debugging on the same date and while running code step by step it gave me correct value on that particular date ( same as indicator on the chart window). But when I run strategy tester using the same ea values are differ from the indicator on the chart... I don't know why it is behaving like that. Actually, while debugging all the values are identical to what indicator is giving, and while running strategy tester all the values are way off from what it should be. Is there some sort of buffer that I need to reset every time I call iCustom or something?
//+------------------------------------------------------------------+
//| |
//| suvroc |
//| |
//+------------------------------------------------------------------+
#property copyright "suvroc"
#property link ""
#property version "1.00"
#include <myFunctions.mqh>
#include <CustomOptimisation.mqh>
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
// GLOBAL VARS
sinput group "EA GENERAL SETTINGS"
input ulong MagicNumber = 101;
input bool UseFillingPolicy = false;
input ENUM_ORDER_TYPE_FILLING FillingPolicy = ORDER_FILLING_FOK;
input double minTrades = 50.0;
sinput group "ATR SETTINGS";
input int atrPeriod = 14;
input int shiftAtr = 0;
sinput group "1st CONFIRMATION INDICATOR PARAMETERS";
//--- enums
enum ENUM_MODE
{
MODE_RSI, // RSI
MODE_STO // Stochastic
};
//--- input parameters
input uint InpPeriod = 9; // Period
input uint InpPeriodSm = 2; // Smoothing
input ENUM_MODE InpMode = MODE_RSI; // Mode
input ENUM_MA_METHOD InpMethod = MODE_SMA; // Method
input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; // Applied price
double atrValue;
int atrHandle;
int asoHandle;
string entrySignal;
string entrySignalConfirmation;
datetime glTimeBarOpen;
//---
TCustomCriterionArray *criterion_Ptr;
//---
int OnInit()
{
//---
glTimeBarOpen = D'1971.01.01 00:00';
string indiPath = "ASO.ex5";
atrHandle = iATR(_Symbol,PERIOD_CURRENT,atrPeriod);
asoHandle = iCustom(_Symbol,PERIOD_CURRENT,indiPath, InpPeriod, InpPeriodSm,InpMode,InpMethod,InpAppliedPrice);
if(asoHandle == INVALID_HANDLE)
{
Print("FAILED TO INIT ASO INDICATOR");
return (INIT_FAILED);
}
if (atrHandle == INVALID_HANDLE)
{
Print("FAILED TO INIT ATR INDICATOR");
return (INIT_FAILED);
}
//criterion_Ptr=new TCustomCriterionArray();
// if(CheckPointer(criterion_Ptr)==POINTER_INVALID)
// {
// return(-1);
// }
//criterion_Ptr.Add( new TSimpleCriterion( STAT_PROFIT ));
//criterion_Ptr.Add( new TSimpleDivCriterion( STAT_BALANCE_DD ));
//criterion_Ptr.Add( new TSimpleMinCriterion( STAT_TRADES, minTrades ));
//criterion_Ptr.Add( new TBalanceSlopeCriterion(Symbol(),100000.0));
//criterion_Ptr.Add(new TTSSFCriterion());
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
// if(CheckPointer(criterion_Ptr)==POINTER_DYNAMIC)
// {
// delete(criterion_Ptr);
// }
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
//+------------------------------------------------------------------+
//| 1. ATR |
//+------------------------------------------------------------------+
atrValue = NormalizeDouble(myAtr(atrHandle,shiftAtr),_Digits);
Comment("ATR : ", atrValue);
//+------------------------------------------------------------------+
//| 2. TESTED INDICATOR |
//+------------------------------------------------------------------+
//--------------------//
// NEW BAR CONTROL //
//--------------------//
datetime currTime = TimeCurrent();
bool newBar = false;
double myBallance = AccountInfoDouble(ACCOUNT_BALANCE);
double contractSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
//Print("current time : " + currTime);
//Check for New Bar
if(currTime == (iTime(Symbol(),PERIOD_CURRENT,0) + PeriodSeconds(PERIOD_M10) * 1))
{
newBar = true;
glTimeBarOpen = iTime(Symbol(),PERIOD_CURRENT,0) + PeriodSeconds(PERIOD_M10) * 1;
}
if(newBar == true)
{
//double myBuffer[];
//CopyBuffer(didiHandle,2,0,2,myBuffer);
// bool cross = DetectCrossover(myBuffer,2);
//Print("DIDI SIGNAL : ", myBuffer[1]);
//--------------------//
// TRADE ENTRY //
//--------------------//
double myLot = CalculatePositionSize(_Symbol, 0.02, (int)(atrValue * 1.5 / _Point));
//-------------------------//
// 1st CONFIRMATION //
//-------------------------//
entrySignal = detectCrossover(asoHandle,0,1,glTimeBarOpen);
Comment("EA #", MagicNumber, " | ",entrySignal, " 1st CI");
//-------------------------//
// 2nd CONFIRMATION //
//-------------------------//
if((entrySignal == "LONG" || entrySignal == "SHORT") && CheckPlacedPositions(MagicNumber) == false)
{
ulong ticket = OpenTrades(entrySignal,MagicNumber,NormalizeDouble(myLot,2), UseFillingPolicy, FillingPolicy);
//SL & TP Trade Modification
if(ticket > 0)
{
double stopLoss = CalculateStopLoss(entrySignal, atrValue * 1.5);
double takeProfit = CalculateTakeProfit(entrySignal, atrValue);
TradeModification(ticket,MagicNumber,stopLoss,takeProfit);
}
}
else if((entrySignal == "LONG" || entrySignal == "SHORT"))
{
Print(entrySignal + " without position check" );
}
else
{
Print(entrySignal);
}
//--------------------//
// TRADE EXIT //
//--------------------//
}
//+------------------------------------------------------------------+
//| 2. ORDER MANAGEMENT |
//+------------------------------------------------------------------+
}
//+------------------------------------------------------------------+
double OnTester()
{
double param=0.0;
// Balance max + min Drawdown + Trades Number:
// if(CheckPointer(criterion_Ptr)!=POINTER_INVALID)
// {
// param=criterion_Ptr.GetCriterion();
// }
//return(param);
double winTrades = TesterStatistics(STAT_PROFIT_TRADES);
double lossTrades = TesterStatistics(STAT_LOSS_TRADES);
double winLossPercent = (winTrades+lossTrades) > 0? winTrades / (winTrades+lossTrades) * 100.0 : 0;
return (winLossPercent);
}
//+------------------------------------------------------------------+
//| DETECT CROSSOVER |
//+------------------------------------------------------------------+
string detectCrossover(int pHandle, int pSignalBuffer1, int pSignalBuffer2, const datetime time)
{
MqlDateTime dt;
TimeToStruct(time,dt);
double indicator1[];
double indicator2[];
CopyBuffer(pHandle,pSignalBuffer1,0,3,indicator1);
CopyBuffer(pHandle,pSignalBuffer2,0,3,indicator2);
ArraySetAsSeries(indicator1, true);
ArraySetAsSeries(indicator2, true);
if(indicator1[0] > indicator2[0] && (indicator1[1] <= indicator2[1]))// || (dt.day_of_week == 1 && indicator[1] > pCrossLine && indicator[2] <= pCrossLine )))
{
return "LONG";
}
else
if(indicator1[0] < indicator2[0] && (indicator1[1] >= indicator2[1])) // || (dt.day_of_week == 1 && indicator[1] < pCrossLine && indicator[2] >= pCrossLine)))
{
return "SHORT";
}
return "NO TRADE - " + DoubleToString(indicator1[0]) + " | " + DoubleToString(indicator2[0]) + " | " + DoubleToString(dt.day_of_week) + " | " + DoubleToString(indicator1[1]) + " | " + DoubleToString(indicator2[1]);
}
Quote
Report
Janybek Kubat · External communityPost link
External answer — Stack Overflow Stack Exchange
Author: Janybek Kubat
Original post: https://stackoverflow.com/a/76952680
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
I found the reason and solution to my issue. To my embarrassment it all was written in a MQL5 help file :
"The Calculation of Indicators During Testing
In the real-time mode, the indicator values are calculated at every
tick.
In the Strategy Tester, indicators are calculated only when they are
accessed for data, i.e. when indicator buffer values are requested.
The only exceptions are custom indicators with the specified #property
tester_everytick_calculate. In this case, recalculation is done on
each tick.
In the visual testing mode, all indicators are unconditionally
recalculated when a new tick arrives in order to be correctly
displayed on the visual testing chart.
The indicator is calculated once per tick. All subsequent requests for
indicator data do not lead to recalculation until a new tick arrives.
Therefore, if the timer is enabled in an EA via the EventSetTimer()
function, the indicator data is requested from the last tick before
each call of the OnTimer() handler. If the indicator has not been
calculated on the last tick yet, the calculations of the indicator
values are launched. If the data has already been prepared, it is
provided without a new recalculation.
Thus, all indicator calculations are performed in the most
resource-saving manner — if the indicator has already been calculated
at a given tick, its data is provided 'as is'. No recalculation is
launched."
Solution to my issue was to modify my indicator by adding #property tester_everytick_calculate .
Quote
Report
Post Reply
Checking account access…