using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Xml;
using TradeIdeas.XML;
using TradeIdeas.MiscSupport;
namespace TradeIdeas.TIProGUI.LimitAlerts
{
///
/// Class that represents a Limit Alert. LimitAlertsMessageManager is responsible for converting XML from the limit alert server into these objects.
///
public class LimitAlert
{
private string _id = "";
///
/// This is the identifier assigned by the limit alerts server. These are only created on the limit alert server.
///
[Browsable(false)]
public string Id { get { return _id; } set { _id = value; } }
private string _clientId = "";
///
/// This is the identifier assigned by the client. The server should know to not create a new alert if the client id already exists on the server.
///
[Browsable(false)]
public string ClientId { get { return _clientId; } set { _clientId = value; } }
private string _symbol = "";
public string Symbol { get { return _symbol; } set { _symbol = value; } }
private double _price;
///
/// The limit alert price.
///
[ColumnInfoAttribute(DisplayName = "Alert Price", Format="2", SizeHint = "XXXXX.XX")]
public double Price { get { return _price; } set { _price = value; } }
private bool _isLong = true;
///
/// The direction of the limit alert. True = from below (price must rise to the alert price to fire), False = from above (price must fall to the alert price to fire)
///
[ColumnInfoAttribute(DisplayName = "From Above/Below", Format="limitalertdirection", SizeHint = "FROM ABOVEXXX")]
public bool IsLong { get { return _isLong; } set { _isLong = value; } }
private bool _longAfter = true;
///
/// The direction of the limit alert after triggering. True = long, False = short
///
[ColumnInfoAttribute(DisplayName = "Side", Format = "longshort", SizeHint = "SHORTXXX")]
public bool LongAfter { get { return _longAfter; } set { _longAfter = value; } }
private string _status = "";
///
/// Current status of this limit alert. Can be WORKING (blue 64,114,232), INVALIDATED (red 255,0,0), EXPIRED (purple 176,64,190), TRIGGERED (green 0,255,0)
///
[ColumnInfoAttribute(DisplayName = "Status", SizeHint = "INVALIDATEDXXX", Format = "limitalertstatus")]
public string Status { get { return _status; } set { _status = value; } }
private DateTime? _triggered = null;
///
/// Triggered date/time if limit alert has been triggered.
///
[ColumnInfoAttribute(DisplayName = "Triggered", Format="t", SizeHint = "XX/XX/XXXX XX:XX:XX")]
public DateTime? Triggered { get { return _triggered; } set { _triggered = value; } }
private DateTime? _expires = null;
///
/// Time datetime after which this limit alert should "expire" if it hasn't triggered or been invalidated first.
///
[ColumnInfoAttribute(DisplayName = "Expires", Format="t", SizeHint = "XX/XX/XXXX XX:XX:XX")]
public DateTime? Expires { get { return _expires; } set { _expires = value; } }
private bool _afterHours = true;
///
/// The direction of the limit alert. True = from below (price must rise to the alert price to fire), False = from above (price must fall to the alert price to fire)
///
[ColumnInfoAttribute(DisplayName = "After Hours", Format = "onoff", SizeHint = "ONOFFXXX")]
public bool AfterHours { get { return _afterHours; } set { _afterHours = value; } }
private DateTime _created = ServerFormats.Now;
///
/// Creation time of this alert.
///
[ColumnInfoAttribute(DisplayName = "Created", Format="t", SizeHint = "XX/XX/XXXX XX:XX:XX")]
public DateTime Created { get { return _created; } set { _created = value; } }
private DateTime _updated = ServerFormats.Now;
///
/// Last updated time of this alert.
///
[ColumnInfoAttribute(DisplayName = "Updated", Format="t", SizeHint = "XX/XX/XXXX XX:XX:XX")]
public DateTime Updated { get { return _updated; } set { _updated = value; } }
private double? _invalidPrice = null;
///
/// Price at which this limit alert becomes invalid and converts to the INVALIDATED status.
///
[ColumnInfoAttribute(DisplayName = "Invalid Price", Format="2", SizeHint = "XXXXX.XX")]
public double? InvalidPrice { get { return _invalidPrice; } set { _invalidPrice = value; } }
private string _notes = "";
///
/// User entered notes that are stored with the alert on the server.
///
[ColumnInfoAttribute(DisplayName = "Notes", SizeHint = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX")]
public string Notes { get { return _notes; } set { _notes = value; } }
private double? _currentPrice = null;
///
/// This is the current price for the symbol.
///
[ColumnInfoAttribute(DisplayName = "Current Price", Format="2", SizeHint = "XXXXX.XX")]
public double? CurrentPrice { get { return _currentPrice; } set { _currentPrice = value; } }
///
/// Distance from alert price
///
[ColumnInfoAttribute(DisplayName = "Dollars from Alert", Format="2", SizeHint = "XXXXX.XX", RealTimeUpdates = true)]
public double? DistanceFromAlert
{
get
{
if (_currentPrice.HasValue)
{
if (_isLong)
return _price - _currentPrice.Value;
else
return _currentPrice.Value - _price;
} else
return null;
}
}
///
/// Dollars difference from triggered price - sort of like P&L
///
[ColumnInfoAttribute(DisplayName = "Dollars Since Triggered", Format="2", SizeHint = "XXXXX.XX", RealTimeUpdates = true)]
public double? DollarsSinceTriggered
{
get
{
if (_triggered.HasValue)
{
if (_currentPrice.HasValue)
{
if (_longAfter)
return _currentPrice.Value - _price;
else
return _price - _currentPrice.Value;
}
}
return null;
}
}
///
/// Percent from triggered price
///
[ColumnInfoAttribute(DisplayName = "Percent Since Triggered", Format="2", SizeHint = "XXXXX.XX", RealTimeUpdates = true)]
public double? PercentSinceTriggered
{
get
{
if (_triggered.HasValue)
return DollarsSinceTriggered / _price * 100;
else
return null;
}
}
///
/// Percent from alert price
///
[ColumnInfoAttribute(DisplayName = "Percent from Alert", Format="2", SizeHint = "XXXXX.XX", RealTimeUpdates = true)]
public double? PercentFromAlert
{
get
{
if (DistanceFromAlert.HasValue)
return DistanceFromAlert / _price * 100;
else
return null;
}
}
///
/// Volatility units from alert price
///
[ColumnInfoAttribute(DisplayName = "Volatility Bars from Alert", Format="2", SizeHint = "XXXXX.XX")]
public double? VolatilityBarsFromAlert
{
get
{
if (DistanceFromAlert.HasValue && _volatility.HasValue)
return DistanceFromAlert / _volatility;
else
return null;
}
}
private double? _volatility = null;
///
/// Volatility as read from a top list.
///
[ColumnInfoAttribute(DisplayName = "Volatility", Format="2", SizeHint = "XXXXX.XX", MaxForColor = 0.5, MinForColor = -1, MidForColor = 0)]
public double? Volatility
{
get { return _volatility; }
set { _volatility = value; }
}
private double? _relativeVolume = null;
///
/// Relative Volume as read from a top list.
///
[ColumnInfoAttribute(DisplayName = "Relative Volume", Format="2", SizeHint = "XXXXX.XX", MaxForColor = 3, MinForColor = -1, MidForColor = 0)]
public double? RelativeVolume
{
get { return _relativeVolume; }
set { _relativeVolume = value; }
}
private int? _todayVolume = null;
///
/// Relative Volume as read from a top list.
///
[ColumnInfoAttribute(DisplayName = "Today Volume", Format="0", SizeHint = "XXX,XXX,XXX")]
public int? TodayVolume
{
get { return _todayVolume; }
set { _todayVolume = value; }
}
private double? _changeFromTheClose = null;
///
/// Today Change as read from a top list.
///
[ColumnInfoAttribute(DisplayName = "Change from the Close $", Units="$", Format="2", SizeHint = "XXXXX.XX", MaxForColor = 1, MinForColor = -1, MidForColor = 0)]
public double? ChangeFromTheClose
{
get { return _changeFromTheClose; }
set { _changeFromTheClose = value; }
}
private double? _changeFromTheClosePercent = null;
///
/// Today Change Percent as read from a top list.
///
[ColumnInfoAttribute(DisplayName = "Change from the Close %", Units="%", Format="2", SizeHint = "XXXXX.XX", MaxForColor = 4, MinForColor = -4, MidForColor = 0)]
public double? ChangeFromTheClosePercent
{
get { return _changeFromTheClosePercent; }
set { _changeFromTheClosePercent = value; }
}
private string _companyName = "";
///
/// Company name of the symbol
///
[ColumnInfoAttribute(DisplayName = "Company Name", SizeHint = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX")]
public string CompanyName { get { return _companyName; } set { _companyName = value; } }
///
/// Daily performance thermograph
///
[ColumnInfoAttribute(DisplayName = "Daily Performance", SizeHint = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX", Format = "thermograph", RealTimeUpdates = true)]
public Thermograph DailyPerformance { get; set; }
///
/// Intraday performance thermograph
///
[ColumnInfoAttribute(DisplayName = "Intraday Performance", SizeHint = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX", Format = "thermograph", RealTimeUpdates = true)]
public Thermograph IntradayPerformance { get; set; }
public LimitAlert()
{
}
///
/// Converts this Limit Alert object to RowData.
///
/// RowData object representing this Limit Alert.
public RowData ToRowData()
{
RowData rowData = new RowData();
rowData.Data.Add("Symbol", _symbol);
rowData.Data.Add("Price", _price);
rowData.Data.Add("IsLong", _isLong);
rowData.Data.Add("LongAfter", _longAfter);
rowData.Data.Add("AfterHours", _afterHours);
rowData.Data.Add("Expires", _expires);
rowData.Data.Add("InvalidPrice", _invalidPrice);
rowData.Data.Add("Triggered", _triggered);
rowData.Data.Add("Created", _created);
rowData.Data.Add("Updated", _updated);
rowData.Data.Add("Status", _status);
rowData.Data.Add("Notes", _notes);
rowData.Data.Add("CurrentPrice", _currentPrice);
rowData.Data.Add("DistanceFromAlert", DistanceFromAlert);
rowData.Data.Add("DollarsSinceTriggered", DollarsSinceTriggered);
rowData.Data.Add("PercentSinceTriggered", PercentSinceTriggered);
rowData.Data.Add("PercentFromAlert", PercentFromAlert);
rowData.Data.Add("Volatility", Volatility);
rowData.Data.Add("VolatilityBarsFromAlert", VolatilityBarsFromAlert);
rowData.Data.Add("RelativeVolume", RelativeVolume);
rowData.Data.Add("TodayVolume", TodayVolume);
rowData.Data.Add("ChangeFromTheClose", ChangeFromTheClose);
rowData.Data.Add("ChangeFromTheClosePercent", ChangeFromTheClosePercent);
rowData.Data.Add("CompanyName", _companyName);
rowData.Data.Add("IntradayPerformance", IntradayPerformance);
rowData.Data.Add("DailyPerformance", DailyPerformance);
rowData.Data.Add("Id", _id);
rowData.Data.Add("object", this);
return rowData;
}
///
/// Save this object to XML
///
///
public void Save(XmlNode description)
{
description.SetProperty("SYMBOL", _symbol);
description.SetProperty("PRICE", _price);
description.SetProperty("IS_LONG", _isLong);
description.SetProperty("LONG_AFTER", _longAfter);
description.SetProperty("AFTER_HOURS", _afterHours);
if (_expires.HasValue)
description.SetProperty("EXPIRES", ServerFormats.ToTimeT(_expires.Value));
if (_invalidPrice.HasValue)
description.SetProperty("INVALID_PRICE", _invalidPrice.Value);
if (_triggered.HasValue)
description.SetProperty("TRIGGERED", ServerFormats.ToTimeT(_triggered.Value));
description.SetProperty("CREATED", ServerFormats.ToTimeT(_created));
description.SetProperty("UPDATED", ServerFormats.ToTimeT(_updated));
description.SetProperty("STATUS", _status);
description.SetProperty("NOTES", _notes);
}
///
/// Restore from XML to this object.
///
///
public void Restore(XmlNode description)
{
_symbol = description.Property("SYMBOL", "");
_price = description.Property("PRICE", 0.0);
_isLong = description.Property("IS_LONG", true);
_longAfter = description.Property("LONG_AFTER", true);
_afterHours = description.Property("AFTER_HOURS", true);
if (description.Property("EXPIRES", 0) != 0)
{
int time_t = description.Property("EXPIRES", 0);
if (time_t > 0)
_expires = ServerFormats.FromTimeT(time_t);
}
if (description.Property("INVALID_PRICE", 0.0) != 0.0)
_invalidPrice = description.Property("INVALID_PRICE", 0.0);
if (description.Property("CREATED", 0) != 0)
{
int time_t = description.Property("CREATED", 0);
if (time_t > 0)
{
DateTime? created = ServerFormats.FromTimeT(time_t);
if (created.HasValue)
_created = created.Value;
}
}
if (description.Property("UPDATED", 0) != 0)
{
int time_t = description.Property("UPDATED", 0);
if (time_t > 0)
{
DateTime? updated = ServerFormats.FromTimeT(time_t);
if (updated.HasValue)
_updated = updated.Value;
}
}
if (description.Property("TRIGGERED", 0) != 0)
{
int time_t = description.Property("TRIGGERED", 0);
if (time_t > 0)
_triggered = ServerFormats.FromTimeT(time_t);
}
_notes = description.Property("NOTES", "");
_status = description.Property("STATUS", "");
}
public override bool Equals(System.Object obj)
{
// If parameter is null return false.
if (obj == null)
return false;
// If parameter cannot be cast to Point return false.
LimitAlert c = obj as LimitAlert;
if ((System.Object)c == null)
return false;
// Return true if the fields match:
return (Id == c.Id);
}
public bool Equals(LimitAlert c)
{
// If parameter is null return false:
if ((object)c == null)
return false;
// Return true if the fields match:
return (Id == c.Id);
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
///
/// Returns friendly string suitable for a long description.
///
///
internal string ToFriendlyString()
{
string toReturn = "";
if (_isLong)
{
toReturn = "Alert (" + (_longAfter ? "Long": "Short") + ") if price of " + Symbol + " rises to $" + Price.ToString("N2");
if (Expires.HasValue)
toReturn += " before " + Expires.Value.ToString("yyyy-MM-dd hh:mm:ss tt");
if (InvalidPrice.HasValue)
toReturn += " unless price falls to $" + InvalidPrice.Value.ToString("N2") + " first";
}
else
{
toReturn = "Alert (" + (_longAfter ? "Long": "Short") + ") if price of " + Symbol + " falls to $" + Price.ToString("N2");
if (Expires.HasValue)
toReturn += " before " + Expires.Value.ToString("yyyy-MM-dd hh:mm:ss tt");
if (InvalidPrice.HasValue)
toReturn += " unless price rises to $" + InvalidPrice.Value.ToString("N2") + " first";
}
toReturn += " (" + Status + ")";
return toReturn;
}
}
}