diff --git a/.gitignore b/.gitignore index d5cb544..77abf91 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ PortfolioManager/bin/** PortfolioManager/obj/** PortfolioManager/*.log - - +PortfolioManager/saveparams.config diff --git a/PortfolioManager/Assets/BlueTriangleUp.png b/PortfolioManager/Assets/BlueTriangleUp.png new file mode 100644 index 0000000..8565fec Binary files /dev/null and b/PortfolioManager/Assets/BlueTriangleUp.png differ diff --git a/PortfolioManager/Assets/GreenTriangleDown.png b/PortfolioManager/Assets/GreenTriangleDown.png new file mode 100644 index 0000000..7c1324e Binary files /dev/null and b/PortfolioManager/Assets/GreenTriangleDown.png differ diff --git a/PortfolioManager/Assets/GreenTriangleUp.png b/PortfolioManager/Assets/GreenTriangleUp.png new file mode 100644 index 0000000..85314d8 Binary files /dev/null and b/PortfolioManager/Assets/GreenTriangleUp.png differ diff --git a/PortfolioManager/Assets/RedTriangleDown.png b/PortfolioManager/Assets/RedTriangleDown.png new file mode 100644 index 0000000..9e3e9d6 Binary files /dev/null and b/PortfolioManager/Assets/RedTriangleDown.png differ diff --git a/PortfolioManager/Assets/RedTriangleUp.png b/PortfolioManager/Assets/RedTriangleUp.png new file mode 100644 index 0000000..7c0500e Binary files /dev/null and b/PortfolioManager/Assets/RedTriangleUp.png differ diff --git a/PortfolioManager/Assets/YellowTriangleUp.png b/PortfolioManager/Assets/YellowTriangleUp.png new file mode 100644 index 0000000..6a281b1 Binary files /dev/null and b/PortfolioManager/Assets/YellowTriangleUp.png differ diff --git a/PortfolioManager/Cache/ImageCache.cs b/PortfolioManager/Cache/ImageCache.cs new file mode 100644 index 0000000..583688c --- /dev/null +++ b/PortfolioManager/Cache/ImageCache.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using Avalonia.Media; +using Avalonia.Media.Imaging; +using System.Linq; +using System.IO; +using Axiom.Utils; + +namespace PortfolioManager.Cache +{ + public class ImageCache : IDisposable + { + public enum ImageType {BlueTriangleUp,GreenTriangleUp,GreenTriangleDown,RedTriangleUp,RedTriangleDown,YellowTriangleUp } + private Dictionary imageCache = new Dictionary(); + private Object thisLock=new Object(); + private static ImageCache imageCacheInstance=null; + + private ImageCache() + { + String currentDirectory = Directory.GetCurrentDirectory(); + String pathToAssets = currentDirectory; + if (!Directory.Exists(currentDirectory + "/Assets")) + { + pathToAssets = currentDirectory + "/publish" + "/Assets"; + } + else + { + 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")); + } + + public static ImageCache GetInstance() + { + lock (typeof(SymbolCache)) + { + if (null == imageCacheInstance) imageCacheInstance = new ImageCache(); + return imageCacheInstance; + } + } + + public void Clear() + { + lock (thisLock) + { + imageCache = new Dictionary(); + } + } + + public void Dispose() + { + lock (thisLock) + { + if (null == imageCacheInstance) return; + List bitmaps = imageCache.Values.ToList(); + foreach (Bitmap bitmap in bitmaps) + { + bitmap.Dispose(); + } + imageCache = null; + imageCacheInstance = null; + } + } + + public IImage GetImage(ImageCache.ImageType imageType) + { + lock(this) + { + return imageCache[imageType]; + } + } + } +} diff --git a/PortfolioManager/PortfolioManager.csproj b/PortfolioManager/PortfolioManager.csproj index 0ffba44..3300a68 100644 --- a/PortfolioManager/PortfolioManager.csproj +++ b/PortfolioManager/PortfolioManager.csproj @@ -52,6 +52,13 @@ + + + PreserveNewest + Assets\%(RecursiveDir)%(Filename)%(Extension) + + + diff --git a/PortfolioManager/UIUtils/UIUtils.cs b/PortfolioManager/UIUtils/UIUtils.cs index 3d6d13c..9840ad0 100644 --- a/PortfolioManager/UIUtils/UIUtils.cs +++ b/PortfolioManager/UIUtils/UIUtils.cs @@ -1,19 +1,48 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using Avalonia.Data.Converters; using MarketData.MarketDataModel; using MarketData.Utils; namespace PortfolioManager.UIUtils { + + /// + /// If the OS is not Window then multiply the first parameter. + /// For example: "30|.5" would multiply 30 * .5 if the OS is not Windows and return 15 as the result. Otherwise (if Windows) it will return 30 + /// I am doing this because I need to adjust image sizes across Windows and Unix platforms where Unix images appear quite larger than Windows + /// + public class OSValueConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + String[] parameters = parameter.ToString().Split('|'); + double valueItem = double.Parse(parameters[0]); + double multiplier = double.Parse(parameters[1]); + + if (Utility.IsOSWindows()) + { + return (int)valueItem; + } + else + { + return (int)(valueItem * multiplier); + } + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + return null; + } + } + public class RMultipleValueConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { double doubleValue = (double)value; if (double.IsNaN(doubleValue) || double.IsInfinity(doubleValue)) return Constants.CONST_DASHES; - return Utility.FormatNumber(doubleValue,2)+"R"; + return Utility.FormatNumber(doubleValue, 2) + "R"; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { diff --git a/PortfolioManager/ViewModels/BollingerBandViewModel.cs b/PortfolioManager/ViewModels/BollingerBandViewModel.cs index b2aa84d..34d1928 100644 --- a/PortfolioManager/ViewModels/BollingerBandViewModel.cs +++ b/PortfolioManager/ViewModels/BollingerBandViewModel.cs @@ -5,6 +5,7 @@ using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; +using Avalonia.Media; using CommunityToolkit.Mvvm.Input; using DynamicData; using Eremex.AvaloniaUI.Charts; @@ -227,6 +228,12 @@ namespace PortfolioManager.ViewModels syncTradeToBand = value; if (syncTradeToBand) showTradeLabels = true; base.OnPropertyChanged("SyncTradeToBand"); + base.OnPropertyChanged("TradePoints"); + base.OnPropertyChanged("ZeroPoint"); + base.OnPropertyChanged("StopLimits"); + base.OnPropertyChanged("TradePointMarkers"); + base.OnPropertyChanged("ZeroPointMarkers"); + base.OnPropertyChanged("StopLimitMarkers"); } } @@ -296,7 +303,21 @@ namespace PortfolioManager.ViewModels } } - // ******************************************************************* P E R S I S T E N C E *************************************************** + /// + /// See the XAML and also OSValueConverter in UIUtils for an explanation. + /// + public int MarkerSize + { + get + { + return 0; + } + } + + // ********************************************************************************************************************************************* + + + // ******************************************************************* P E R S I S T E N C E *************************************************** public override bool CanPersist() { @@ -313,8 +334,6 @@ namespace PortfolioManager.ViewModels saveParams.Add(new KeyValuePair("SelectedDayCount", selectedDayCount.ToString())); saveParams.Add(new KeyValuePair("SyncTradeToBand", syncTradeToBand.ToString())); saveParams.Add(new KeyValuePair("ShowTradeLabels", showTradeLabels.ToString())); - // saveParams.Add(new KeyValuePair("ShowRiskFree", showRiskFree.ToString())); - // saveParams.Add(new KeyValuePair("IsLegendVisible", isLegendVisible.ToString())); saveParams.Add(new KeyValuePair("UseLeastSquaresFit", useLeastSquaresFit.ToString())); saveParams.Add(new KeyValuePair("ShowInsiderTransactions", showInsiderTransactions.ToString())); if(null!=stopLimits && 0!=stopLimits.Count) @@ -353,11 +372,6 @@ namespace PortfolioManager.ViewModels else showTradeLabels=true; } catch (Exception) { showTradeLabels = true; } - // try - // { - // if(saveParameters.ContainsKey("IsLegendVisible"))isLegendVisible=Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("IsLegendVisible") select item).FirstOrDefault().Value); - // } - // catch (Exception){;} try { if(saveParameters.ContainsKey("UseLeastSquaresFit"))useLeastSquaresFit=Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("UseLeastSquaresFit") select item).FirstOrDefault().Value); @@ -368,9 +382,6 @@ namespace PortfolioManager.ViewModels if(saveParameters.ContainsKey("ShowInsiderTransactions"))showInsiderTransactions=Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("ShowInsiderTransactions") select item).FirstOrDefault().Value); } catch (Exception){;} - // try{showRiskFree = Boolean.Parse((from KeyValuePair item in saveParameters where item.Key.Equals("ShowRiskFree") select item).FirstOrDefault().Value);} - // catch (Exception){;} - try { if(saveParameters.ContainsKey("StopHistoryCount")) @@ -418,8 +429,6 @@ namespace PortfolioManager.ViewModels { base.DisplayName = "Bollinger(" + selectedSymbol + ")"; base.OnPropertyChanged("DisplayName"); - // InitializeDataSources(); - // InitializeData(); stopLimit = PortfolioDA.GetStopLimit(selectedSymbol); portfolioTrades = PortfolioDA.GetTradesSymbol(selectedSymbol); portfolioTradesLots = LotAggregator.CombineLots(portfolioTrades); @@ -480,13 +489,14 @@ namespace PortfolioManager.ViewModels base.OnPropertyChanged("LeastSquares"); base.OnPropertyChanged("GraphTitle"); base.OnPropertyChanged("Title"); - // base.OnPropertyChanged("TradePoints"); - // base.OnPropertyChanged("Markers"); - // base.OnPropertyChanged("ZeroPoint"); - // base.OnPropertyChanged("ZeroPointMarkers"); - // base.OnPropertyChanged("StopLimit"); - // base.OnPropertyChanged("StopLimitMarkers"); + base.OnPropertyChanged("TradePoints"); + base.OnPropertyChanged("ZeroPoint"); + base.OnPropertyChanged("StopLimits"); + + base.OnPropertyChanged("TradePointMarkers"); + base.OnPropertyChanged("ZeroPointMarkers"); + base.OnPropertyChanged("StopLimitMarkers"); base.OnPropertyChanged("InsiderTransactionPointDisposedSmall"); base.OnPropertyChanged("InsiderTransactionPointDisposedMedium"); @@ -496,7 +506,6 @@ namespace PortfolioManager.ViewModels base.OnPropertyChanged("InsiderTransactionPointAcquiredMedium"); base.OnPropertyChanged("InsiderTransactionPointAcquiredLarge"); - // base.OnPropertyChanged("InsiderTransactionPointMarkersDisposedSmall"); // base.OnPropertyChanged("InsiderTransactionPointMarkersDisposedMedium"); // base.OnPropertyChanged("InsiderTransactionPointMarkersDisposedLarge"); @@ -528,9 +537,6 @@ namespace PortfolioManager.ViewModels base.OnPropertyChanged("Symbols"); }); } - - - } // ************************************************* C O M P O S I T E P R O P E R T I E S ******************************************** @@ -609,10 +615,65 @@ namespace PortfolioManager.ViewModels } } + public CompositeDataSource TradePoints + { + get + { + if (!showTradeLabels) return Empty(); + return compositeDataSourceTradePoints; + } + } + + public IImage TradePointMarkers + { + get + { + if (!showTradeLabels) return null; + return ImageCache.GetInstance().GetImage(ImageCache.ImageType.YellowTriangleUp); + } + } + + public CompositeDataSource ZeroPoint + { + get + { + if (!showTradeLabels) return Empty(); + return compositeDataSourceZeroPoint; + } + } + + public IImage ZeroPointMarkers + { + get + { + if (!showTradeLabels) return null; + return ImageCache.GetInstance().GetImage(ImageCache.ImageType.BlueTriangleUp); + } + } + + public CompositeDataSource StopLimits + { + get + { + if (!showTradeLabels) return Empty(); + return compositeDataSourceStopLimit; + } + } + + public IImage StopLimitMarkers + { + get + { + if (!showTradeLabels) return null; + return ImageCache.GetInstance().GetImage(ImageCache.ImageType.RedTriangleUp); + } + } + public CompositeDataSource InsiderTransactionPointDisposedSmall { get { + if (!showInsiderTransactions) return Empty(); return compositeDataSourceInsiderTransactionPointDisposedSmall; } } @@ -621,6 +682,7 @@ namespace PortfolioManager.ViewModels { get { + if (!showInsiderTransactions) return Empty(); return compositeDataSourceInsiderTransactionPointDisposedMedium; } } @@ -629,6 +691,7 @@ namespace PortfolioManager.ViewModels { get { + if (!showInsiderTransactions) return Empty(); return compositeDataSourceInsiderTransactionPointDisposedLarge; } } @@ -637,6 +700,7 @@ namespace PortfolioManager.ViewModels { get { + if (!showInsiderTransactions) return Empty(); return compositeDataSourceInsiderTransactionPointAcquiredSmall; } } @@ -645,6 +709,7 @@ namespace PortfolioManager.ViewModels { get { + if (!showInsiderTransactions) return Empty(); return compositeDataSourceInsiderTransactionPointAcquiredMedium; } } @@ -653,14 +718,12 @@ namespace PortfolioManager.ViewModels { get { + if (!showInsiderTransactions) return Empty(); return compositeDataSourceInsiderTransactionPointAcquiredLarge; } } // ********************************************************************************************************************************************* - - - public void CreateCompositeDataSources() { if (null == prices || 0 == prices.Count) return; diff --git a/PortfolioManager/ViewModels/MainWindowViewModel.cs b/PortfolioManager/ViewModels/MainWindowViewModel.cs index cb858f2..996ec2f 100644 --- a/PortfolioManager/ViewModels/MainWindowViewModel.cs +++ b/PortfolioManager/ViewModels/MainWindowViewModel.cs @@ -8,6 +8,7 @@ using Avalonia.Threading; using Axiom.Utils; using MarketData.Cache; using MarketData.DataAccess; +using PortfolioManager.Cache; using PortfolioManager.Command; namespace PortfolioManager.ViewModels @@ -43,9 +44,10 @@ namespace PortfolioManager.ViewModels } try { LocalPriceCache.GetInstance().Dispose(); } catch (Exception) {; } try { GBPriceCache.GetInstance().Dispose(); } catch (Exception) {; } + try { ImageCache.GetInstance().Dispose(); } catch (Exception) {; } //try{PriceCache.GetInstance().Dispose();}catch(Exception){;} - // try{SymbolCache.GetInstance().Dispose();}catch(Exception){;} - base.OnDispose(); + // try{SymbolCache.GetInstance().Dispose();}catch(Exception){;} + base.OnDispose(); MDTrace.WriteLine(LogLevel.DEBUG, "[MainWindowViewModel:OnDispose] LEAVE"); } diff --git a/PortfolioManager/Views/BollingerBandView.axaml b/PortfolioManager/Views/BollingerBandView.axaml index a1ae48e..c5be122 100644 --- a/PortfolioManager/Views/BollingerBandView.axaml +++ b/PortfolioManager/Views/BollingerBandView.axaml @@ -19,6 +19,7 @@ + @@ -147,6 +148,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/PortfolioManager/saveparams.config b/PortfolioManager/saveparams.config index e1c7dd5..ceb2b95 100644 --- a/PortfolioManager/saveparams.config +++ b/PortfolioManager/saveparams.config @@ -2,26 +2,10 @@ Type,PortfolioManager.ViewModels.MGSHMomentumViewModel,PathFileName,C:\boneyard\ 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,180,SyncTradeToBand,False,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,SPOT,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,RGLD,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,PRIM,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,NRG,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,DBX,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,CRS,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,SXT,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,PLMR,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,DRD,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,HURN,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,IEFA,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,IDA,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,MD,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,PSO,SelectedWatchList,Valuations,SelectedDayCount,1440,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,OPRA,SelectedWatchList,Valuations,SelectedDayCount,1440,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,DORM,SelectedWatchList,Valuations,SelectedDayCount,1440,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,KEP,SelectedWatchList,Valuations,SelectedDayCount,1440,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,VSTCX,SelectedWatchList,Valuations,SelectedDayCount,1440,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,SPY,SelectedWatchList,Valuations,SelectedDayCount,1440,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True +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