Evaluate indicator at close of bar
Evaluate indicator at close of bar
26 Jul 2023, 12:36
Hello,
I am working on a custom indicator that produces a “1” when the criteria is valid, else “0”.
I would like the code to be evaluated at the close of the bar, alternatively at the start of the new bar, whatever is the most convenient regarding the code.
The current issue is that the indicator produces signals for historical data, but not for live real-time data.
Do you guys have any idea what the issue might be, and do you have any suggestions how improve the code?
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
#region Indicator
public class CustomIndicator : Indicator
{
[Output("Main", LineColor = "Black", LineStyle = LineStyle.Solid)]
public IndicatorDataSeries Result { get; set; }
// Creating the ExponentialMovingAverage indicators with specified periods
private ExponentialMovingAverage ema100;
private ExponentialMovingAverage ema200;
private ExponentialMovingAverage ema999;
// Creating the RSI indicators with specified period
private RelativeStrengthIndex rsi;
// Creating the variable class lastIndex
private int lastIndex;
#endregion
#region Initialize
protected override void Initialize()
{
// Initialize the ExponentialMovingAverage indicators with specified periods
ema100 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 100);
ema200 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 200);
ema999 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 999);
// Initialize the RSI indicator with period of 5
rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 5);
// Initialize the lastIndex variable as the integer 0
lastIndex = 0;
}
#endregion
#region Calculate
public override void Calculate(int index)
{
// If the current index is higher than the last index used in calculation, proceed with the calculation
// This implies that the calculation is only run once per bar, in the start of the newly formed bar.
if (index > lastIndex)
{
// Calculate if criteria for the first signal is met
bool firstCriteriaMet =
Bars.ClosePrices[index] > ema200.Result[index] &&
ema100.Result[index] > ema200.Result[index] &&
ema200.Result[index] > ema999.Result[index] &&
rsi.Result[index] < 20 && rsi.Result[index - 1] >= 20;
// Calculate if criteria for the second signal is met
bool secondCriteriaMet =
Bars.ClosePrices[index] < ema200.Result[index] &&
ema100.Result[index] < ema200.Result[index] &&
ema200.Result[index] < ema999.Result[index] &&
rsi.Result[index] > 80 && rsi.Result[index - 1] <= 80;
// Assign the Result value based on if any of the conditions are met
bool conditionMet = firstCriteriaMet || secondCriteriaMet;
Result[index] = conditionMet ? 1 : 0;
// Save the current index as the last used index
lastIndex = index;
}
}
#endregion
}
}
}
Thank you!
Best Regards,
Simon
Replies
sjolandersimon
26 Jul 2023, 13:18
( Updated at: 21 Dec 2023, 09:23 )
RE: Evaluate indicator at close of bar
Thank you for the fast reply.
With the given code setup, the indicator produces signals for historical data, see the picture below for the example Gold.
But when the indicator is live and evaluating the most recent real-time data, no signal is produced, even though the criteria is meet. I have come to this conclusion by watching new price bars forming.
PanagiotisChar said:
Hi there,
The current issue is that the indicator produces signals for historical data, but not for live real-time data.
How did you come this conclusion?
Need help? Join us on Telegram
@sjolandersimon
PanagiotisChar
26 Jul 2023, 13:37
Hi again,
Try removing this condition
if (index > lastIndex)
It causes the problem and I don't see the point of it
@PanagiotisChar
PanagiotisChar
26 Jul 2023, 13:37
Hi again,
Try removing this condition
if (index > lastIndex)
It causes the problem and I don't see the point of it
@PanagiotisChar
sjolandersimon
26 Jul 2023, 14:20
RE: Evaluate indicator at close of bar
PanagiotisChar said:
Hi again,
Try removing this condition
if (index > lastIndex)
It causes the problem and I don't see the point of it
Thanks for the reply.
When I remove the line of codes related to the "private int lastIndex", the indicator produces signals meeting the criteria for real-time price data. Although it evaluates at ever tick, resulting in all to many signals.
What would you recommend using as code to make the indicator only to be evaluated at the start of a new bar?
@sjolandersimon
PanagiotisChar
27 Jul 2023, 05:21
Hi,
It's wrong to evaluate at the opening of the previous bar. This is what you were doing before and was not working. The indicator should be calculated on every tick until the bar closes. Regarding signals (I guess you are reading this from a cBot?) you should only consider closed bars.
Need help? Join us on Telegram
@PanagiotisChar
sjolandersimon
31 Jul 2023, 20:05
RE: Evaluate indicator at close of bar
PanagiotisChar said:
Hi,
It's wrong to evaluate at the opening of the previous bar. This is what you were doing before and was not working. The indicator should be calculated on every tick until the bar closes. Regarding signals (I guess you are reading this from a cBot?) you should only consider closed bars.
Need help? Join us on Telegram
Thanks for the reply, I appreciate your effort!
When the indicator is evaluated at every tick, a signal is produced every time the condition is met during the length of that bar.
I am using an email notification, and my actual problem is that I am receiving an email for every tick the condition is met during the length of the bar. I would like to only receive one email at the close of the bar if the condition is met at the close of that bar. Do you have any suggestion how to proceed based on this information?
Actually I am working with chatGPT to produce code. The AI can produce a lot of interesting code, but you have to be very specific and you often have to modify the code in some degree.
@sjolandersimon
PanagiotisChar
01 Aug 2023, 07:32
Hi,
I would like to only receive one email at the close of the bar if the condition is met at the close of that bar. Do you have any suggestion how to proceed based on this information?
You need to have a flag that would check if an alert was triggered within that bar and send the alert only when it hasn't. Reset this flag on each bar change.
Need help? Join us on Telegram
@PanagiotisChar
sjolandersimon
02 Aug 2023, 19:47
RE: Evaluate indicator at close of bar
PanagiotisChar said:
Hi,
I would like to only receive one email at the close of the bar if the condition is met at the close of that bar. Do you have any suggestion how to proceed based on this information?
You need to have a flag that would check if an alert was triggered within that bar and send the alert only when it hasn't. Reset this flag on each bar change.
Hi Panagiotis,
Thanks for the reply and suggestion in how to improve the code.
I have made somewhat progress with the script. Below are two different scripts for the same criteria and is calculated at every tick respectively once at the close of the bar.
The 1st script below have the following prerequisites:
- Calculations are done at every tick
- Email notification is sent (and received) when the criteria is met. Several emails are sent due to the criteria is met several times during the length of a bar.
using System;
using System.Linq;
using System.Net.Mail;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class CustomIndicator : Indicator
{
[Output("Main", LineColor = "Black", LineStyle = LineStyle.Solid)]
public IndicatorDataSeries Result { get; set; }
private ExponentialMovingAverage ema100;
private ExponentialMovingAverage ema200;
private ExponentialMovingAverage ema999;
private RelativeStrengthIndex rsi;
protected override void Initialize()
{
ema100 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 100);
ema200 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 200);
ema999 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 999);
rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 5);
}
public override void Calculate(int index)
{
bool firstCriteriaMet =
Bars.ClosePrices[index] > ema200.Result[index] &&
ema100.Result[index] > ema200.Result[index] &&
ema200.Result[index] > ema999.Result[index] &&
rsi.Result[index] < 20 && rsi.Result[index - 1] >= 20;
bool secondCriteriaMet =
Bars.ClosePrices[index] < ema200.Result[index] &&
ema100.Result[index] < ema200.Result[index] &&
ema200.Result[index] < ema999.Result[index] &&
rsi.Result[index] > 80 && rsi.Result[index - 1] <= 80;
// Assign the Result value based on if any of the conditions are met
Result[index] = (firstCriteriaMet || secondCriteriaMet) ? 1 : 0;
// Send a notification if the condition is met
if (firstCriteriaMet || secondCriteriaMet)
{
Notifications.SendEmail("XXX@outlook.com", "XXX@outlook.com", "cTrader alert", $"1h Mark up or down: {SymbolName}");
}
}
}
}
The 2nd script below have the following prerequisites:
- Calculations are done once per bar, which I have seen works in real time when the criteria has been met at the close of the bar.
- Email notification is not sent, and no information message is logged. I know that I have the right settings for the email system since it works for the 1st script.
using System;
using System.Linq;
using System.Net.Mail;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class CustomIndicator : Indicator
{
[Output("Main", LineColor = "Black", LineStyle = LineStyle.Solid)]
public IndicatorDataSeries Result { get; set; }
private ExponentialMovingAverage ema100;
private ExponentialMovingAverage ema200;
private ExponentialMovingAverage ema999;
private RelativeStrengthIndex rsi;
private int lastIndex = -1;
protected override void Initialize()
{
ema100 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 100);
ema200 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 200);
ema999 = Indicators.ExponentialMovingAverage(Bars.ClosePrices, 999);
rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 5);
}
public override void Calculate(int index)
{
if (index > lastIndex)
{
OnBarClosed(lastIndex);
lastIndex = index;
}
}
private void OnBarClosed(int index)
{
bool firstCriteriaMet =
Bars.ClosePrices[index] > ema200.Result[index] &&
ema100.Result[index] > ema200.Result[index] &&
ema200.Result[index] > ema999.Result[index] &&
rsi.Result[index] < 20 && rsi.Result[index - 1] >= 20;
bool secondCriteriaMet =
Bars.ClosePrices[index] < ema200.Result[index] &&
ema100.Result[index] < ema200.Result[index] &&
ema200.Result[index] < ema999.Result[index] &&
rsi.Result[index] > 80 && rsi.Result[index - 1] <= 80;
// Assign the Result value based on if any of the conditions are met
Result[index] = (firstCriteriaMet || secondCriteriaMet) ? 1 : 0;
// Send a notification if the condition is met
if (firstCriteriaMet || secondCriteriaMet)
{
Notifications.SendEmail("XXX@outlook.com", "XXX@outlook.com", "cTrader alert", $"1h Mark up or down: {SymbolName}");
}
}
}
}
So to the question. I am trying to get the 2nd script to work with regards to email notification being sent. My suspicion is that it has something to do with email notification system not working well in current conditions when it is evaluated once per bar?
What are your suggestion how to improve further with regards to the issues with email notification and the 2nd script?
@sjolandersimon
PanagiotisChar
26 Jul 2023, 13:06
Hi there,
How did you come this conclusion?
Aieden Technologies
Need help? Join us on Telegram
@PanagiotisChar