diff --git a/PortfolioManager/Assets/AmberTriangleUp.png b/PortfolioManager/Assets/AmberTriangleUp.png new file mode 100644 index 0000000..158a36a Binary files /dev/null and b/PortfolioManager/Assets/AmberTriangleUp.png differ diff --git a/PortfolioManager/Assets/DarkBlueTriangleUp.png b/PortfolioManager/Assets/DarkBlueTriangleUp.png new file mode 100644 index 0000000..9b50619 Binary files /dev/null and b/PortfolioManager/Assets/DarkBlueTriangleUp.png differ diff --git a/PortfolioManager/Assets/MagentaTriangleUp.png b/PortfolioManager/Assets/MagentaTriangleUp.png new file mode 100644 index 0000000..24b29c2 Binary files /dev/null and b/PortfolioManager/Assets/MagentaTriangleUp.png differ diff --git a/PortfolioManager/Assets/OrangeTriangleUp.png b/PortfolioManager/Assets/OrangeTriangleUp.png new file mode 100644 index 0000000..63d223b Binary files /dev/null and b/PortfolioManager/Assets/OrangeTriangleUp.png differ diff --git a/PortfolioManager/Cache/ImageCache.cs b/PortfolioManager/Cache/ImageCache.cs index 583688c..56a82be 100644 --- a/PortfolioManager/Cache/ImageCache.cs +++ b/PortfolioManager/Cache/ImageCache.cs @@ -10,7 +10,8 @@ namespace PortfolioManager.Cache { public class ImageCache : IDisposable { - public enum ImageType {BlueTriangleUp,GreenTriangleUp,GreenTriangleDown,RedTriangleUp,RedTriangleDown,YellowTriangleUp } + public enum ImageType {BlueTriangleUp,GreenTriangleUp,GreenTriangleDown,RedTriangleUp,RedTriangleDown,YellowTriangleUp, + OrangeTriangleUp, AmberTriangleUp,MagentaTriangleUp, DarkBlueTriangleUp} private Dictionary imageCache = new Dictionary(); private Object thisLock=new Object(); private static ImageCache imageCacheInstance=null; @@ -27,13 +28,17 @@ namespace PortfolioManager.Cache { pathToAssets = currentDirectory + "/Assets"; } - MDTrace.WriteLine(LogLevel.DEBUG,$"Reading assets from {pathToAssets}"); - imageCache.Add(ImageCache.ImageType.BlueTriangleUp,new Bitmap(pathToAssets+"/BlueTriangleUp.png")); - imageCache.Add(ImageCache.ImageType.GreenTriangleUp,new Bitmap(pathToAssets+"/GreenTriangleUp.png")); - imageCache.Add(ImageCache.ImageType.GreenTriangleDown,new Bitmap(pathToAssets+"/GreenTriangleDown.png")); - imageCache.Add(ImageCache.ImageType.RedTriangleUp,new Bitmap(pathToAssets+"/RedTriangleUp.png")); - imageCache.Add(ImageCache.ImageType.RedTriangleDown,new Bitmap(pathToAssets+"/RedTriangleDown.png")); - imageCache.Add(ImageCache.ImageType.YellowTriangleUp,new Bitmap(pathToAssets+"/YellowTriangleUp.png")); + MDTrace.WriteLine(LogLevel.DEBUG, $"Reading assets from {pathToAssets}"); + imageCache.Add(ImageCache.ImageType.BlueTriangleUp, new Bitmap(pathToAssets + "/BlueTriangleUp.png")); + imageCache.Add(ImageCache.ImageType.GreenTriangleUp, new Bitmap(pathToAssets + "/GreenTriangleUp.png")); + imageCache.Add(ImageCache.ImageType.GreenTriangleDown, new Bitmap(pathToAssets + "/GreenTriangleDown.png")); + imageCache.Add(ImageCache.ImageType.RedTriangleUp, new Bitmap(pathToAssets + "/RedTriangleUp.png")); + imageCache.Add(ImageCache.ImageType.RedTriangleDown, new Bitmap(pathToAssets + "/RedTriangleDown.png")); + imageCache.Add(ImageCache.ImageType.YellowTriangleUp, new Bitmap(pathToAssets + "/YellowTriangleUp.png")); + imageCache.Add(ImageCache.ImageType.OrangeTriangleUp, new Bitmap(pathToAssets + "/OrangeTriangleUp.png")); + imageCache.Add(ImageCache.ImageType.AmberTriangleUp, new Bitmap(pathToAssets + "/AmberTriangleUp.png")); + imageCache.Add(ImageCache.ImageType.MagentaTriangleUp,new Bitmap(pathToAssets+"/MagentaTriangleUp.png")); + imageCache.Add(ImageCache.ImageType.DarkBlueTriangleUp,new Bitmap(pathToAssets+"/DarkBlueTriangleUp.png")); } public static ImageCache GetInstance() diff --git a/PortfolioManager/ViewModels/BollingerBandViewModel.cs b/PortfolioManager/ViewModels/BollingerBandViewModel.cs index 8bf3d50..01fa7ef 100644 --- a/PortfolioManager/ViewModels/BollingerBandViewModel.cs +++ b/PortfolioManager/ViewModels/BollingerBandViewModel.cs @@ -73,12 +73,12 @@ namespace PortfolioManager.ViewModels private BollingerBands bollingerBands; - public BollingerBandViewModel() + public BollingerBandViewModel(bool loadedFromParams = false) { InitializeDataSources(); PropertyChanged += OnViewModelPropertyChanged; DisplayName = "Bollinger"; - Initialize(); + Initialize(loadedFromParams ? false : true); } protected override void OnDispose() @@ -87,11 +87,11 @@ namespace PortfolioManager.ViewModels base.OnDispose(); } - private void Initialize() + private void Initialize(bool executePropertyChanged=true) { Task workerTask = Task.Factory.StartNew(() => { - MDTrace.WriteLine(LogLevel.DEBUG, $"WatchListDA.GetWatchLists()"); + MDTrace.WriteLine(LogLevel.DEBUG, $"BollingerBandViewModel::Initialize()"); watchListNames = WatchListDA.GetWatchLists(); watchListNames.Insert(0, UIConstants.CONST_ALL); selectedWatchList = watchListNames.Find(x => x.Equals("Valuations")); @@ -99,9 +99,12 @@ namespace PortfolioManager.ViewModels }); workerTask.ContinueWith((continuation) => { - base.OnPropertyChanged("Symbols"); - base.OnPropertyChanged("WatchListNames"); - base.OnPropertyChanged("SelectedWatchList"); + if (executePropertyChanged) + { + base.OnPropertyChanged("Symbols"); + base.OnPropertyChanged("WatchListNames"); + base.OnPropertyChanged("SelectedWatchList"); + } }); } @@ -192,6 +195,10 @@ namespace PortfolioManager.ViewModels } set { + if (String.IsNullOrEmpty(selectedSymbol)) + { + return; + } selectedSymbol = value; base.OnPropertyChanged("SelectedSymbol"); } @@ -325,7 +332,7 @@ namespace PortfolioManager.ViewModels public override SaveParameters GetSaveParameters() { SaveParameters saveParams = new SaveParameters(); - if (null == selectedSymbol) return null; + if (String.IsNullOrEmpty(selectedSymbol)) return null; saveParams.Add(new KeyValuePair("Type",GetType().Namespace+"."+GetType().Name)); saveParams.Add(new KeyValuePair("SelectedSymbol", selectedSymbol)); saveParams.Add(new KeyValuePair("SelectedWatchList", selectedWatchList)); @@ -353,45 +360,56 @@ namespace PortfolioManager.ViewModels { try { - Referer=saveParameters.Referer; - selectedSymbol = (from KeyValuePair item in saveParameters where item.Key.Equals("SelectedSymbol") select item).FirstOrDefault().Value; - selectedWatchList = (from KeyValuePair item in saveParameters where item.Key.Equals("SelectedWatchList") select item).FirstOrDefault().Value; - base.OnPropertyChanged("SelectedWatchList"); - selectedDayCount = Int32.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("SelectedDayCount") select item).FirstOrDefault().Value); - try + + Task workerTask = Task.Factory.StartNew(() => { - if(saveParameters.ContainsKey("SyncTradeToBand"))syncTradeToBand=Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("SyncTradeToBand") select item).FirstOrDefault().Value); - else syncTradeToBand=true; - } - catch (Exception) { syncTradeToBand = true; } - try - { - if(saveParameters.ContainsKey("ShowTradeLabels"))showTradeLabels = Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("ShowTradeLabels") select item).FirstOrDefault().Value); - else showTradeLabels=true; - } - catch (Exception) { showTradeLabels = true; } - try - { - if(saveParameters.ContainsKey("UseLeastSquaresFit"))useLeastSquaresFit=Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("UseLeastSquaresFit") select item).FirstOrDefault().Value); - } - catch (Exception){;} - try - { - if(saveParameters.ContainsKey("ShowInsiderTransactions"))showInsiderTransactions=Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("ShowInsiderTransactions") select item).FirstOrDefault().Value); - } - catch (Exception){;} - try - { - if(saveParameters.ContainsKey("StopHistoryCount")) + + Referer = saveParameters.Referer; + selectedSymbol = (from KeyValuePair item in saveParameters where item.Key.Equals("SelectedSymbol") select item).FirstOrDefault().Value; + selectedWatchList = (from KeyValuePair item in saveParameters where item.Key.Equals("SelectedWatchList") select item).FirstOrDefault().Value; + selectedDayCount = Int32.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("SelectedDayCount") select item).FirstOrDefault().Value); + MDTrace.WriteLine(LogLevel.DEBUG, $"BollingerBandViewModel::SetSaveParameters('{selectedSymbol}','{selectedWatchList}','{selectedDayCount}')"); + try { - stopLimits = StopLimitsExtensions.FromSaveParams(saveParameters); + if (saveParameters.ContainsKey("SyncTradeToBand")) syncTradeToBand = Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("SyncTradeToBand") select item).FirstOrDefault().Value); + else syncTradeToBand = true; } - } - catch(Exception exception) + catch (Exception) { syncTradeToBand = true; } + try + { + if (saveParameters.ContainsKey("ShowTradeLabels")) showTradeLabels = Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("ShowTradeLabels") select item).FirstOrDefault().Value); + else showTradeLabels = true; + } + catch (Exception) { showTradeLabels = true; } + try + { + if (saveParameters.ContainsKey("UseLeastSquaresFit")) useLeastSquaresFit = Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("UseLeastSquaresFit") select item).FirstOrDefault().Value); + } + catch (Exception) {; } + try + { + if (saveParameters.ContainsKey("ShowInsiderTransactions")) showInsiderTransactions = Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("ShowInsiderTransactions") select item).FirstOrDefault().Value); + } + catch (Exception) {; } + try + { + if (saveParameters.ContainsKey("StopHistoryCount")) + { + stopLimits = StopLimitsExtensions.FromSaveParams(saveParameters); + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}", exception.ToString())); + } + // base.OnPropertyChanged("SelectedWatchList"); + // base.OnPropertyChanged("SelectedSymbol"); + }); + workerTask.ContinueWith((continuation) => { - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); - } - base.OnPropertyChanged("SelectedSymbol"); + base.OnPropertyChanged("SelectedWatchList"); + base.OnPropertyChanged("SelectedSymbol"); + }); } catch (Exception) { @@ -409,22 +427,24 @@ namespace PortfolioManager.ViewModels // ************************************************************************************************************************************* private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs) { - if (eventArgs.PropertyName.Equals("SelectedSymbol")) + if (eventArgs.PropertyName.Equals("SelectedSymbol") && !String.IsNullOrEmpty(selectedSymbol)) { InitializeDataSources(); InitializeData(); } - if (eventArgs.PropertyName.Equals("SyncTradeToBand") || + if ((eventArgs.PropertyName.Equals("SyncTradeToBand") || eventArgs.PropertyName.Equals("ShowTradeLabels") || eventArgs.PropertyName.Equals("SelectedSymbol") || eventArgs.PropertyName.Equals("ShowRiskFree") || eventArgs.PropertyName.Equals("LeastSquaresFit") || - (eventArgs.PropertyName.Equals("SelectedDayCount") && null != selectedSymbol)) + eventArgs.PropertyName.Equals("SelectedDayCount")) + && !String.IsNullOrEmpty(selectedSymbol)) { IsBusy = true; Task workerTask = Task.Factory.StartNew(() => { + MDTrace.WriteLine(LogLevel.DEBUG,$"OnViewModelPropertyChanged({eventArgs.PropertyName}). Selected symbol '{selectedSymbol}'"); base.DisplayName = "Bollinger(" + selectedSymbol + ")"; base.OnPropertyChanged("DisplayName"); stopLimit = PortfolioDA.GetStopLimit(selectedSymbol); @@ -474,7 +494,6 @@ namespace PortfolioManager.ViewModels }); workerTask.ContinueWith((continuation) => { - IsBusy = false; base.OnPropertyChanged("K"); base.OnPropertyChanged("KL1"); base.OnPropertyChanged("L"); @@ -511,6 +530,7 @@ namespace PortfolioManager.ViewModels base.OnPropertyChanged("InsiderTransactionPointMarkersAcquiredSmall"); base.OnPropertyChanged("InsiderTransactionPointMarkersAcquiredMedium"); base.OnPropertyChanged("InsiderTransactionPointMarkersAcquiredLarge"); + IsBusy = false; }); } else if (eventArgs.PropertyName.Equals("SelectedWatchList")) @@ -719,7 +739,7 @@ namespace PortfolioManager.ViewModels get { if (!showTradeLabels) return null; - return ImageCache.GetInstance().GetImage(ImageCache.ImageType.YellowTriangleUp); + return ImageCache.GetInstance().GetImage(ImageCache.ImageType.DarkBlueTriangleUp); } } diff --git a/PortfolioManager/ViewModels/GainLossViewModel.cs b/PortfolioManager/ViewModels/GainLossViewModel.cs index 331eaba..aa45642 100644 --- a/PortfolioManager/ViewModels/GainLossViewModel.cs +++ b/PortfolioManager/ViewModels/GainLossViewModel.cs @@ -750,21 +750,20 @@ namespace PortfolioManager.ViewModels } } - [RelayCommand] + [RelayCommand(CanExecute = nameof(CanExecuteBollingerBand))] public async Task BollingerBands() { + if (null == selectedGainLossSummaryItem) return; SaveParameters saveParams = SaveParameters.Parse("Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedGainLossSummaryItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180,SyncTradeToBand,FALSE"); saveParams.Referer = this; WorkspaceInstantiator.Invoke(saveParams); await Task.FromResult(true); + } - // await Task.FromResult(() => - // { - // SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedGainLossSummaryItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180,SyncTradeToBand,FALSE"); - // saveParams.Referer = this; - // WorkspaceInstantiator.Invoke(saveParams); - // }); - } + public bool CanExecuteBollingerBand() + { + return selectedGainLossSummaryItem == default ? false : true; + } // ****************************************************** T O O L T I P S ********************************************************* public String DollarChangePercent diff --git a/PortfolioManager/ViewModels/MGSHMomentumViewModel.cs b/PortfolioManager/ViewModels/MGSHMomentumViewModel.cs index 41a244a..f33f3ec 100644 --- a/PortfolioManager/ViewModels/MGSHMomentumViewModel.cs +++ b/PortfolioManager/ViewModels/MGSHMomentumViewModel.cs @@ -112,6 +112,7 @@ namespace PortfolioManager.ViewModels get { ObservableCollection collection = new ObservableCollection(); + collection.Add(new MenuItem() { Header = "Bollinger Bands...", Command = BollingerBandsCommand, StaysOpenOnClick = false }); collection.Add(new MenuItem() { Header = "Close Position...", Command = CloseCommand, StaysOpenOnClick = false }); collection.Add(new MenuItem() { Header = "Edit Position...", Command = EditCommand, StaysOpenOnClick = false }); collection.Add(new MenuItem() { Header = "Add To WatchList", Command = AddToWatchListCommand, StaysOpenOnClick = false }); @@ -122,6 +123,12 @@ namespace PortfolioManager.ViewModels // ********************************************************************* R E L A Y S ***************************************************************** + [RelayCommand(CanExecute = nameof(CanExecuteBollingerBands))] + public async Task BollingerBands() + { + await ExecuteBollingerBands(); + } + [RelayCommand(CanExecute = nameof(CanClosePosition))] public async Task Close() { @@ -140,6 +147,12 @@ namespace PortfolioManager.ViewModels await OpenEditDialog(); } + public bool CanExecuteBollingerBands() + { + if (null == selectedPosition || null == selectedPosition.Symbol) return false; + return true; + } + public bool CanEdit() { if (null == selectedPosition || null == selectedPosition.Symbol || !Utility.IsEpoch(selectedPosition.SellDate)) return false; @@ -164,6 +177,14 @@ namespace PortfolioManager.ViewModels await ReloadTradeFile(); } + public async Task ExecuteBollingerBands() + { + SaveParameters saveParams = SaveParameters.Parse("Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,360"); + saveParams.Referer=this; + WorkspaceInstantiator.Invoke(saveParams); + await Task.FromResult(true); + } + public async Task ReloadTradeFile() { LoadSessionFile(); diff --git a/PortfolioManager/Views/BollingerBandView.axaml b/PortfolioManager/Views/BollingerBandView.axaml index 5512d94..fd1f3df 100644 --- a/PortfolioManager/Views/BollingerBandView.axaml +++ b/PortfolioManager/Views/BollingerBandView.axaml @@ -82,7 +82,7 @@ - + @@ -91,7 +91,7 @@ - + diff --git a/PortfolioManager/appsettings.json b/PortfolioManager/appsettings.json index 69457d0..9d74d8b 100644 --- a/PortfolioManager/appsettings.json +++ b/PortfolioManager/appsettings.json @@ -1,7 +1,7 @@ { -"market_data" : "Database=market_data;Datasource=10.0.0.199;Username=guest;Password=guest", -"portfolio_data" : "Database=portfolio_data;Datasource=10.0.0.199;Username=guest;Password=guest", -"user_data" : "Database=user_data;Datasource=10.0.0.199;Username=guest;Password=guest", +"market_data" : "Database=market_data;Datasource=Adrastea;Username=guest;Password=guest", +"portfolio_data" : "Database=portfolio_data;Datasource=Adrastea;Username=guest;Password=guest", +"user_data" : "Database=user_data;Datasource=Adrastea;Username=guest;Password=guest", "sms_smtpaddress" : "smtp.gmail.com", "sms_smsusername" : "skessler1964@gmail.com", "sms_smspassword" : "xjfo isnf gmyi zovr", diff --git a/PortfolioManager/saveparams.config b/PortfolioManager/saveparams.config index ceb2b95..e17316f 100644 --- a/PortfolioManager/saveparams.config +++ b/PortfolioManager/saveparams.config @@ -1,11 +1,6 @@ -Type,PortfolioManager.ViewModels.MGSHMomentumViewModel,PathFileName,C:\boneyard\marketdata\Sessions\MGSH20250331.TXT Type,PortfolioManager.ViewModels.MomentumViewModel,PathFileName,C:\boneyard\marketdata\Sessions\MG20180131.TXT Type,PortfolioManager.ViewModels.CMMomentumViewModel,PathFileName,C:\boneyard\marketdata\Sessions\CM20191031.TXT Type,PortfolioManager.ViewModels.CMTrendViewModel,PathFileName,C:\boneyard\marketdata\Sessions\CMT20200817.TXT -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,RNMBY,SelectedWatchList,Valuations,SelectedDayCount,90,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,JFNNX,SelectedWatchList,Valuations,SelectedDayCount,1440,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,CRS,SelectedWatchList,Valuations,SelectedDayCount,90,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,TSCDY,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,GWRE,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,SPOT,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,RGLD,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True +Type,PortfolioManager.ViewModels.MGSHMomentumViewModel,PathFileName,C:\boneyard\marketdata\Sessions\MGSH20250331.TXT +Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,NRG,SelectedWatchList,Valuations,SelectedDayCount,360,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True +Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,DBX,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True