using System; using System.Collections.Generic; using System.Linq; using System.Text; using TradeIdeas.TIProGUI; using TradeIdeas.MiscSupport; using System.ComponentModel; using TradeIdeas.TIProData; using TradeIdeas.ServerConnection; using TradeIdeas.XML; using System.Xml; using System.Web; using System.Collections.Specialized; using System.Drawing; using TradeIdeas.TIProData.Configuration; namespace AIStrategyWindow { public delegate void NewAlertHandler(RowData rowData, AIStrategy strategy); public delegate void NewStrategyTradeHandler(StrategyTrade trade, AIStrategy strategy); public delegate void CloudLinkLoadedHandler(AIStrategy strategy); public delegate void HistoryCompleteHandler(AIStrategy strategy); public class AIStrategy: IRowDataCapable { private string _name = ""; /// /// Name of the strategy. /// [ColumnInfoAttribute(SizeHint="Opening Range Breakdown Hold 3_30pmXXXX")] public string Strategy { get { return _name; } set { _name = value; } } private double? _winrate = null; [ColumnInfoAttribute(DisplayName = "Win %", Format="1", SizeHint = "Win %XX", MidForColor = 50, MinForColor = 40, MaxForColor = 65.0)] public double? WinRate { get { return _winrate; } set { _winrate = value; } } private double _profitFactor = 1.0; [ColumnInfoAttribute(DisplayName = "Profit Factor", Format="2", SizeHint = "ProfitXX", MinForColor = 0.8, MidForColor = 1, MaxForColor = 2.5)] public double ProfitFactor { get { return _profitFactor; } set { _profitFactor = value; } } private string _lastSymbol = ""; [ColumnInfoAttribute(DisplayName = "Last Symbol", SizeHint = "MSFTXX", RealTimeUpdates = true)] public string LastSymbol { get { return _lastSymbol; } set { _lastSymbol = value; } } private double? _lastSignalPrice = null; [ColumnInfoAttribute(DisplayName = "Last Signal Price", SizeHint = "SymbolXX", Format="2", RealTimeUpdates = true)] public double? LastSignalPrice { get { return _lastSignalPrice; } set { _lastSignalPrice = value; } } private DateTime? _lastSignalTime = null; [ColumnInfoAttribute(Format = "relativetime", DisplayName = "Last Signal Time", SizeHint = "Last SignalXX", RealTimeUpdates = true)] public DateTime? LastSignalTime { get { return _lastSignalTime; } set { _lastSignalTime = value; } } private double? _lastStopPrice = null; [ColumnInfoAttribute(DisplayName = "Last Stop Price", SizeHint = "SymbolXX", Format="2", RealTimeUpdates = true)] public double? LastStopPrice { get { return _lastStopPrice; } set { _lastStopPrice = value; } } private double? _lastSmartStop = null; [ColumnInfoAttribute(DisplayName = "Last Smart Stop", SizeHint = "SymbolXX", Format="2", RealTimeUpdates = true)] public double? LastSmartStop { get { return _lastSmartStop; } set { _lastSmartStop = value; } } private double? _lastTargetPrice = null; [ColumnInfoAttribute(DisplayName = "Last Target Price", SizeHint = "SymbolXX", Format="2", RealTimeUpdates = true)] public double? LastTargetPrice { get { return _lastTargetPrice; } set { _lastTargetPrice = value; } } /// /// Sum of profit from each trade in this strategy /// [ColumnInfoAttribute(DisplayName = "Profit", SizeHint = "XXXX.XX", Format = "dollars", RealTimeUpdates = true)] public double Profit { get { double? profit = _strategyTrades.Sum(x => x.Profit); if (profit.HasValue) return profit.Value; return 0.0; } } /// /// Sum of Non-Exit profit from each trade in this strategy /// [ColumnInfoAttribute(DisplayName = "Risk On Profit", SizeHint = "XXXX.XX", Format = "dollars", RealTimeUpdates = true)] public double NonExitProfit { get { double? nonExitProfit = _strategyTrades.Sum(x => x.NonExitProfit); if (nonExitProfit.HasValue) return nonExitProfit.Value; return 0.0; } } [ColumnInfoAttribute(DisplayName = "Profit Basis Points", SizeHint = "XXXX.XX", Format = "0", RealTimeUpdates = true, DefaultVisible = false)] public double ProfitBasisPoints { get { double? basisPoints = _strategyTrades.Sum(x => x.ProfitBasisPoints); if (basisPoints.HasValue) return basisPoints.Value; return 0.0; } } [ColumnInfoAttribute(DisplayName = "Open Profit", SizeHint = "XXXX.XX", Format = "dollars", RealTimeUpdates = true, DefaultVisible = false)] public double OpenProfit { get { List openTrades = _strategyTrades.Where(x => !x.ExitTime.HasValue).ToList(); if (openTrades.Count > 0) { double? profit = openTrades.Sum(x => x.Profit); if (profit.HasValue) return profit.Value; } return 0.0; } } [ColumnInfoAttribute(DisplayName = "Open Profit Basis Points", SizeHint = "XXXX.XX", Format = "0", RealTimeUpdates = true, DefaultVisible = false)] public double OpenProfitBasisPoints { get { List openTrades = _strategyTrades.Where(x => !x.ExitTime.HasValue).ToList(); if (openTrades.Count > 0) { double? profit = openTrades.Sum(x => x.ProfitBasisPoints); if (profit.HasValue) return profit.Value; } return 0.0; } } [ColumnInfoAttribute(DisplayName = "Risk Off Profit", SizeHint = "XXXX.XX", Format = "dollars", RealTimeUpdates = true, DefaultVisible = false)] public double ClosedProfit { get { List closedTrades = _strategyTrades.Where(x => x.ExitTime.HasValue).ToList(); if (closedTrades.Count > 0) { double? profit = closedTrades.Sum(x => x.Profit); if (profit.HasValue) return profit.Value; } return 0.0; } } [ColumnInfoAttribute(DisplayName = "Closed Profit Basis Points", SizeHint = "XXXX.XX", Format = "0", RealTimeUpdates = true, DefaultVisible = false)] public double ClosedProfitBasisPoints { get { List closedTrades = _strategyTrades.Where(x => x.ExitTime.HasValue).ToList(); if (closedTrades.Count > 0) { double? profit = closedTrades.Sum(x => x.ProfitBasisPoints); if (profit.HasValue) return profit.Value; } return 0.0; } } [ColumnInfoAttribute(DisplayName = "Trades Today", SizeHint = "XXXX", Format = "0", RealTimeUpdates = true)] public int TradesToday { get { return _strategyTrades.Count; } } [ColumnInfoAttribute(DisplayName = "Open Trades Today", SizeHint = "XXXX", Format = "0", RealTimeUpdates = true, DefaultVisible = false)] public int OpenTradesToday { get { return _strategyTrades.Where(x => x.IsOpen).Count(); } } [ColumnInfoAttribute(DisplayName = "Closed Trades Today", SizeHint = "XXXX", Format = "0", RealTimeUpdates = true, DefaultVisible = false)] public int ClosedTradesToday { get { return _strategyTrades.Where(x => !x.IsOpen).Count(); } } [ColumnInfoAttribute(DisplayName = "Average Profit Per Trade Today", SizeHint = "XXXX.XX", Format = "dollars", RealTimeUpdates = true)] public double? AvgProfitToday { get { if (_strategyTrades.Count > 0) return _strategyTrades.Where(x => x.Profit.HasValue).Sum(x => x.Profit.Value) / _strategyTrades.Count; else return null; } } [ColumnInfoAttribute(DisplayName = "Win % Today", SizeHint = "XXXX", Format = "1", RealTimeUpdates = true, MidForColor = 50, MinForColor = 15, MaxForColor = 85.0)] public double? WinRateToday { get { if (_strategyTrades.Count > 0) return (double)_strategyTrades.Where(x => x.Profit.HasValue && x.Profit.Value > 0).Count() / _strategyTrades.Count * 100; else return null; } } private double _totalTrades = 0; [ColumnInfoAttribute(DisplayName = "Total Trades", Format="0", SizeHint = "XXXXXXX")] public double TotalTrades { get { return _totalTrades; } set { _totalTrades = value; } } private double _maxTradesPerDay = 0.0; [ColumnInfoAttribute(DisplayName = "Max Trades Per Day (observed)", SizeHint = "XXXXXXX", Format="0")] public double MaxTradesPerDay { get { return _maxTradesPerDay; } set { _maxTradesPerDay = value; } } [ColumnInfoAttribute(DisplayName = "Recent Performance", Format = "thermograph", SizeHint = "XXXXXXXXXXXXXXXXXXXXXXX", DefaultVisible = true)] public Thermograph RecentPerformance { get; set; } [ColumnInfoAttribute(DisplayName = "Time Stop", SizeHint = "XXXXXXXXXX")] public string TimeStop { get { if (null == _oddsMakerRequest) return ""; else { if (_oddsMakerRequest.UseExitTimeMinutesAfter) return _oddsMakerRequest.ExitTimeMinutesAfter + "min"; else if (_oddsMakerRequest.UseExitAtTimeOfDay) { int minutesBeforeClose = _oddsMakerRequest.ExitTimeMinutesBefore; DateTime marketClose = GuiEnvironment.GetMarketCloseLocalTime(); DateTime timeStop = marketClose.AddMinutes(-minutesBeforeClose); return timeStop.ToString(GuiEnvironment.AlertTimeShortFormat); } else if (_oddsMakerRequest.UseExitTimeFutureOpen) { DateTime marketOpen = GuiEnvironment.GetMarketOpenLocalTime(); return "+" + _oddsMakerRequest.ExitTimeOpenDays + " days at " + marketOpen.ToString(GuiEnvironment.AlertTimeShortFormat); } else if (_oddsMakerRequest.UseExitTimeFutureClose) { DateTime marketClose = GuiEnvironment.GetMarketCloseLocalTime(); return "+" + _oddsMakerRequest.ExitTimeCloseDays + " days at " + marketClose.ToString(GuiEnvironment.AlertTimeShortFormat); } } return ""; } } [ColumnInfoAttribute(DisplayName = "Stop Loss", SizeHint = "XXXXXXXXXX")] public string StopLoss { get { if (null == _oddsMakerRequest || !_oddsMakerRequest.UseStopLoss) return ""; else { if (_oddsMakerRequest.UseStopFilter) { ConfigurationWindowManager configurationWindowManager = AiUtils.ConfigurationWindowManager(_connectionMaster, _config); Filter filter = configurationWindowManager.FindFilter(_oddsMakerRequest.StopFilter); if (null != filter) return filter.LongDescription; return _oddsMakerRequest.StopFilter; } else if (_oddsMakerRequest.StopLoss.HasValue) { if (_oddsMakerRequest.UsePercent) return _oddsMakerRequest.StopLoss.Value.ToString("N2") + "%"; else return "$" + _oddsMakerRequest.StopLoss.Value.ToString("N2"); } } return ""; } } [ColumnInfoAttribute(DisplayName = "Profit Target", SizeHint = "XXXXXXXXXX")] public string ProfitTarget { get { if (null == _oddsMakerRequest || !_oddsMakerRequest.UseProfitTarget) return ""; else { if (_oddsMakerRequest.UseTargetFilter) { ConfigurationWindowManager configurationWindowManager = AiUtils.ConfigurationWindowManager(_connectionMaster, _config); Filter filter = configurationWindowManager.FindFilter(_oddsMakerRequest.TargetFilter); if (null != filter) return filter.LongDescription; return _oddsMakerRequest.TargetFilter; } else if (_oddsMakerRequest.ProfitTarget.HasValue) { if (_oddsMakerRequest.UsePercent) return _oddsMakerRequest.ProfitTarget.Value.ToString("N2") + "%"; else return "$" + _oddsMakerRequest.ProfitTarget.Value.ToString("N2"); } } return ""; } } private string _config = ""; [Browsable(false)] public string Config { get { return _config; } set { _config = ScrubConfig(value); //SetConfig(); } } private bool _historyComplete = false; [Browsable(false)] public bool HistoryComplete { get { return _historyComplete; } set { _historyComplete = value; } } private bool _cloudLinkLoaded = false; [Browsable(false)] public bool CloudLinkLoaded { get { return _cloudLinkLoaded; } set { _cloudLinkLoaded = value; } } private DateTime? _lastUpdated = null; [Browsable(false)] public DateTime? LastUpdated { get { return _lastUpdated; } set { _lastUpdated = value; } } private string _cloudLink = ""; [Browsable(false)] public string CloudLink { get { return _cloudLink; } set { _cloudLink = value; LoadCloudLink(); } } private bool _isLong = true; [ColumnInfoAttribute(DisplayName = "L/S", Format="longshort", SizeHint = "XXXXXXX")] public bool IsLong { get { return _isLong; } set { _isLong = value; } } private string _timeframe = ""; [ColumnInfoAttribute(DisplayName = "Timeframe", SizeHint = "XXXXXXXXXX")] public string TimeFrame { get { return _timeframe; } set { _timeframe = value; } } private DateTime? _optimizedDate = null; [ColumnInfoAttribute(DisplayName = "Optimized Date", Format = "t")] public DateTime? OptimizedDate { get { return _optimizedDate; } set { _optimizedDate = value; } } private DateTime? _creationDate = null; [ColumnInfoAttribute(DisplayName = "Creation Date", Format = "t")] public DateTime? CreationDate { get { return _creationDate; } set { _creationDate = value; } } private DateTime? _dataLastUpdated = null; [ColumnInfoAttribute(DisplayName = "Data Last Updated", Format = "relativetime", DefaultVisible = false, RealTimeUpdates = true)] public DateTime? DataLastUpdated { get { return _dataLastUpdated; } set { _dataLastUpdated = value; } } private StreamingAlerts _streamingAlerts = null; [Browsable(false)] public StreamingAlerts StreamingAlerts { get { return _streamingAlerts; } } private List _strategyTrades = new List(); [Browsable(false)] public List StrategyTrades { get { return _strategyTrades; } } [ColumnInfoAttribute(DisplayName = "Today Performance Risk Off", Format = "thermograph", SizeHint = "XXXXXXXXXXXXXXXXXXXXXXX", DefaultVisible = true)] public Thermograph TodayPerformance { get; set; } [ColumnInfoAttribute(DisplayName = "Today Performance Risk On", Format = "thermograph", SizeHint = "XXXXXXXXXXXXXXXXXXXXXXX", DefaultVisible = true)] public Thermograph TodayPerformanceNonExit { get; set; } [ColumnInfoAttribute(DisplayName = "Today Performance (BP)", Format = "thermograph", SizeHint = "XXXXXXXXXXXXXXXXXXXXXXX", DefaultVisible = true)] [Browsable(false)] public Thermograph TodayBasisPoints { get; set; } private ConnectionMaster _connectionMaster = null; public event NewAlertHandler onNewAlertReceived; public event NewStrategyTradeHandler onNewStrategyTradeReceived; public event CloudLinkLoadedHandler onCloudLinkLoaded; public event HistoryCompleteHandler HistoryCompleted; public AIStrategy() { _connectionMaster = GuiEnvironment.FindConnectionMaster(""); } /// /// Allows us to reset signals each day. /// private DateTime? _lastAlertReceived = null; private List _allAlerts = new List(); /// /// Adds an alert and it may convert it and add it to StrategyTrades if required. Should be called in order from oldest to most recent. /// /// Alert public void AddAlert(RowData rowData) { string symbol = rowData.GetSymbol(); DateTime? alertTime = rowData.GetTime(); if (!alertTime.HasValue) return; // if last alert received was yesterday, then reset alerts to a new day if (_lastAlertReceived.HasValue && _lastAlertReceived.Value.ToMarketTimeZone().ToString("yyyy-MM-dd") != alertTime.Value.ToMarketTimeZone().ToString("yyyy-MM-dd")) ResetAlerts(); if (TooEarly(alertTime.Value)) return; if (TooLate(alertTime.Value)) return; _allAlerts.Add(rowData); // if there are multiple signals per symbol, only add the first one if (_strategyTrades.Where(x => x.Symbol == symbol).Count() > 0) return; StrategyTrade strategyTrade = GetStrategyTrade(rowData); SetLastSignalData(strategyTrade); if (null != onNewStrategyTradeReceived) onNewStrategyTradeReceived(strategyTrade, this); } private bool TooEarly(DateTime entryTime) { int minutesAfterOpen = GetStartTime(); return GuiEnvironment.GetMarketOpenInMarketTimeZone().AddMinutes(minutesAfterOpen) > entryTime.ToMarketTimeZone(); } private bool TooLate(DateTime entryTime) { int minutesBeforeClose = GetEndTime(); return GuiEnvironment.GetMarketCloseInMarketTimeZone().AddMinutes(-minutesBeforeClose) < entryTime.ToMarketTimeZone(); } private int GetStartTime() { int hours = _oddsMakerRequest.EntryHoursStart; int minutes = _oddsMakerRequest.EntryMinutesStart; return hours * 60 + minutes; } private int GetEndTime() { int hours = _oddsMakerRequest.EntryHoursEnd; int minutes = _oddsMakerRequest.EntryMinutesEnd; return hours * 60 + minutes; } public StrategyTrade GetStrategyTrade(RowData rowData) { string symbol = rowData.GetSymbol(); int? entryTimeT = rowData.GetAsInt("ENTRY_TIME", 0); DateTime? entryTime = rowData.GetTime(); if (entryTimeT.HasValue && !entryTime.HasValue) entryTime = ServerFormats.FromTimeT(entryTimeT.Value); double entryPrice = rowData.GetPrice(); if (entryPrice == 0.0) entryPrice = rowData.GetAsDouble("ENTRY_PRICE", 0.0); StrategyTrade strategyTrade = new StrategyTrade(); string id = rowData.GetAsString("ID", ""); bool newTrade = false; if (_strategyTrades.Where(x => x.ID == id).Count() > 0) strategyTrade = _strategyTrades.Where(x => x.ID == id).First(); else { newTrade = true; strategyTrade.ID = id; } strategyTrade.IsNew = rowData.GetAsDouble("NEW", 0.0) == 1; //System.Diagnostics.Debug.WriteLine("[GetStrategyTrade] IsNew is " + strategyTrade.IsNew + " for " + strategyTrade.Symbol); double exitTimeT = rowData.GetAsDouble("EXIT_TIME", 0.0); if (exitTimeT != 0.0) strategyTrade.ExitTime = ServerFormats.FromTimeT((int)exitTimeT); strategyTrade.ExitReason = rowData.GetAsString("EXIT_REASON", ""); if (rowData.GetAsDouble("EXIT_PRICE", 0.0) != 0.0) strategyTrade.ExitPrice = rowData.GetAsDouble("EXIT_PRICE", 0.0); strategyTrade.Symbol = symbol; strategyTrade.EntryTime = entryTime.Value; strategyTrade.EntryPrice = entryPrice; strategyTrade.IsLong = _isLong; if (rowData.GetAsDouble("STOP_PRICE", 0.0) != 0.0) strategyTrade.StopPrice = rowData.GetAsDouble("STOP_PRICE", 0.0); else strategyTrade.StopPrice = GetStopPrice(entryPrice, rowData); strategyTrade.Shares = GetShares(strategyTrade.EntryPrice, strategyTrade.StopPrice); if (rowData.GetAsDouble("TARGET_PRICE", 0.0) != 0.0) strategyTrade.TargetPrice = rowData.GetAsDouble("TARGET_PRICE", 0.0); else strategyTrade.TargetPrice = GetTargetPrice(entryPrice, rowData); if (rowData.GetAsDouble("TIME_STOP", 0.0) != 0.0) strategyTrade.TimeStop = ServerFormats.FromTimeT((long)rowData.GetAsDouble("TIME_STOP", 0.0)).Value; else strategyTrade.TimeStop = GetTimeStop(entryTime); if (rowData.GetAsDouble("PROFIT", 0.0) != 0) strategyTrade.Profit = rowData.GetAsDouble("PROFIT", 0.0) * (double)strategyTrade.Shares; if (rowData.GetAsDouble("NONEXIT_PROFIT", 0.0) != 0) strategyTrade.NonExitProfit = rowData.GetAsDouble("NONEXIT_PROFIT", 0.0) * (double)strategyTrade.Shares; else strategyTrade.SetNonExitProfitFromLast(); int? tradeZone = rowData.GetAsInt("TRADE_ZONE", 0); if (tradeZone.HasValue) strategyTrade.TradeZone = tradeZone.Value; if (rowData.GetAsDouble("PROFIT_CHANGE_15", 0.0) != 0) strategyTrade.ProfitChange15 = rowData.GetAsDouble("PROFIT_CHANGE_15", 0.0) * (double)strategyTrade.Shares; if (rowData.GetAsDouble("PROFIT_CHANGE_5", 0.0) != 0) strategyTrade.ProfitChange5 = rowData.GetAsDouble("PROFIT_CHANGE_5", 0.0) * (double)strategyTrade.Shares; if (rowData.GetAsDouble("SMART_STOP", 0.0) != 0) strategyTrade.SmartStop = rowData.GetAsDouble("SMART_STOP", 0.0); else if (rowData.GetAsDouble("c_SmartStopD", 0.0) != 0) strategyTrade.SmartStop = rowData.GetAsDouble("c_SmartStopD", 0.0); strategyTrade.Strategy = this; _strategyTrades.Add(strategyTrade); if (newTrade) { SetLastSignalData(strategyTrade); if (null != onNewStrategyTradeReceived) onNewStrategyTradeReceived(strategyTrade, this); } return strategyTrade; } /// /// Gets the number of shares that should be used. The stop price is needed when the user has chosen AiPositionSizingType.BasedOnStopLoss. /// /// The entry price. /// The stop price. /// public static int GetShares(double entryPrice, double? stopPrice) { if (GuiEnvironment.AiPositionSizingType == GuiEnvironment.AiPositionSizing.FixedShares) return GuiEnvironment.AiSharesPerTrade; else if (GuiEnvironment.AiPositionSizingType == GuiEnvironment.AiPositionSizing.FixedDollars) return (int)(GuiEnvironment.AiDollarsPerTrade / entryPrice); else if (GuiEnvironment.AiPositionSizingType == GuiEnvironment.AiPositionSizing.BasedOnStopLoss && stopPrice.HasValue && stopPrice.Value > 0) return (int)Math.Round(GuiEnvironment.AiRiskDollars / Math.Abs(entryPrice - stopPrice.Value)); else return 1; } /// /// Returns the time stop based on the strategy. Might be based on the entry time depending on timed exit selection. /// /// Entry time of trade /// DateTime of private DateTime? GetTimeStop(DateTime? entryTime) { DateTime? toReturn = null; if (_oddsMakerRequest.UseExitTimeFutureClose) { int days = _oddsMakerRequest.ExitTimeOpenDays; toReturn = GuiEnvironment.GetMarketCloseLocalTime(entryTime.Value.AddDays(days)); if (toReturn.Value.DayOfWeek == DayOfWeek.Saturday || toReturn.Value.DayOfWeek == DayOfWeek.Sunday) toReturn = toReturn.Value.AddDays(2); } else if (_oddsMakerRequest.UseExitTimeFutureOpen) { int days = _oddsMakerRequest.ExitTimeOpenDays; toReturn = GuiEnvironment.GetMarketOpenLocalTime(entryTime.Value.AddDays(days)); if (toReturn.Value.DayOfWeek == DayOfWeek.Saturday || toReturn.Value.DayOfWeek == DayOfWeek.Sunday) toReturn = toReturn.Value.AddDays(2); } else if (_oddsMakerRequest.UseExitAtTimeOfDay) { int minutesBefore = _oddsMakerRequest.ExitTimeMinutesBefore; toReturn = GuiEnvironment.GetMarketCloseLocalTime(entryTime.Value).AddMinutes(-minutesBefore); } else { int minutesAfter = _oddsMakerRequest.ExitTimeMinutesAfter; toReturn = entryTime.Value.AddMinutes(minutesAfter); DateTime timeStopMarketClose = GuiEnvironment.GetMarketCloseLocalTime(toReturn.Value); if (toReturn.Value > timeStopMarketClose) toReturn = timeStopMarketClose; } return toReturn; } /// /// Returns the target price for a given entry price. /// /// Entry price for the trade /// Row data from alert /// Target price suitable for using as a limit price. private double? GetTargetPrice(double entryPrice, RowData alertData) { if (null != _oddsMakerRequest && _oddsMakerRequest.UseProfitTarget) { if (_oddsMakerRequest.UseTargetFilter && _oddsMakerRequest.TargetFilter != "") { double targetDistance = alertData.GetAsDouble("c_" + _oddsMakerRequest.TargetFilter, 0.0); if (targetDistance == 0.0) return null; else if (_isLong) return entryPrice + targetDistance; else return entryPrice - targetDistance; } else if (_oddsMakerRequest.ProfitTarget.HasValue) { if (_isLong) if (_oddsMakerRequest.UseDollars) return entryPrice + _oddsMakerRequest.ProfitTarget.Value; else { double targetPercent = _oddsMakerRequest.ProfitTarget.Value; double targetDistance = targetPercent * entryPrice; return entryPrice + targetDistance; } else { if (_oddsMakerRequest.UseDollars) return entryPrice - _oddsMakerRequest.ProfitTarget.Value; else { double targetPercent = _oddsMakerRequest.ProfitTarget.Value; double targetDistance = targetPercent * entryPrice; return entryPrice - targetDistance; } } } else return null; } return null; } /// /// Returns stop price for a given entry price. /// /// Entry price for the trade. /// Row data for the alert /// Stop price level. private double? GetStopPrice(double entryPrice, RowData alertData) { if ( null != _oddsMakerRequest && _oddsMakerRequest.UseStopLoss) { if (_oddsMakerRequest.UseStopFilter && _oddsMakerRequest.StopFilter != "") { double stopDistance = alertData.GetAsDouble("c_" + _oddsMakerRequest.StopFilter, 0.0); if (stopDistance == 0.0) return null; else if (_isLong) return entryPrice - stopDistance; else return entryPrice + stopDistance; } else if (_oddsMakerRequest.StopLoss.HasValue) { if (_isLong) if (_oddsMakerRequest.UseDollars) return entryPrice - _oddsMakerRequest.StopLoss.Value; else { double stopPercent = _oddsMakerRequest.StopLoss.Value / 100; double stopDistance = stopPercent * entryPrice; return entryPrice - stopDistance; } else { if (_oddsMakerRequest.UseDollars) return entryPrice + _oddsMakerRequest.StopLoss.Value; else { double stopPercent = _oddsMakerRequest.StopLoss.Value / 100; double stopDistance = stopPercent * entryPrice; return entryPrice + stopDistance; } } } else return null; } return null; } /// /// Resets all private variables for new trading day /// private void ResetAlerts() { _allAlerts.Clear(); _lastAlertReceived = null; _strategyTrades.Clear(); } private bool _historyRunning = false; private History _history; private List _historyQueue = new List(); public void LoadHistory() { DateTime now = GuiEnvironment.GetNowInMarketTimeZone(); DateTime marketOpen = GuiEnvironment.GetMarketOpenInMarketTimeZone(); // don't load history if we're in the pre market if (now < marketOpen) { if (null != HistoryCompleted) HistoryCompleted(this); return; } HistoryRequest historyRequest = new HistoryRequest(); historyRequest.Config = _config; historyRequest.EndTime = GuiEnvironment.GetMarketOpenLocalTime(); historyRequest.MaxCount = 100; historyRequest.StartTime = null; _history = _connectionMaster.HistoryManager.GetHistory(historyRequest); _history.HistoryData += _history_HistoryData; _history.HistoryStatus += _history_HistoryStatus; _historyQueue.Clear(); _historyRunning = true; _history.Start(); } void _history_HistoryStatus(History sender) { _historyRunning = sender.HistoryDisposition != HistoryDisposition.Done && sender.HistoryDisposition != HistoryDisposition.NotSent; if (sender.HistoryDisposition == HistoryDisposition.MoreAvailable) _history.Start(); if (sender.HistoryDisposition == HistoryDisposition.Done) LoadHistoryQueue(); } private void LoadHistoryQueue() { try { foreach (RowData rowData in _historyQueue) { AddAlert(rowData); } _historyQueue.Clear(); if (null != onNewAlertReceived) onNewAlertReceived(null, this); _historyComplete = true; if (null != HistoryCompleted) HistoryCompleted(this); } catch (Exception e) { string debugView = e.StackTrace; } } void _history_HistoryData(List alerts, History sender) { foreach (RowData rowData in alerts) { _historyQueue.Insert(0, rowData); } } private void SetLastSignalData(StrategyTrade trade) { string symbol = trade.Symbol; _lastSymbol = symbol; double price = trade.EntryPrice; if (price != 0.0) _lastSignalPrice = price; // Depending on the local system clock, this could display to the user as in the future. // If that's the case, just use current system time to avoid that situation. DateTime? lastSignalTime = trade.EntryTime; if (lastSignalTime.HasValue) { if (lastSignalTime > ServerFormats.Now) _lastSignalTime = ServerFormats.Now; else _lastSignalTime = lastSignalTime; } if (trade.StopPrice.HasValue) _lastStopPrice = trade.StopPrice.Value; if (trade.TargetPrice.HasValue) _lastTargetPrice = trade.TargetPrice.Value; if (trade.SmartStop.HasValue) _lastSmartStop = trade.SmartStop.Value; _lastUpdated = ServerFormats.Now; } public RowData ToRowData() { RowData rowData = new RowData(); rowData.Data.Add("Strategy", _name); rowData.Data.Add("WinRate", _winrate); rowData.Data.Add("ProfitFactor", _profitFactor); rowData.Data.Add("LastSymbol", _lastSymbol); if (null != _lastSignalTime) rowData.Data.Add("LastSignalTime", _lastSignalTime); if (null != _lastSignalPrice) rowData.Data.Add("LastSignalPrice", _lastSignalPrice); rowData.Data.Add("TimeFrame", _timeframe); rowData.Data.Add("IsLong", _isLong); rowData.Data.Add("MaxTradesPerDay", _maxTradesPerDay); rowData.Data.Add("TotalTrades", _totalTrades); rowData.Data.Add("LastUpdated", _lastUpdated); rowData.Data.Add("RecentPerformance", RecentPerformance); rowData.Data.Add("Profit", Profit); rowData.Data.Add("NonExitProfit", NonExitProfit); rowData.Data.Add("ProfitBasisPoints", ProfitBasisPoints); rowData.Data.Add("ClosedProfit", ClosedProfit); rowData.Data.Add("ClosedProfitBasisPoints", ClosedProfitBasisPoints); rowData.Data.Add("OpenProfit", OpenProfit); rowData.Data.Add("OpenProfitBasisPoints", OpenProfitBasisPoints); rowData.Data.Add("TradesToday", TradesToday); rowData.Data.Add("OpenTradesToday", OpenTradesToday); rowData.Data.Add("ClosedTradesToday", ClosedTradesToday); rowData.Data.Add("AvgProfitToday", AvgProfitToday); rowData.Data.Add("WinRateToday", WinRateToday); rowData.Data.Add("TimeStop", TimeStop); rowData.Data.Add("StopLoss", StopLoss); rowData.Data.Add("ProfitTarget", ProfitTarget); rowData.Data.Add("TodayPerformance", TodayPerformance); rowData.Data.Add("TodayBasisPoints", TodayBasisPoints); rowData.Data.Add("TodayPerformanceNonExit", TodayPerformanceNonExit); if (_optimizedDate.HasValue) rowData.Data.Add("OptimizedDate", _optimizedDate); if (_creationDate.HasValue) rowData.Data.Add("CreationDate", _creationDate); if (_lastStopPrice.HasValue) rowData.Data.Add("LastStopPrice", _lastStopPrice); if (_lastSmartStop.HasValue) rowData.Data.Add("LastSmartStop", _lastSmartStop); if (_lastTargetPrice.HasValue) rowData.Data.Add("LastTargetPrice", _lastTargetPrice); if (_dataLastUpdated.HasValue) rowData.Data.Add("DataLastUpdated", _dataLastUpdated); rowData.Data.Add("object", this); return rowData; } private void SetConfig() { if (null != _streamingAlerts) _streamingAlerts.Stop(); _streamingAlerts = _connectionMaster.StreamingAlertsManager.GetAlerts(_config); StartStreamingAlerts(); } private void StartStreamingAlerts() { if (_streamingAlerts.Config != "") { _streamingAlerts.StreamingAlertsData += _streamingAlerts_StreamingAlertsData; _streamingAlerts.StreamingAlertsConfig += _streamingAlerts_StreamingAlertsConfig; _streamingAlerts.Start(); } } void _streamingAlerts_StreamingAlertsConfig(StreamingAlerts source) { } void _streamingAlerts_StreamingAlertsData(List data, StreamingAlerts source) { foreach (RowData rowData in data) { if (rowData.GetSymbol() != "") AddAlert(rowData); if (null != onNewAlertReceived) onNewAlertReceived(rowData, this); } } private void LoadCloudLink() { Dictionary command = TalkWithServer.CreateMessage("command", "cloud_import", "code", _cloudLink); SendLoadImportCommand(command); } private void SendLoadImportCommand(object command) { try { _connectionMaster.SendManager.SendMessage((Dictionary)command, LoadImportCommandResponse, false, command); } catch (Exception e) { string debugView = e.StackTrace; } } private void LoadImportCommandResponse(byte[] body, object clientid) { if (null == body) SendLoadImportCommand(clientid); else LoadImportCommandResponse(body); } private OddsMakerConfiguration.OddsMakerConfigMemento _oddsMakerRequest; private void LoadImportCommandResponse(byte[] body) { XmlNode wrapper = XmlHelper.Get(body).Node(0).Node("LAYOUT"); bool clearPrevious = wrapper.Property("CLEAR_PREVIOUS", false); XmlDocument layout = XmlHelper.Get(Encoding.UTF8.GetBytes(wrapper.Text())); if (null == layout) { StringBuilder sb = new StringBuilder("Unable to load this item."); if (wrapper.Text() == "") sb.Append(" (Not found.)"); else sb.Append(" (Corrupted.)"); return; } _oddsMakerRequest = GetOddsMakerRequest(layout); _cloudLinkLoaded = true; if (null != onCloudLinkLoaded) onCloudLinkLoaded(this); if (GuiEnvironment.AppConfig.Node("GUI_LIB").Node("AI_STRATEGIES").Node("TRADE_CLIENT").Property("VALUE", 0) == 1) LoadHistory(); } private OddsMakerConfiguration.OddsMakerConfigMemento GetOddsMakerRequest(XmlDocument layout) { OddsMakerConfiguration.OddsMakerConfigMemento toReturn = new OddsMakerConfiguration.OddsMakerConfigMemento(); if (layout.HasChildNodes) { XmlNode layoutNode = layout.FirstChild; XmlNode windowNode = layoutNode.Node("WINDOW"); if (null != windowNode) { try { toReturn.Load(windowNode); } catch (Exception e) { string debugView = e.StackTrace; } } } return toReturn; } internal void RefreshStrategyTrade(StrategyTrade strategyTrade, RowData rowData, LumenWorks.Framework.IO.Csv.CsvReader csvReader = null) { strategyTrade.Shares = GetShares(strategyTrade.EntryPrice, strategyTrade.StopPrice); strategyTrade.Profit = rowData.GetAsDouble("PROFIT", 0.0) * (double)strategyTrade.Shares; strategyTrade.ProfitChange15 = rowData.GetAsDouble("PROFIT_CHANGE_15", 0.0) * (double)strategyTrade.Shares; strategyTrade.ProfitChange5 = rowData.GetAsDouble("PROFIT_CHANGE_5", 0.0) * (double)strategyTrade.Shares; strategyTrade.MaxProfit = rowData.GetAsDouble("MAX_PROFIT", 0.0) * (double)strategyTrade.Shares; strategyTrade.MinProfit = rowData.GetAsDouble("MIN_PROFIT", 0.0) * (double)strategyTrade.Shares; strategyTrade.LastPrice = rowData.GetAsDouble("LAST", strategyTrade.EntryPrice); if (!double.IsNaN(rowData.GetAsDouble("NONEXIT_PROFIT", double.NaN))) strategyTrade.NonExitProfit = rowData.GetAsDouble("NONEXIT_PROFIT", double.NaN) * (double)strategyTrade.Shares; else strategyTrade.SetNonExitProfitFromLast(); strategyTrade.IsNew = rowData.GetAsDouble("NEW", 0.0) == 1; int? tradeZone = rowData.GetAsInt("TRADE_ZONE", 0); if (tradeZone.HasValue) strategyTrade.TradeZone = tradeZone.Value; if (rowData.GetAsDouble("EXIT_PRICE", 0.0) != 0.0) strategyTrade.ExitPrice = rowData.GetAsDouble("EXIT_PRICE", 0.0); else strategyTrade.ExitPrice = null; if (rowData.GetAsDouble("EXIT_TIME", 0.0) > 0) strategyTrade.ExitTime = ServerFormats.FromTimeT((int)rowData.GetAsDouble("EXIT_TIME", 0.0)); else strategyTrade.ExitTime = null; if (rowData.GetAsDouble("MAX_PROFIT_TIME", 0.0) != 0.0) strategyTrade.MaxProfitTime = ServerFormats.FromTimeT((int)rowData.GetAsDouble("MAX_PROFIT_TIME", 0.0)); else strategyTrade.MaxProfitTime = null; if (rowData.GetAsDouble("MIN_PROFIT_TIME", 0.0) != 0.0) strategyTrade.MinProfitTime = ServerFormats.FromTimeT((int)rowData.GetAsDouble("MIN_PROFIT_TIME", 0.0)); else strategyTrade.MinProfitTime = null; strategyTrade.ExitReason = rowData.GetAsString("EXIT_REASON", ""); if (null != csvReader && csvReader.GetFieldHeaders().Contains("PROFIT_HISTORY") && csvReader["PROFIT_HISTORY"] != "") strategyTrade.TodayPerformance = RowDataHelper.GetThermograph(csvReader["PROFIT_HISTORY"], strategyTrade.Shares, 1); else strategyTrade.TodayPerformance = null; if (null != csvReader && csvReader.GetFieldHeaders().Contains("PROFIT_HISTORY_NONEXIT") && csvReader["PROFIT_HISTORY_NONEXIT"] != "") strategyTrade.TodayPerformanceNonExit = RowDataHelper.GetThermograph(csvReader["PROFIT_HISTORY_NONEXIT"], strategyTrade.Shares, 1); else strategyTrade.TodayPerformanceNonExit = null; strategyTrade.DataLastUpdated = ServerFormats.Now; } internal void Dispose() { if (null != _streamingAlerts) { _streamingAlerts.Stop(); _streamingAlerts = null; } if (null != _history) { _history.Stop(); _history = null; } } private readonly string SMART_STOP_CODE = "SmartStopD"; private string ScrubConfig(string config) { NameValueCollection parameters = HttpUtility.ParseQueryString(config); bool found = false; int largestShow = 0; foreach (string name in parameters.AllKeys) { if (name.StartsWith("show")) { if (parameters[name] == SMART_STOP_CODE) found = true; string number = name.Replace("show", ""); int showNumber = -1; if (int.TryParse(number, out showNumber)) { if (showNumber > largestShow) largestShow = showNumber; } } } if (!found) config += "&show" + (largestShow + 1) + "=" + SMART_STOP_CODE; return config; } internal void ComputeTodayPerformance() { try { if (_strategyTrades.Count > 0) { List profits = new List(); List profitsNonExit = new List(); List basisPoints = new List(); bool foundRiskOffProfit = false; bool foundNonExitProfit = false; DateTime entryFirstTrade = _strategyTrades.Min(x => x.EntryTime); if (entryFirstTrade > GuiEnvironment.GetMarketOpenLocalTime(entryFirstTrade) && entryFirstTrade < GuiEnvironment.GetMarketCloseLocalTime(entryFirstTrade)) { DateTime entryTime = entryFirstTrade; DateTime now = ServerFormats.Now; while (entryTime < GuiEnvironment.GetMarketCloseLocalTime(entryTime) && entryTime < now) { double profit = 0; double profitNonExit = 0; double basisPoint = 0; foreach (StrategyTrade strategyTrade in _strategyTrades) { TimeSpan sinceEntry = entryTime - strategyTrade.EntryTime; double minutesSinceEntry = sinceEntry.TotalMinutes; if (minutesSinceEntry > 0) { int index = (int)minutesSinceEntry; TimeSpan sinceExit = TimeSpan.MinValue; if (strategyTrade.ExitTime.HasValue) { sinceExit = entryTime - strategyTrade.ExitTime.Value; if (sinceExit.TotalMinutes > 0) { profit += strategyTrade.Profit.Value; basisPoint += strategyTrade.ProfitBasisPoints.Value; } } if (null != strategyTrade.TodayPerformance && null != strategyTrade.TodayPerformance.Values && strategyTrade.TodayPerformance.Values.Count >= index + 1) { double thisProfit = strategyTrade.TodayPerformance.Values[index]; profit += thisProfit; double basisPointAtTime = thisProfit / strategyTrade.EntryPrice * 100 * 100; basisPoint += basisPointAtTime; foundRiskOffProfit = true; } if (null != strategyTrade.TodayPerformanceNonExit && null != strategyTrade.TodayPerformanceNonExit.Values && strategyTrade.TodayPerformanceNonExit.Values.Count >= index + 1) { double thisProfitNonExit = strategyTrade.TodayPerformanceNonExit.Values[index]; profitNonExit += thisProfitNonExit; foundNonExitProfit = true; } } } if (foundRiskOffProfit) profits.Add(profit); if (foundNonExitProfit) profitsNonExit.Add(profitNonExit); basisPoints.Add(basisPoint); entryTime = entryTime.AddMinutes(1); } } if (profits.Count > 0) { double max = Math.Max(profits.Max(), Math.Abs(profits.Min())); TodayPerformance = new Thermograph(); TodayPerformance.Max = max; TodayPerformance.Mid = 0; TodayPerformance.MidColor = Color.Black; TodayPerformance.Min = -max; TodayPerformance.Values = profits; } else TodayPerformance = null; if (profitsNonExit.Count > 0) { double max = Math.Max(profitsNonExit.Max(), Math.Abs(profitsNonExit.Min())); TodayPerformanceNonExit = new Thermograph(); TodayPerformanceNonExit.Max = max; TodayPerformanceNonExit.Mid = 0; TodayPerformanceNonExit.MidColor = Color.Black; TodayPerformanceNonExit.Min = -max; TodayPerformanceNonExit.Values = profitsNonExit; } else TodayPerformanceNonExit = null; if (basisPoints.Count > 0) { double max = Math.Max(basisPoints.Max(), Math.Abs(basisPoints.Min())); TodayBasisPoints = new Thermograph(); TodayBasisPoints.Max = max; TodayBasisPoints.Mid = 0; TodayBasisPoints.MidColor = Color.Black; TodayBasisPoints.Min = -max; TodayBasisPoints.Values = basisPoints; } } } catch (Exception e) { string debugView = e.StackTrace; } } } }