Warning! This section will be deprecated on February 1st 2025. Please move all your Indicators to the cTrader Store catalogue.
Description
Alert levels.
Store events in MyDocuments folder to detect crossing from setup date.
Functions:
1. Color alert.
2. Sound alert.
To use sound alerts please plaсe Ring.wav into MyDocuments folder.
using System;
using System.IO;
using System.Globalization;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
public class Alerts : Indicator
{
[Parameter("Prices")]
public string Prices { get; set; }
[Parameter("Sound", DefaultValue = false)]
public bool Sound { get; set; }
[Parameter("Visual", DefaultValue = true)]
public bool Visual { get; set; }
[Parameter("Alert diapasone", DefaultValue = 10, MinValue = 0)]
public int AlertDiapasone { get; set; }
[Parameter("Contignous type", DefaultValue = 0, MinValue = 0, MaxValue = 1)]
public int ContignousType { get; set; }
[Parameter("Thickness", DefaultValue = 1, MinValue = 1)]
public int Thickness { get; set; }
private class Alert
{
public DateTime setup;
public double price;
public int index = 0;
public bool inArgs;
public int played = 5;
public DateTime? lastPlayed = null;
public Alert(DateTime setup, double price, bool inArgs)
{
this.setup = setup;
this.price = price;
this.inArgs = inArgs;
}
}
private List<Alert> alerts;
private string lastError;
private string getFName()
{
return string.Format("{0}\\{1}-alerts.csv", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Symbol.Code);
}
private static Object lockObject = new Object();
private bool load()
{
string fname = getFName();
if (!File.Exists(fname))
{
return true;
}
StreamReader rd = new StreamReader(new FileStream(fname, FileMode.Open, FileAccess.Read, FileShare.Read));
try
{
while (!rd.EndOfStream)
{
string line = rd.ReadLine();
string []arr = line.Split(';');
if (arr.Length != 2)
{
lastError = string.Format("Read {0} error : invalid alert format - ", fname, line);
Print(lastError);
return false;
}
Alert alert;
try
{
alert = new Alert(DateTime.ParseExact(arr[1], "yyyyMMdd-HHmm", CultureInfo.InvariantCulture), Double.Parse(arr[0]), false);
}
catch(Exception e)
{
lastError = string.Format("Read {0} error : invalid alert format - {1}", fname, line, e.Message);
Print(lastError);
return false;
}
alerts.Add(alert);
}
}
catch (IOException e)
{
lastError = string.Format("Read {0} error : {1}", fname, e.Message);
Print(lastError);
return false;
}
finally
{
rd.Close();
}
return true;
}
private void save()
{
if (alerts.Count == 0)
{
return;
}
string fname = getFName();
StreamWriter wr = new StreamWriter(new FileStream(fname, FileMode.Create, FileAccess.Write, FileShare.None));
try
{
foreach (Alert alert in alerts)
{
wr.WriteLine(string.Format("{0};{1}", alert.price, alert.setup.ToString("yyyyMMdd-HHmm")));
}
}
catch(IOException e)
{
Print("Write {0} error : {1}", fname, e.Message);
}
finally
{
wr.Close();
}
}
private Alert alertExists(double price)
{
foreach (Alert alert in alerts)
{
if (alert.price == price)
{
return alert;
}
}
return null;
}
private bool parse()
{
if (Prices == null)
{
return true;
}
string []prices = Prices.Split(';');
try
{
foreach (string s in prices)
{
double price = double.Parse(s);
Alert exists = alertExists(price);
if (exists == null)
{
alerts.Add(new Alert(MarketSeries.OpenTime.LastValue, price, true));
}
else
{
exists.inArgs = true;
}
}
}
catch (Exception e)
{
lastError = string.Format("Prices parsing error : {0}", e.Message);
Print(lastError);
return false;
}
return true;
}
private int Period()
{
if (TimeFrame == TimeFrame.Minute)
return 1;
if (TimeFrame == TimeFrame.Minute2)
return 2;
if (TimeFrame == TimeFrame.Minute3)
return 3;
if (TimeFrame == TimeFrame.Minute4)
return 4;
if (TimeFrame == TimeFrame.Minute5)
return 5;
if (TimeFrame == TimeFrame.Minute6)
return 6;
if (TimeFrame == TimeFrame.Minute7)
return 7;
if (TimeFrame == TimeFrame.Minute8)
return 8;
if (TimeFrame == TimeFrame.Minute9)
return 9;
if (TimeFrame == TimeFrame.Minute10)
return 10;
if (TimeFrame == TimeFrame.Minute15)
return 15;
if (TimeFrame == TimeFrame.Minute20)
return 20;
if (TimeFrame == TimeFrame.Minute30)
return 30;
if (TimeFrame == TimeFrame.Minute45)
return 45;
if (TimeFrame == TimeFrame.Hour)
return 60;
if (TimeFrame == TimeFrame.Hour2)
return 120;
if (TimeFrame == TimeFrame.Hour3)
return 180;
if (TimeFrame == TimeFrame.Hour4)
return 240;
if (TimeFrame == TimeFrame.Hour6)
return 360;
if (TimeFrame == TimeFrame.Hour8)
return 480;
if (TimeFrame == TimeFrame.Hour12)
return 720;
if (TimeFrame == TimeFrame.Daily)
return 1440;
if (TimeFrame == TimeFrame.Day2)
return 2880;
if (TimeFrame == TimeFrame.Day3)
return 4320;
if (TimeFrame == TimeFrame.Weekly)
return 10080;
return 43200;
}
private void ReDraw()
{
ChartObjects.RemoveAllObjects();
foreach (Alert alert in alerts)
{
if (MarketSeries.OpenTime.LastValue.AddMinutes(Period()) < alert.setup)
{
return;
}
if (!alert.inArgs)
{
continue;
}
Colors color;
int periods = MarketSeries.OpenTime.Count - MarketSeries.OpenTime.GetIndexByTime(alert.setup);
bool crossed = MarketSeries.Close.HasCrossedAbove(alert.price, periods) || MarketSeries.Close.HasCrossedBelow(alert.price, periods);
bool near = Math.Abs(MarketSeries.Close.LastValue - alert.price) <= AlertDiapasone * Symbol.PipSize;
if (near && Sound && alert.played > 0 && (alert.lastPlayed == null || DateTime.UtcNow.AddMinutes(-1) >= alert.lastPlayed))
{
Notifications.PlaySound(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Ring.wav"));
alert.lastPlayed = DateTime.UtcNow;
--alert.played;
}
if (Visual && (crossed || near))
{
color = Colors.Red;
}
else
{
color = Colors.CornflowerBlue;
}
ChartObjects.DrawText(string.Format("alert_{0}", alert.price),
string.Format("| {0}{1}", alert.price, near ? string.Format(" ({0})", Math.Round(Math.Abs(MarketSeries.Close.LastValue - alert.price) / Symbol.PipSize), 1) : ""),
MarketSeries.OpenTime.Count + 1,
alert.price,
VerticalAlignment.Center,
HorizontalAlignment.Right,
color);
if (ContignousType == 0)
{
for (int j = MarketSeries.Close.Count - 1; j > 0 && alert.index == 0; --j)
{
if (MarketSeries.Low[j] <= alert.price && MarketSeries.High[j] >= alert.price)
{
alert.index = j;
}
}
}
else
{
alert.index = 1;
}
if (alert.index != 0)
{
ChartObjects.DrawLine(string.Format("alert_{0}_l", alert.price),
alert.index,
alert.price,
MarketSeries.OpenTime.Count + 1,
alert.price,
color,
Thickness,
LineStyle.Dots);
}
}
}
private DateTime? lastModified;
private void check()
{
DateTime? writeTime = null;
lock (lockObject)
{
if (File.Exists(getFName()))
{
writeTime = File.GetLastWriteTime(getFName());
}
if (lastModified == null || lastModified < writeTime)
{
ChartObjects.RemoveAllObjects();
alerts.Clear();
if (!load() || !parse())
{
ChartObjects.DrawText("AlertsErrorMessage", string.Format("Alerts\n{0}", lastError), StaticPosition.TopRight, Colors.Red);
}
else
{
if (lastModified == null)
{
save();
}
}
}
lastModified = writeTime;
}
}
protected override void Initialize()
{
alerts = new List<Alert>();
check();
}
private int ticks = 10;
private double last = 0;
public override void Calculate(int index)
{
if (--ticks == 0 || Math.Abs(last - MarketSeries.Close.LastValue) > Symbol.PipSize)
{
check();
ReDraw();
ticks = 10;
last = MarketSeries.Close.LastValue;
}
}
}
}
ZI
ZigzagAK
Joined on 06.02.2015
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: Alerts.algo
- Rating: 0
- Installs: 3706
- Modified: 13/10/2021 09:54
Note that publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section, please use the Copyright Infringement Notification form to submit a claim.
Comments
Log in to add a comment.
KH
it is a good indicator.
is it posible drag price level with mouse?
like price alert in metatrader
Thank you for your indicator !
But I also have this error: "Prices parsing error" when I add it to my chart.
Any idea ?
TO
Got an error about something wrong with the format
Can you tell me the code for a different alert sound for call and for put?