Add ability to show image markers.

This commit is contained in:
2025-06-15 20:11:58 -04:00
parent 9b1135b5ec
commit 20d253d50e
14 changed files with 236 additions and 54 deletions

3
.gitignore vendored
View File

@@ -1,5 +1,4 @@
PortfolioManager/bin/**
PortfolioManager/obj/**
PortfolioManager/*.log
PortfolioManager/saveparams.config

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -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<ImageType,Bitmap> imageCache = new Dictionary<ImageType,Bitmap>();
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<ImageType, Bitmap>();
}
}
public void Dispose()
{
lock (thisLock)
{
if (null == imageCacheInstance) return;
List<Bitmap> 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];
}
}
}
}

View File

@@ -52,6 +52,13 @@
</None>
</ItemGroup>
<ItemGroup>
<Content Include="Assets\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>Assets\%(RecursiveDir)%(Filename)%(Extension)</Link>
</Content>
</ItemGroup>
<Target Name="PostClean" AfterTargets="Clean">
<RemoveDir Directories="$(BaseIntermediateOutputPath)" /><!-- obj -->
<RemoveDir Directories="$(BaseOutputPath)" /><!-- bin -->

View File

@@ -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
{
/// <summary>
/// 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
/// </summary>
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)
{

View File

@@ -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 ***************************************************
/// <summary>
/// See the XAML and also OSValueConverter in UIUtils for an explanation.
/// </summary>
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<String, String>("SelectedDayCount", selectedDayCount.ToString()));
saveParams.Add(new KeyValuePair<String, String>("SyncTradeToBand", syncTradeToBand.ToString()));
saveParams.Add(new KeyValuePair<String, String>("ShowTradeLabels", showTradeLabels.ToString()));
// saveParams.Add(new KeyValuePair<String, String>("ShowRiskFree", showRiskFree.ToString()));
// saveParams.Add(new KeyValuePair<String, String>("IsLegendVisible", isLegendVisible.ToString()));
saveParams.Add(new KeyValuePair<String, String>("UseLeastSquaresFit", useLeastSquaresFit.ToString()));
saveParams.Add(new KeyValuePair<String, String>("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<String,String> item in saveParameters where item.Key.Equals("IsLegendVisible") select item).FirstOrDefault().Value);
// }
// catch (Exception){;}
try
{
if(saveParameters.ContainsKey("UseLeastSquaresFit"))useLeastSquaresFit=Boolean.Parse((from KeyValuePair<String,String> 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<String,String> item in saveParameters where item.Key.Equals("ShowInsiderTransactions") select item).FirstOrDefault().Value);
}
catch (Exception){;}
// try{showRiskFree = Boolean.Parse((from KeyValuePair<String, String> 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;

View File

@@ -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");
}

View File

@@ -19,6 +19,7 @@
<local:DateValueConverter x:Key="DateFormat"/>
<local:RMultipleValueConverter x:Key="RMultipleFormat"/>
<local:BoolValueConverter x:Key="BoolFormat"/>
<local:OSValueConverter x:Key="OSValueConverter"/>
</UserControl.Resources>
<Grid Background="LightGray">
@@ -147,6 +148,24 @@
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="TradeMarkersPointsGraph" DataAdapter="{Binding TradePoints.DataAdapter}" >
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=TradePointMarkers, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=20|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="ZeroPointMarkersPointsGraph" DataAdapter="{Binding ZeroPoint.DataAdapter}">
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=ZeroPointMarkers, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=20|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="StopLimitMarkersPointsGraph" DataAdapter="{Binding StopLimits.DataAdapter}">
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=StopLimitMarkers, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=20|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="InsiderTransactionsPointMarkersPointsGraphDisposedSmall" DataAdapter="{Binding InsiderTransactionPointDisposedSmall.DataAdapter}" >
<mxc:CartesianPointSeriesView ShowInCrosshair="False" Color="red" MarkerSize="10"/>

View File

@@ -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