From e8d3f68b3dd0b37e3f20df75703bedf3fe18e478 Mon Sep 17 00:00:00 2001 From: Sean Date: Mon, 16 Jun 2025 19:59:04 -0400 Subject: [PATCH] More changes for BollingerBands. --- PortfolioManager/Assets/AmberTriangleUp.png | Bin 0 -> 2627 bytes .../Assets/DarkBlueTriangleUp.png | Bin 0 -> 2125 bytes PortfolioManager/Assets/MagentaTriangleUp.png | Bin 0 -> 1837 bytes PortfolioManager/Assets/OrangeTriangleUp.png | Bin 0 -> 2957 bytes PortfolioManager/Cache/ImageCache.cs | 21 ++-- .../ViewModels/BollingerBandViewModel.cs | 116 ++++++++++-------- .../ViewModels/GainLossViewModel.cs | 15 ++- .../ViewModels/MGSHMomentumViewModel.cs | 21 ++++ .../Views/BollingerBandView.axaml | 4 +- PortfolioManager/appsettings.json | 6 +- PortfolioManager/saveparams.config | 11 +- 11 files changed, 117 insertions(+), 77 deletions(-) create mode 100644 PortfolioManager/Assets/AmberTriangleUp.png create mode 100644 PortfolioManager/Assets/DarkBlueTriangleUp.png create mode 100644 PortfolioManager/Assets/MagentaTriangleUp.png create mode 100644 PortfolioManager/Assets/OrangeTriangleUp.png diff --git a/PortfolioManager/Assets/AmberTriangleUp.png b/PortfolioManager/Assets/AmberTriangleUp.png new file mode 100644 index 0000000000000000000000000000000000000000..158a36adcff6a3217baf17f3e9fb7a2e3029b507 GIT binary patch literal 2627 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 literal 0 HcmV?d00001 diff --git a/PortfolioManager/Assets/MagentaTriangleUp.png b/PortfolioManager/Assets/MagentaTriangleUp.png new file mode 100644 index 0000000000000000000000000000000000000000..24b29c2ff40601af28ec41c7b916bf36cb33da3b GIT binary patch literal 1837 zcmYLKc{tST7yr%}l1cbkrqIwrU1U z&JvKQ2)MUm-FiRC zK%~V2Z*ncjWp$EFzebfguyNsGY0pH>Bs{G+LiPzh4*TXz3?VWRFOJP?9xAD6SCK+m z9Wwh7bHvpBA^eeX$hpQAI5Ez$LhVX|v87Wj4wHMKB1`j=4_l&F8TmROr7mRW!+vUJ zDkGzEF|cvJA@B}H1qx#McWub360g>$$2gQZXkcOd{Pbsz$FvTgm;Np_t1R(pqX$Fl z7(kAdn?2Cj6_qZC9S(b-ZKs_^aZlND>eBt`r~=)!I=@*=-Yr*b1Q#Cel~f+2o;3Kf>u*AZv=rGnMR7sm_&Swm?zvVUq2Vk zHBBS+r3>-qaP#D97$r>?&np?Y1^A!=XkI<`8kvkiYcHLNh`7=^2I3@yGqr73y4{aBPHQJzFi)NbTMI z4VpabXLL zQu)ox*AkbcmAcmzG;(@;zTnVgZS6RjlJF0MD0M~p9@3O@T$NakW*e>c6m0CkLpkH`#c%5dAf)(FFoSMEFP{V)G-GGqFf z^B=|-Z1qM)aRo+}mI_=gR8_BYNeVSO0%sbrWk{@eu=EvIAaDP}iW&AJ^Q=dAlKo1U zaDuY9DzWQJc`D|8U{up-^H;!2*AzJp^sF`HYT-?=%h_`BDClf5U^jbXanhx z2Jr@6S|})!z|T;6h`I!>UG?Vv{*}hAcOItGH0ZffdENU{$)UR=FB8Y!;)j%Z0e9(u zU}R^Ub5AlY=d^Z)O0C>|4{Q9N86RB}~Q*!fY;LSLeQT@w0_)uoz zIwPW96MA=s6PJk+Wmp4^e7Uv$F05X0(~sWm8}`Zzf=t>YnG#*9dcKRhOFYhP1J0M4 z-rItti2;pgc+<}ZDGTE@e;VHr%K5z#ahW)w4xZ(gI{9XbZZ&4FN_vJ$b+&n_$zYkS zG#_)M&{^;dGp)exfZeR5 zlwI-)CwURjRx$dGrs?HB5KZ!MWWAZGq34a)0-~}mBYj?>W?(Ze;VvX>H XqJK5BzkNYH7Z@xqS>uavl!$)-g|$yl literal 0 HcmV?d00001 diff --git a/PortfolioManager/Assets/OrangeTriangleUp.png b/PortfolioManager/Assets/OrangeTriangleUp.png new file mode 100644 index 0000000000000000000000000000000000000000..63d223ba18fb7a4bb5738080f57fd488dc63961d GIT binary patch literal 2957 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 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