using MarketData.Generator; using MarketData.MarketDataModel; using MarketData.Utils; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using PortfolioManager.ViewModels; using PortfolioManager.UIUtils; using System.Collections.Specialized; using MarketData.Generator.CMTrend; using MarketData; using Position=MarketData.Generator.CMTrend.Position; using StopLimit=MarketData.MarketDataModel.StopLimit; using MarketData.DataAccess; using PortfolioManager.Interface; using Avalonia.Media; namespace PortfolioManager.Models { public class CMTPositionModelCollection:ObservableCollection { public void Add(ActivePositions activePositions) { foreach(Position position in activePositions)Add(new CMTPositionModel(position)); } public void Add(Positions allPositions) { foreach(Position position in allPositions) Add(new CMTPositionModel(position)); } public void OnCollectionChanged() { base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset,null)); } } public class CMTPositionModel : ModelBase, IPositionModel { private Position position=new Position(); private int priceChangeDirection=0; private double prevPrice=double.NaN; private double currentPriceLow=double.NaN; private DateTime lastUpdated=DateTime.Now; private double edgeRatio=double.NaN; public CMTPositionModel() { } public CMTPositionModel(Position position) { Symbol=position.Symbol; PurchaseDate=position.PurchaseDate; SellDate=position.SellDate; Shares=position.Shares; PurchasePrice=position.PurchasePrice; CurrentPrice=position.CurrentPrice; PositionRiskPercentDecimal=position.PositionRiskPercentDecimal; InitialStopLimit=position.InitialStopLimit; TrailingStopLimit=position.TrailingStopLimit; LastStopAdjustment=position.LastStopAdjustment; this.position.R=position.R; this.position.C=position.C; } public void UpdateProperties() { base.OnPropertyChanged("CurrentPrice"); base.OnPropertyChanged("MarketValue"); base.OnPropertyChanged("ActiveMarketValue"); base.OnPropertyChanged("GainLoss"); base.OnPropertyChanged("GainLossPcnt"); base.OnPropertyChanged("RMultiple"); base.OnPropertyChanged("EdgeRatioAsString"); base.OnPropertyChanged("CurrentPriceColor"); base.OnPropertyChanged("TrailingStopLimitColor"); base.OnPropertyChanged("InitialStopLimitColor"); base.OnPropertyChanged("TotalRiskExposureColor"); base.OnPropertyChanged("ActiveMarketValueColor"); base.OnPropertyChanged("GainLossColor"); base.OnPropertyChanged("GainLossPcntColor"); base.OnPropertyChanged("EdgeRatioAsStringColor"); base.OnPropertyChanged("RMultipleColor"); } public Position Position { get{return position;} set { Symbol=position.Symbol; PurchaseDate=position.PurchaseDate; SellDate=position.SellDate; Shares=position.Shares; PurchasePrice=position.PurchasePrice; CurrentPrice=position.CurrentPrice; PositionRiskPercentDecimal=position.PositionRiskPercentDecimal; InitialStopLimit=position.InitialStopLimit; TrailingStopLimit=position.TrailingStopLimit; LastStopAdjustment=position.LastStopAdjustment; this.position.R=position.R; this.position.C=position.C; } } public String Symbol { get { return position.Symbol; } set { position.Symbol = value; base.OnPropertyChanged("Symbol"); } } public IBrush SymbolColor { get { if (!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public DateTime PurchaseDate { get { return position.PurchaseDate; } set { position.PurchaseDate=value; base.OnPropertyChanged("PurchaseDate"); } } public IBrush PurchaseDateColor { get { DateGenerator dateGenerator=new DateGenerator(); if(!dateGenerator.IsMarketOpen(PurchaseDate)) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } public DateTime SellDate { get { return position.SellDate; } set { position.SellDate=value; base.OnPropertyChanged("SellDate"); } } public IBrush SellDateColor { get { if(Utility.IsEpoch(SellDate)) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); DateGenerator dateGenerator=new DateGenerator(); if(!dateGenerator.IsMarketOpen(SellDate)) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public int DaysHeld { get { DateGenerator dateGenerator=new DateGenerator(); if(Utility.IsEpoch(SellDate)) return dateGenerator.DaysBetween(PurchaseDate,DateTime.Now.Date); return dateGenerator.DaysBetween(PurchaseDate,SellDate); } } public IBrush DaysHeldColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** // Here we take R as based upon our StopLimit. public double R { get { if(position.TrailingStopLimit>position.PurchasePrice)return 0.00; // here we are considering the current risk/share which is based on our stop limit return position.TrailingStopLimit>position.PurchasePrice?0.00:position.PurchasePrice-position.TrailingStopLimit; } } public IBrush RColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public double TotalRiskExposure { get{return R*position.Shares;} } public IBrush TotalRiskExposureColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public double EdgeRatio { get{return edgeRatio;} set { edgeRatio=value; base.OnPropertyChanged("EdgeRatio"); base.OnPropertyChanged("EdgeRatioAsStringColor"); } } public String EdgeRatioAsString { get{return Utility.FormatNumber(edgeRatio,2,false);} } public IBrush EdgeRatioAsStringColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); if(double.IsNaN(edgeRatio))return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); if(edgeRatio>=1.00)return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); } } // *** public String RMultipleAsString { get{return Utility.FormatNumber((position.CurrentPrice-position.PurchasePrice)/(position.PurchasePrice-position.InitialStopLimit),2,false)+"R";} // always based on original position risk } public double RMultiple { get{return (position.CurrentPrice-position.PurchasePrice)/(position.PurchasePrice-position.InitialStopLimit);} // always based on original position risk } public IBrush RMultipleColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public double PositionRiskPercentDecimal { get{return position.PositionRiskPercentDecimal;} set { position.PositionRiskPercentDecimal=value; base.OnPropertyChanged("PositionRiskPercentDecimal"); } } public double InitialStopLimit { get { return position.InitialStopLimit; } set { position.InitialStopLimit=value; base.OnPropertyChanged("InitialStopLimit"); base.OnPropertyChanged("InitialStopLimitColor"); } } public IBrush InitialStopLimitColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); if(!Utility.IsEpoch(position.LastStopAdjustment)) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); // if we have a trailing stop then we are no longer using the initial stop StopLimit stopLimit=StopLimitDA.GetStopLimit(position.Symbol); if(null==stopLimit||!stopLimit.StopPrice.Equals(Math.Round(position.InitialStopLimit,2))) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Purple); if(currentPriceLow<=position.InitialStopLimit) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } public double TrailingStopLimit { get { return position.TrailingStopLimit; } set { position.TrailingStopLimit=value; base.OnPropertyChanged("TrailingStopLimit"); base.OnPropertyChanged("TrailingStopLimitColor"); } } public IBrush TrailingStopLimitColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); if(currentPriceLow<=position.TrailingStopLimit) { return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); } StopLimit stopLimit=StopLimitDA.GetStopLimit(position.Symbol); if(null==stopLimit || !stopLimit.StopPrice.Equals(Math.Round(position.TrailingStopLimit,2))) { return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Purple); } return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public DateTime LastStopAdjustment { get { return position.LastStopAdjustment; } set { position.LastStopAdjustment=value; base.OnPropertyChanged("LastStopAdjustment"); } } public IBrush LastStopAdjustmentColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public int DaysSinceLastStopAdjustment { get { if(!IsActivePosition)return int.MinValue; DateGenerator dateGenerator=new DateGenerator(); DateTime today=DateTime.Now; int daysSinceLastStopAdjustment=int.MinValue; if(Utility.IsEpoch(position.LastStopAdjustment)) daysSinceLastStopAdjustment=dateGenerator.DaysBetweenActual(today,position.PurchaseDate); else daysSinceLastStopAdjustment=dateGenerator.DaysBetweenActual(today,position.LastStopAdjustment); return daysSinceLastStopAdjustment; } } public IBrush DaysSinceLastStopAdjustmentColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); int daysSinceLastStopAdjustment=DaysSinceLastStopAdjustment; if(int.MinValue.Equals(daysSinceLastStopAdjustment))return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); if(daysSinceLastStopAdjustment>=90) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); else if(daysSinceLastStopAdjustment>=60) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); // I made them both red because yellow and purple looked horrible return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green); } } // *** public double Shares { get { return position.Shares; } set { position.Shares=value; base.OnPropertyChanged("Shares"); base.OnPropertyChanged("Exposure"); base.OnPropertyChanged("ActiveExposure"); base.OnPropertyChanged("MarketValue"); base.OnPropertyChanged("ActiveMarketValue"); base.OnPropertyChanged("GainLoss"); base.OnPropertyChanged("GainLossPcnt"); } } public IBrush SharesColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public double PurchasePrice { get { return position.PurchasePrice; } set { position.PurchasePrice=value; base.OnPropertyChanged("PurchasePrice"); base.OnPropertyChanged("Exposure"); base.OnPropertyChanged("ActiveExposure"); base.OnPropertyChanged("GainLoss"); base.OnPropertyChanged("GainLossPcnt"); } } public IBrush PurchasePriceColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public double CurrentPrice { get { return position.CurrentPrice; } set { if(position.CurrentPrice==value) return; position.CurrentPrice=value; if(double.IsNaN(prevPrice)) { prevPrice=position.CurrentPrice; priceChangeDirection=0; } else if(prevPrice>position.CurrentPrice) priceChangeDirection=-1; else if(prevPrice==position.CurrentPrice) priceChangeDirection=0; else priceChangeDirection=1; prevPrice=position.CurrentPrice; UpdateProperties(); } } public IBrush CurrentPriceColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); if(priceChangeDirection>0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green); else if(priceChangeDirection<0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public double CurrentPriceLow { get{return currentPriceLow;} set { if(currentPriceLow==value)return; currentPriceLow=value; base.OnPropertyChanged("CurrentPriceLow"); base.OnPropertyChanged("CurrentPriceLowAsString"); base.OnPropertyChanged("TrailingStopLimitColor"); base.OnPropertyChanged("InitialStopLimitColor"); } } // *** public String CurrentPriceLowAsString { get { return Utility.FormatCurrency(currentPriceLow); } } public IBrush CurrentPriceLowAsStringColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public DateTime LastUpdated { get { return lastUpdated; } set { lastUpdated=value; base.OnPropertyChanged("LastUpdated"); } } public IBrush LastUpdatedColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } // *** public double Exposure { get { return Shares*PurchasePrice; } } public double ActiveExposure { get { return IsActivePosition?Exposure:0.00; } } public IBrush ActiveExposureColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } public double MarketValue { get { return Shares*CurrentPrice; } } public double ActiveMarketValue { get { return IsActivePosition?MarketValue:0.00; } } public IBrush ActiveMarketValueColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); if(ActiveMarketValue>Exposure) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green); else if(ActiveMarketValue 0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green); else if (GainLoss < 0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } public double GainLossPcnt { get { return (MarketValue-Exposure)/Exposure; } } public IBrush GainLossPcntColor { get { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); if(GainLoss>0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green); else if(GainLoss<0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } } public bool IsActivePosition { get { return Utility.IsEpoch(SellDate)?true:false; } } } }