iCustom() function return value is different from an actual indicator in MQL5

iCustom() function return value is different from an actual indicator in MQL5

Manage alerts

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

Quoted from Forex.com.bd-Editorial External answer — Stack Overflow Stack Exchange Author: Janybek Kubat Source score (net votes, not local likes): 1 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 .

Cancel quote

Checking account access…