OnCalculate not working for me

 

Hello experts,

I need your advise to understand why OnCalculate doesnt work in my EA.

I have the following compilation warning "OnCalculate function declared with wrong type or/and parameters" and the print statements always return 0 when EA is running.

2023.02.08 15:10:22.523 TestOnCalculate ADAUSDm,M30: LotSize calculated: 0.0
2023.02.08 15:10:22.523 TestOnCalculate ADAUSDm,M30: Trail stop loss level calculated: 0.0
2023.02.08 15:10:22.523 TestOnCalculate ADAUSDm,M30: Stop loss level calculated: 0.0
2023.02.08 15:10:22.523 TestOnCalculate ADAUSDm,M30: ATR value calculated: 0.0

2023.02.08 15:10:20.296 TestOnCalculate ADAUSDm,M30: LotSize calculated: 0.0

All I need here is to use OnCalculate to get the updated value for LotSize and TrailingStopLossLevel based on ATR

Maybe I don't really understand how it works so appreciate if you can explain it.

input double ATR_Multiplier = 1.5; // ATR multiplier for stop loss
input double RiskRewardRatio = 2;  // Risk to reward ratio
input int MovingAveragePeriod = 14; // Moving average period for crossover
input int TrailingStop = 100;       // Trailing stop in points

double ATRValue;
double StopLossLevel;
double TrailStopLossLevel;
double LotSize;
double TrailingStopLevel;

//+------------------------------------------------------------------+
//| Expert OnCalculate function                                      |
//+------------------------------------------------------------------+
void 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[])
   {
       ATRValue = iATR(NULL, 0, MovingAveragePeriod, PRICE_CLOSE);
       StopLossLevel = close[0] - ATR_Multiplier * ATRValue;
       TrailStopLossLevel = close[0] - ATRValue;

   
       // Calculate lot size based on 2:1 reward to risk ratio
       LotSize = AccountFreeMargin() * RiskRewardRatio / (ATRValue * Point);
       
   }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
       Print("ATR value calculated: ", ATRValue);
       Print("Stop loss level calculated: ", StopLossLevel);;
       Print("Trail stop loss level calculated: ",TrailStopLossLevel);
       Print("LotSize calculated: ", LotSize);
   
  }
Documentation on MQL5: Language Basics / Functions / Event Handling Functions
Documentation on MQL5: Language Basics / Functions / Event Handling Functions
  • www.mql5.com
Event Handling Functions - Functions - Language Basics - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 

"int" not "void"

int  OnCalculate(
   const int        rates_total,       // size of input time series
   const int        prev_calculated,   // number of handled bars at the previous call
   const datetime&  time{},            // Time array
   const double&    open[],            // Open array
   const double&    high[],            // High array
   const double&    low[],             // Low array
   const double&    close[],           // Close array
   const long&      tick_volume[],     // Tick Volume array
   const long&      volume[],          // Real Volume array
   const int&       spread[]           // Spread array
   );

And you have to return a value, an int type value to be passed as the prev_calculated parameter during the next function call.

 
Fernando Carreiro #:

"int" not "void"

And you have to return a value!

Return Value

int type value to be passed as the prev_calculated parameter during the next function call.

I have already tried this as well before the post but same it didnt work, compilation warning "no indicator window property is defined, indicator_chart_window is applied".

and when run with the EA, i have the following error "'TestOnCalculate' is not expert and cannot be executed"


input double ATR_Multiplier = 1.5; // ATR multiplier for stop loss
input double RiskRewardRatio = 2;  // Risk to reward ratio
input int MovingAveragePeriod = 14; // Moving average period for crossover
input int TrailingStop = 100;       // Trailing stop in points

double ATRValue;
double StopLossLevel;
double TrailStopLossLevel;
double LotSize;
double TrailingStopLevel;

//+------------------------------------------------------------------+
//| Expert OnCalculate 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[])
   {
       ATRValue = iATR(NULL, 0, MovingAveragePeriod, PRICE_CLOSE);
       //Print("ATR value calculated: ", ATRValue);
       StopLossLevel = close[0] - ATR_Multiplier * ATRValue;
       //Print("Stop loss level calculated: ", StopLossLevel);
       TrailStopLossLevel = close[0] - ATRValue;
       //Print("Trail stop loss level calculated: ",TrailStopLossLevel);
   
       // Calculate lot size based on 2:1 reward to risk ratio
       LotSize = AccountFreeMargin() * RiskRewardRatio / (ATRValue * Point);
       //Print("LotSize calculated: ", LotSize);
       
       return rates_total;
   }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
       Print("ATR value calculated: ", ATRValue);
       Print("Stop loss level calculated: ", StopLossLevel);;
       Print("Trail stop loss level calculated: ",TrailStopLossLevel);
       Print("LotSize calculated: ", LotSize);
   
  }
 
ahmedelmidany #:I have already tried this as well before the post but same it didnt work, compilation warning "no indicator window property is defined, indicator_chart_window is applied". and when run with the EA, i have the following error "'TestOnCalculate' is not expert and cannot be executed"

You can't use OnCalculate and OnTick at the same time.

If it is an Indicator then ONLY use OnCalculate (indicators cannot trade).

If it is an Expert Advisor then ONLY use OnTick.

 
Fernando Carreiro #:

You can't use OnCalculate and OnTick at the same time.

If it is an Indicator then ONLY use OnCalculate (indicators cannot trade).

If it is an Expert Advisor then ONLY use OnTick.

Thanks for the explanation Fernando.

 
       ATRValue = iATR(NULL, 0, MovingAveragePeriod, PRICE_CLOSE);
Do not post code that will not even compile.
 
William Roeder #:
Do not post code that will not even compile.

You can elaborate more on what do you mean by "will not even compile" rather than pasting same comment.

 
@William Roeder #: Do not post code that will not even compile.

It does compile. The user is just coding it incorrectly.

ahmedelmidany #: You can elaborate more on what do you mean by "will not even compile" rather than pasting same comment.

It does compile, but you are using it incorrectly ...

ATRValue = iATR( _Symbol, _Period, MovingAveragePeriod, 0 );
double  iATR( 
   string       symbol,     // symbol 
   int          timeframe,  // timeframe 
   int          period,     // averaging period 
   int          shift       // shift 
   );
 
Fernando Carreiro #: It does compile. The user is just coding it incorrectly.
Sorry. Coffee hadn't yet kicked in; I was thinking MQL5 (handle).
 
@William Roeder #: Sorry. Coffee hadn't yet kicked in; I was thinking MQL5 (handle).
No problem!
 

Im tryin to write code on MT5  and I have the following compilation warning  "OnCalculate function declared with wrong type or/and parameters"

But even i use int to replace for void  like you guys said but it did not work. 
help me pls. thanks 
here is my code


//+------------------------------------------------------------------+
//|                                              KeltnerStrategy.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property strict

//--- Tham số của chỉ báo và các tham số giao dịch
input double lotSize = 0.1;  // Lot size for trading
input int slippage = 3;      // Slippage for orders
input double stopLoss = 50;  // Stop loss in points
input double takeProfit = 50; // Take profit in points
double Ask, Bid;

//--- Input của 2 đường EMA 10 và 200
input int emaPeriod1 = 10;   // Period of the first EMA (short)
input int emaPeriod2 = 200;  // Period of the second EMA (long)

double ema10Buffer[];  // dùng để lưu giá trị của ema10  
double ema200Buffer[]; // dùng để lưu giá trị của ema200

int emaHandle10, emaHandle200;  // handle: mã định danh

//--- input của dải keltner 
//Công Thức Kênh Keltner
//Đường Trung Bình (EMA): Đường trung bình động hàm số của giá đóng cửa.
//Đường Trên (Upper Band): EMA + (ATR * Multiplier).
//Đường Dưới (Lower Band): EMA - (ATR * Multiplier).
input int    emaPeriod = 50;          // EMA period - length keltner 
input int    atrPeriod = 50;          // ATR period -> thường giống với EMA 
input double multiplier = 1.5;        // Multiplier for ATR

double upperBandBuffer[];
double emaBuffer[];
double lowerBandBuffer[];
double atrBuffer[];

int emaHandle;
int atrHandle;



int OnInit() // hàm khởi tạo
  { 
     // Ask là giá hiện tại mà bạn có thể mua
     // Bid là giá hiện tại mà bạn có thể bán 
   Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
   Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
   
// đoạn này của 2 đường EMA
     // Create handles for EMA indicators
     // hàm Symbol trả về tên của cặp tiền tệ/ tài sản bạn đang phân tích 
     // hàm Period trả về khung tgian mà bạn đang xem 
     // hàm Mode_ema cho biết bạn đang dùng chỉ báo dạng EMA -> không phải là SMA hay gì khác 
     // hàm price_close cho biết chỉ báo sẽ tính toán dựa trên giá đóng cửa của nến  ( bạn cx có thể dùng những hàm khác như price_open, price_high, price_low)
   emaHandle10 = iMA(Symbol(), Period(), emaPeriod1, 0, MODE_EMA, PRICE_CLOSE); 
   emaHandle200 = iMA(Symbol(), Period(), emaPeriod2, 0, MODE_EMA, PRICE_CLOSE);
 
  // sắp xếp thứ tự theo nến, nến gần nhất đang chạy sẽ là thứ tự 0, các nến trước đó có thứ tự tăng dần
   ArraySetAsSeries(ema10Buffer, true); 
   ArraySetAsSeries(ema200Buffer, true);
   
// dải keltner
  // Tạo handle cho EMA và ATR
   emaHandle = iMA(Symbol(), Period(), emaPeriod, 0, MODE_EMA, PRICE_CLOSE);
   atrHandle = iATR(Symbol(), Period(), atrPeriod);   
  // sắp xếp thứ tự theo nến
   ArraySetAsSeries(upperBandBuffer, true);
   ArraySetAsSeries(emaBuffer, true);
   ArraySetAsSeries(lowerBandBuffer, true);

   // gán các buffers cho các chỉ báo
   SetIndexBuffer(0, upperBandBuffer);
   SetIndexBuffer(1, emaBuffer);
   SetIndexBuffer(2, lowerBandBuffer);

   return(INIT_SUCCEEDED);
  }
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 long &spread[])  
  {
   // Kiểm tra số lượng nến đủ để tính toán
   if (rates_total < emaPeriod || rates_total < atrPeriod)
      return (0);
                 
   //sao chép dữ liệu vào buffer
   CopyBuffer(emaHandle10,0,0,rates_total,ema10Buffer);
   CopyBuffer(emaHandle200,0,0,rates_total,ema200Buffer);
   CopyBuffer(emaHandle, 0, 0, rates_total, emaBuffer);
   CopyBuffer(atrHandle, 0, 0, rates_total, atrBuffer);
   
   // Lấy giá trị mới nhất của EMA 10 và 200 vào buffer
   double ema10Value = ema10Buffer[0];
   double ema200Value = ema200Buffer[0];
   
   //lấy giá trị mới nhất của EMA và ATR
   double atr = atrBuffer[0]; 
   double ema = emaBuffer[0];
   
   // Tính dải trên và dải dưới của Keltner
   
   upperBandBuffer[0] = ema + atr * multiplier; // Tính dải trên
   lowerBandBuffer[0] = ema - atr * multiplier; // Tính dải dưới
   
   // lấy giá trị mới nhất của dải trên và dải dưới
   double lowerBand = lowerBandBuffer[0];
   double upperBand = upperBandBuffer[0];
   
   // Kiểm tra và mở lệnh

   if (ema10Value <= ema200Value && ema10Value <= lowerBand)
     {
      // Vào lệnh sell nếu EMA 10 và EMA 200 cùng nằm dưới hoặc trùng đường dưới của Keltner
      OpenSellOrder();
     }
   else if (ema10Value >= ema200Value && ema10Value >= upperBand)
     {
      // Vào lệnh buy nếu EMA 10 và EMA 200 cùng nằm trên hoặc trùng đường trên của Keltner
      OpenBuyOrder();
     }
   else if (ema10Value >= upperBand && ema10Value > ema200Value)
     {
      // Vào lệnh buy nếu EMA 10 cắt lên đường trên của Keltner và nằm trên EMA 200
      OpenBuyOrder();
     }
   else if (ema10Value <= lowerBand && ema10Value < ema200Value)
     {
      // Vào lệnh sell nếu EMA 10 cắt xuống dưới đường dưới của Keltner và nằm dưới EMA 200
      OpenSellOrder();
     }
   return (rates_total);
  }

//+------------------------------------------------------------------+
//| Open a buy order                                                 |
//+------------------------------------------------------------------+
// khai báo hàm OpenbuyOrder
void OpenBuyOrder() 
  {
    MqlTradeRequest request = {};    // Khởi tạo đối tượng yêu cầu giao dịch
    MqlTradeResult result = {};      // Khởi tạo đối tượng kết quả giao dịch

    request.action   = TRADE_ACTION_DEAL; // Hành động giao dịch
    request.symbol   = Symbol();          // Cặp tiền tệ
    request.volume   = lotSize;           // Kích thước lệnh
    request.type     = 0;         // Loại lệnh mua
    request.price    = NormalizeDouble(Ask, _Digits); // Giá mua
    request.sl       = NormalizeDouble(Ask - stopLoss * _Point, _Digits);  // Mức Stop Loss
    request.tp       = NormalizeDouble(Ask + takeProfit * _Point, _Digits); // Mức Take Profit
    request.deviation= slippage;          // Slippage
    request.magic    = 0;                 // Magic Number
    request.comment  = "Buy Order";       // Comment
  }

//+------------------------------------------------------------------+
//| Open a sell order                                                |
//+------------------------------------------------------------------+
// khai báo hàm OpenSellOrder
void OpenSellOrder()
  { 
   MqlTradeRequest request = {};    // Khởi tạo đối tượng yêu cầu giao dịch
   MqlTradeResult result = {};      // Khởi tạo đối tượng kết quả giao dịch

    request.action   = TRADE_ACTION_DEAL; // Hành động giao dịch
    request.symbol   = Symbol();          // Cặp tiền tệ
    request.volume   = lotSize;           // Kích thước lệnh
    request.type     = 1;        // Loại lệnh bán
    request.price    = NormalizeDouble(Bid, _Digits); // Giá bán
    request.sl       = NormalizeDouble(Bid + stopLoss * _Point, _Digits);  // Mức Stop Loss
    request.tp       = NormalizeDouble(Bid - takeProfit * _Point, _Digits); // Mức Take Profit
    request.deviation= slippage;          // Slippage
    request.magic    = 0;                 // Magic Number
    request.comment  = "Sell Order";      // Comment
  }



  
Documentation on MQL5: Language Basics / Functions / Event Handling Functions
Documentation on MQL5: Language Basics / Functions / Event Handling Functions
  • www.mql5.com
The MQL5 language provides processing of some predefined events . Functions for handling these events must be defined in a MQL5 program; function...