Commit Latest

This commit is contained in:
2025-06-22 12:54:07 -04:00
parent 981a873dee
commit b1d0b835b6
3 changed files with 465 additions and 52 deletions

View File

@@ -16,24 +16,39 @@ using ScottPlot;
using ScottPlot.Avalonia; using ScottPlot.Avalonia;
using ScottPlot.Plottables; using ScottPlot.Plottables;
using SkiaSharp; using SkiaSharp;
using MarketData.Numerical;
namespace PortfolioManager.Renderers namespace PortfolioManager.Renderers
{ {
public static class SizeFactor
{
public const float Small = 0.09375f;
public const float Normal = 0.125f;
public const float Large = 0.15625f;
}
public static class FontFactor
{
public const int FontSize = 10;
}
public class BollingerBandRenderer : ModelBase public class BollingerBandRenderer : ModelBase
{ {
private Price latestPrice = default; private Price latestPrice = default;
private Price zeroPrice = default; private Price zeroPrice = default;
private bool showLabels =true; private bool showLabels = true;
private bool showMarkers = true; private bool showMarkers = true;
private bool showLegend = true; private bool showLegend = false;
private bool showTradeLabels = true;
private bool syncTradeToBand = true; private bool syncTradeToBand = true;
private StopLimit stopLimit = default; private StopLimit stopLimit = default;
private StopLimits stopLimits = default;
private PortfolioTrades portfolioTrades = default; private PortfolioTrades portfolioTrades = default;
private PortfolioTrades portfolioTradesLots = default; private PortfolioTrades portfolioTradesLots = default;
private Prices prices = default; private Prices prices = default;
private BollingerBands bollingerBands; private BollingerBands bollingerBands;
private InsiderTransactionSummaries insiderTransactionSummaries = null; private InsiderTransactionSummaries insiderTransactionSummaries = null;
public BollingerBandRenderer(AvaPlot plotter) public BollingerBandRenderer(AvaPlot plotter)
{ {
Plotter = plotter ?? throw new ArgumentNullException(nameof(plotter)); Plotter = plotter ?? throw new ArgumentNullException(nameof(plotter));
@@ -85,7 +100,6 @@ namespace PortfolioManager.Renderers
DateTime latestPricingDate = PricingDA.GetLatestDate(selectedSymbol); DateTime latestPricingDate = PricingDA.GetLatestDate(selectedSymbol);
latestPrice = PricingDA.GetPrice(selectedSymbol, latestPricingDate); latestPrice = PricingDA.GetPrice(selectedSymbol, latestPricingDate);
zeroPrice = ParityGenerator.GenerateGainLossValue(openTrades, latestPrice); zeroPrice = ParityGenerator.GenerateGainLossValue(openTrades, latestPrice);
if (!syncTradeToBand) if (!syncTradeToBand)
{ {
@@ -105,11 +119,14 @@ namespace PortfolioManager.Renderers
DateGenerator dateGenerator = new DateGenerator(); DateGenerator dateGenerator = new DateGenerator();
DateTime earliestInsiderTransactionDate = dateGenerator.GenerateFutureBusinessDate(prices[prices.Count - 1].Date, 30); DateTime earliestInsiderTransactionDate = dateGenerator.GenerateFutureBusinessDate(prices[prices.Count - 1].Date, 30);
insiderTransactionSummaries = InsiderTransactionDA.GetInsiderTransactionSummaries(selectedSymbol, earliestInsiderTransactionDate); insiderTransactionSummaries = InsiderTransactionDA.GetInsiderTransactionSummaries(selectedSymbol, earliestInsiderTransactionDate);
} }
} }
bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices); bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
GenerateCompositeDataSources(bollingerBands); GenerateBollingerBands();
GenerateZeroPoint(zeroPrice); GenerateZeroPoint(zeroPrice);
GenerateInsiderTransactions();
GenerateStopLimits();
GenerateTradePoints();
} }
/// <summary> /// <summary>
@@ -118,7 +135,7 @@ namespace PortfolioManager.Renderers
/// <param name="zeroPrice"></param> /// <param name="zeroPrice"></param>
private void GenerateZeroPoint(Price zeroPrice) private void GenerateZeroPoint(Price zeroPrice)
{ {
if (!ShowMarkers) return; if (!ShowMarkers || null == zeroPrice) return;
ImageMarker imageMarker = default; ImageMarker imageMarker = default;
Coordinates coordinates = default; Coordinates coordinates = default;
Image image = default; Image image = default;
@@ -129,19 +146,193 @@ namespace PortfolioManager.Renderers
image = TextMarkerImageGenerator.ToSPImage(ImageCache.GetInstance().GetImage(ImageCache.ImageType.BlueTriangleUp)); image = TextMarkerImageGenerator.ToSPImage(ImageCache.GetInstance().GetImage(ImageCache.ImageType.BlueTriangleUp));
coordinates = new Coordinates(dates[0].ToOADate(), values[0]); coordinates = new Coordinates(dates[0].ToOADate(), values[0]);
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image, 0.125f); imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image, SizeFactor.Normal);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.Append("Even "); sb.Append("Even ");
sb.Append(Utility.FormatCurrency(zeroPrice.Close)); sb.Append(Utility.FormatCurrency(zeroPrice.Close));
double parityOffsetPercent = (latestPrice.Close - zeroPrice.Close) / zeroPrice.Close; double parityOffsetPercent = (latestPrice.Close - zeroPrice.Close) / zeroPrice.Close;
sb.Append("(").Append(parityOffsetPercent < 0 ? "" : "+").Append(Utility.FormatPercent(parityOffsetPercent)).Append(")"); sb.Append("(").Append(parityOffsetPercent < 0 ? "" : "+").Append(Utility.FormatPercent(parityOffsetPercent)).Append(")");
image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), 130, 24, 11); image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), 130, 24, FontFactor.FontSize);
coordinates = new Coordinates(dates[0].ToOADate(), values[0]-5.00); coordinates = new Coordinates(dates[0].ToOADate(), values[0] - 5.00);
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image); imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image);
} }
private void GenerateCompositeDataSources(BollingerBands bollingerBands)
/// <summary>
/// Generate Stop Limits
/// </summary>
private void GenerateStopLimits()
{
if (null == stopLimits && null == zeroPrice) return;
if (null != stopLimits)
{
StopLimits = StopLimitCompositeModel.CreateCompositeDataSource(stopLimits);
}
else if (null != stopLimit && null != zeroPrice)
{
StopLimits = GainLossModel.CreateCompositeDataSource(zeroPrice.Date, stopLimit.StopPrice);
}
(DateTime[] dates, double[] values) = StopLimits.ToXYData();
Image imageStopLimitMarker = TextMarkerImageGenerator.ToSPImage(ImageCache.GetInstance().GetImage(ImageCache.ImageType.RedTriangleUp));
for (int index = 0; index < dates.Length; index++)
{
DateTime date = dates[index];
double value = values[index];
Coordinates coordinates = new Coordinates(date.ToOADate(), value);
ImageMarker imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageStopLimitMarker, SizeFactor.Normal);
}
if (null != stopLimits)
{
for (int index = 0; index < stopLimits.Count; index++)
{
StopLimit limit = stopLimits[index];
StringBuilder sb = new StringBuilder();
sb.Append(limit.StopType).Append(" ");
sb.Append(Utility.FormatCurrency(limit.StopPrice));
if (index == stopLimits.Count - 1)
{
Price latestPrice = prices[0];
double percentOffsetFromLow = ((latestPrice.Low - limit.StopPrice) / limit.StopPrice);
sb.Append(" (").Append(percentOffsetFromLow > 0 ? "+" : "").Append(Utility.FormatPercent(percentOffsetFromLow)).Append(")");
}
Image image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), 150, 24, FontFactor.FontSize);
Coordinates coordinates = new Coordinates(dates[0].ToOADate(), values[0] - 5.00);
ImageMarker imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image);
}
}
else
{
if (null == zeroPrice) return;
if (null == stopLimit || null == zeroPrice || !showTradeLabels) return;
Price latestPrice = prices[0];
double percentOffsetFromLow = ((latestPrice.Low - stopLimit.StopPrice) / stopLimit.StopPrice);
StringBuilder sb = new StringBuilder();
sb.Append(stopLimit.StopType).Append(" ");
sb.Append(Utility.FormatCurrency(stopLimit.StopPrice));
sb.Append(" (").Append(percentOffsetFromLow > 0 ? "+" : "").Append(Utility.FormatPercent(percentOffsetFromLow)).Append(")");
Image image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), 150, 24, FontFactor.FontSize);
Coordinates coordinates = new Coordinates(latestPrice.Date.ToOADate(), stopLimit.StopPrice - 5.00);
ImageMarker imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image);
}
}
/// <summary>
/// Generate Trade Points
/// </summary>
private void GenerateTradePoints()
{
}
/// <summary>
/// Generate Insider Transactions
/// </summary>
private void GenerateInsiderTransactions()
{
if (null == prices || 0 == prices.Count || !ShowMarkers) return;
ImageMarker imageMarker = default;
Coordinates coordinates = default;
double minClose = (from Price price in prices select price.Close).Min();
// get the maximum date in the bollinger band series
DateTime maxBollingerDate = (from BollingerBandElement bollingerBandElement in bollingerBands select bollingerBandElement.Date).Max();
// ensure that the insider transactions are clipped to the bollingerband max date. There are some items in insider transaction summaries (options dated in the future) that will throw the graphic out of proportion
InsiderTransactionSummaries disposedSummaries = new InsiderTransactionSummaries((from InsiderTransactionSummary insiderTransactionSummary in insiderTransactionSummaries where insiderTransactionSummary.NumberOfSharesAcquiredDisposed < 0 && insiderTransactionSummary.TransactionDate.Date <= maxBollingerDate select insiderTransactionSummary).ToList());
InsiderTransactionSummaries acquiredSummaries = new InsiderTransactionSummaries((from InsiderTransactionSummary insiderTransactionSummary in insiderTransactionSummaries where insiderTransactionSummary.NumberOfSharesAcquiredDisposed > 0 && insiderTransactionSummary.TransactionDate.Date <= maxBollingerDate select insiderTransactionSummary).ToList());
BinCollection<InsiderTransactionSummary> disposedSummariesBin = BinHelper<InsiderTransactionSummary>.CreateBins(new BinItems<InsiderTransactionSummary>(disposedSummaries), 3);
BinCollection<InsiderTransactionSummary> acquiredSummariesBin = BinHelper<InsiderTransactionSummary>.CreateBins(new BinItems<InsiderTransactionSummary>(acquiredSummaries), 3);
InsiderTransactionPointDisposedSmall = InsiderTransactionModel.InsiderTransactionSummaries(new InsiderTransactionSummaries(disposedSummariesBin[2]), minClose);
InsiderTransactionPointDisposedMedium = InsiderTransactionModel.InsiderTransactionSummaries(new InsiderTransactionSummaries(disposedSummariesBin[1]), minClose);
InsiderTransactionPointDisposedLarge = InsiderTransactionModel.InsiderTransactionSummaries(new InsiderTransactionSummaries(disposedSummariesBin[0]), minClose);
InsiderTransactionPointAcquiredSmall = InsiderTransactionModel.InsiderTransactionSummaries(new InsiderTransactionSummaries(acquiredSummariesBin[0]), minClose);
InsiderTransactionPointAcquiredMedium = InsiderTransactionModel.InsiderTransactionSummaries(new InsiderTransactionSummaries(acquiredSummariesBin[1]), minClose);
InsiderTransactionPointAcquiredLarge = InsiderTransactionModel.InsiderTransactionSummaries(new InsiderTransactionSummaries(acquiredSummariesBin[2]), minClose);
Image imageDisposed = TextMarkerImageGenerator.ToSPImage(ImageCache.GetInstance().GetImage(ImageCache.ImageType.RedTriangleDown));
Image imageAcquired = TextMarkerImageGenerator.ToSPImage(ImageCache.GetInstance().GetImage(ImageCache.ImageType.GreenTriangleUp));
// Disposed
{
(DateTime[] dates, double[] values) = InsiderTransactionPointDisposedSmall.ToXYData();
for (int index = 0; index < dates.Length; index++)
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageDisposed, SizeFactor.Small);
}
}
{
(DateTime[] dates, double[] values) = InsiderTransactionPointDisposedMedium.ToXYData();
for (int index = 0; index < dates.Length; index++)
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageDisposed, SizeFactor.Normal);
}
}
{
(DateTime[] dates, double[] values) = InsiderTransactionPointDisposedLarge.ToXYData();
for (int index = 0; index < dates.Length; index++)
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageDisposed, SizeFactor.Large);
}
}
// Acquired
{
(DateTime[] dates, double[] values) = InsiderTransactionPointAcquiredSmall.ToXYData();
for (int index = 0; index < dates.Length; index++)
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageAcquired, SizeFactor.Small);
}
}
{
(DateTime[] dates, double[] values) = InsiderTransactionPointAcquiredMedium.ToXYData();
for (int index = 0; index < dates.Length; index++)
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageAcquired, SizeFactor.Normal);
}
}
{
(DateTime[] dates, double[] values) = InsiderTransactionPointAcquiredLarge.ToXYData();
for (int index = 0; index < dates.Length; index++)
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageAcquired, SizeFactor.Large);
}
}
}
/// <summary>
/// Generate Bollinger Bands
/// </summary>
private void GenerateBollingerBands()
{ {
K = BollingerBandModel.K(bollingerBands); K = BollingerBandModel.K(bollingerBands);
KL1 = BollingerBandModel.KL1(bollingerBands); KL1 = BollingerBandModel.KL1(bollingerBands);
@@ -218,32 +409,34 @@ namespace PortfolioManager.Renderers
scatter.LineWidth = 2; scatter.LineWidth = 2;
} }
} }
// *********************************************************** P R O P E R T I E S *****************************************************
public bool SyncTradeToBand public bool SyncTradeToBand
{ {
get get
{ {
return syncTradeToBand; return syncTradeToBand;
} }
set set
{ {
syncTradeToBand = value; syncTradeToBand = value;
base.OnPropertyChanged("SyncTradeToBand"); base.OnPropertyChanged("SyncTradeToBand");
} }
} }
public bool ShowLabels public bool ShowLabels
{ {
get get
{ {
return showLabels; return showLabels;
} }
set set
{ {
showLabels = value; showLabels = value;
base.OnPropertyChanged("ShowLabels"); base.OnPropertyChanged("ShowLabels");
} }
} }
public bool ShowMarkers public bool ShowMarkers
{ {
@@ -272,24 +465,35 @@ namespace PortfolioManager.Renderers
} }
public AvaPlot Plotter { get; private set; } public AvaPlot Plotter { get; private set; }
public CompositeDataSource K { get; private set; } = Empty();
public CompositeDataSource KL1 { get; private set; } = Empty(); private CompositeDataSource InsiderTransactionPointDisposedSmall { get; set; } = Empty();
public CompositeDataSource L { get; private set; } = Empty(); private CompositeDataSource InsiderTransactionPointDisposedMedium { get; set; } = Empty();
public CompositeDataSource LP1 { get; private set; } = Empty(); private CompositeDataSource InsiderTransactionPointDisposedLarge { get; set; } = Empty();
public CompositeDataSource High { get; private set; } = Empty(); private CompositeDataSource InsiderTransactionPointAcquiredSmall { get; set; } = Empty();
public CompositeDataSource Low { get; private set; } = Empty(); private CompositeDataSource InsiderTransactionPointAcquiredMedium { get; set; } = Empty();
public CompositeDataSource Close { get; private set; } = Empty(); private CompositeDataSource InsiderTransactionPointAcquiredLarge { get; set; } = Empty();
public CompositeDataSource SMAN { get; private set; } = Empty();
public CompositeDataSource Volume { get; private set; } = Empty(); private CompositeDataSource K { get; set; } = Empty();
public CompositeDataSource LeastSquares { get; private set; } = Empty(); private CompositeDataSource KL1 { get; set; } = Empty();
public CompositeDataSource ZeroPoint { get; private set; } = Empty(); private CompositeDataSource L { get; set; } = Empty();
private CompositeDataSource LP1 { get; set; } = Empty();
private CompositeDataSource High { get; set; } = Empty();
private CompositeDataSource Low { get; set; } = Empty();
private CompositeDataSource Close { get; set; } = Empty();
private CompositeDataSource SMAN { get; set; } = Empty();
private CompositeDataSource Volume { get; set; } = Empty();
private CompositeDataSource LeastSquares { get; set; } = Empty();
private CompositeDataSource ZeroPoint { get; set; } = Empty();
private CompositeDataSource StopLimits { get; set; } = Empty();
private static CompositeDataSource Empty() private static CompositeDataSource Empty()
{
return new CompositeDataSource()
{ {
return new CompositeDataSource() DataAdapter = new SortedDateTimeDataAdapter()
{ };
DataAdapter = new SortedDateTimeDataAdapter()
};
}
} }
}
} }

View File

@@ -15,6 +15,7 @@ namespace PortfolioManager.ViewModels
public void PlotterLoadedEvent(object sender, PlotterLoadedEventArgs e) public void PlotterLoadedEvent(object sender, PlotterLoadedEventArgs e)
{ {
// String selectedSymbol = "VST";
String selectedSymbol = "CRS"; String selectedSymbol = "CRS";
int selectedDayCount = 180; int selectedDayCount = 180;

View File

@@ -668,3 +668,211 @@
[Thread=1][TRACE.DEBUG][6/21/2025 6:46:06 PM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE [Thread=1][TRACE.DEBUG][6/21/2025 6:46:06 PM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/21/2025 6:46:06 PM] [PortfolioManager.Program::Main(args)]There were 46 threads still running at application shutdown. [Thread=1][TRACE.VERBOSE][6/21/2025 6:46:06 PM] [PortfolioManager.Program::Main(args)]There were 46 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/21/2025 6:46:06 PM] [PortfolioManager.Program::Main(args)][MAIN:EXIT] [Thread=1][TRACE.VERBOSE][6/21/2025 6:46:06 PM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:47:31 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:47:31 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:47:31 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:47:31 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 9:47:36 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 9:47:38 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 9:47:38 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=15][TRACE.VERBOSE][6/22/2025 9:47:38 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 9:47:38 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:47:38 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=16][TRACE.VERBOSE][6/22/2025 9:47:38 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:47:38 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:47:38 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 9:47:38 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 9:47:38 AM] [PortfolioManager.Program::Main(args)]There were 47 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:47:38 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:48:28 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:48:28 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:48:28 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:48:28 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 9:48:32 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 9:48:38 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 9:48:38 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:48:38 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=14][TRACE.VERBOSE][6/22/2025 9:48:38 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 9:48:38 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=15][TRACE.VERBOSE][6/22/2025 9:48:38 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:48:38 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:48:38 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 9:48:38 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 9:48:38 AM] [PortfolioManager.Program::Main(args)]There were 45 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:48:38 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:50:23 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:50:24 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:50:24 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:50:24 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 9:50:28 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 9:50:34 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 9:50:34 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=14][TRACE.VERBOSE][6/22/2025 9:50:34 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 9:50:34 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:50:34 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=15][TRACE.VERBOSE][6/22/2025 9:50:34 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:50:34 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:50:34 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 9:50:34 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 9:50:34 AM] [PortfolioManager.Program::Main(args)]There were 46 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:50:34 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:04 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:04 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:04 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:04 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 9:51:07 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 9:51:12 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 9:51:12 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=14][TRACE.VERBOSE][6/22/2025 9:51:12 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:12 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:12 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=15][TRACE.VERBOSE][6/22/2025 9:51:12 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:12 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:12 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 9:51:12 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:12 AM] [PortfolioManager.Program::Main(args)]There were 46 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:12 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:33 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:33 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:33 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:33 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 9:51:36 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 9:51:39 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 9:51:39 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=14][TRACE.VERBOSE][6/22/2025 9:51:39 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:39 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:39 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:39 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'WaitSleepJoin'. Joining main thread...
[Thread=15][TRACE.VERBOSE][6/22/2025 9:51:40 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:40 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 9:51:40 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:40 AM] [PortfolioManager.Program::Main(args)]There were 46 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:51:40 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:52:29 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:52:30 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:52:30 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:52:30 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 9:52:33 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 9:52:37 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 9:52:37 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=15][TRACE.VERBOSE][6/22/2025 9:52:37 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 9:52:37 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:52:37 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=16][TRACE.VERBOSE][6/22/2025 9:52:37 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:52:37 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:52:37 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 9:52:37 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 9:52:38 AM] [PortfolioManager.Program::Main(args)]There were 45 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:52:38 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:53:05 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:53:05 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:53:05 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:53:05 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 9:53:09 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 9:53:11 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 9:53:11 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=13][TRACE.VERBOSE][6/22/2025 9:53:11 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 9:53:11 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:53:11 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=14][TRACE.VERBOSE][6/22/2025 9:53:11 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:53:11 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:53:11 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 9:53:11 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 9:53:11 AM] [PortfolioManager.Program::Main(args)]There were 45 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:53:11 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:57:25 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:57:26 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:57:26 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:57:26 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 9:57:30 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 9:57:40 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 9:57:40 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=14][TRACE.VERBOSE][6/22/2025 9:57:40 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 9:57:40 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:57:40 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=15][TRACE.VERBOSE][6/22/2025 9:57:40 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:57:40 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 9:57:40 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 9:57:40 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 9:57:40 AM] [PortfolioManager.Program::Main(args)]There were 46 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 9:57:40 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:59:52 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 9:59:53 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:59:53 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 9:59:53 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 9:59:56 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 10:00:07 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 10:00:07 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=14][TRACE.VERBOSE][6/22/2025 10:00:07 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 10:00:07 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 10:00:07 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=1][TRACE.VERBOSE][6/22/2025 10:00:07 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'WaitSleepJoin'. Joining main thread...
[Thread=15][TRACE.VERBOSE][6/22/2025 10:00:08 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 10:00:08 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 10:00:08 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 10:00:08 AM] [PortfolioManager.Program::Main(args)]There were 46 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 10:00:08 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 10:05:23 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 10:05:23 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 10:05:23 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 10:05:23 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 10:05:27 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 10:06:06 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 10:06:06 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=16][TRACE.VERBOSE][6/22/2025 10:06:06 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 10:06:06 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 10:06:06 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=17][TRACE.VERBOSE][6/22/2025 10:06:06 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 10:06:06 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 10:06:06 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 10:06:06 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 10:06:06 AM] [PortfolioManager.Program::Main(args)]There were 45 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 10:06:06 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 10:06:24 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 10:06:24 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 10:06:24 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 10:06:24 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 10:06:28 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 10:07:55 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 10:07:55 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=18][TRACE.VERBOSE][6/22/2025 10:07:55 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 10:07:55 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 10:07:55 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=19][TRACE.VERBOSE][6/22/2025 10:07:55 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 10:07:55 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 10:07:55 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 10:07:55 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 10:07:55 AM] [PortfolioManager.Program::Main(args)]There were 43 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 10:07:55 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 10:08:52 AM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 10:08:52 AM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 10:08:52 AM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 10:08:52 AM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 10:11:32 AM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 10:11:58 AM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 10:11:58 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=11][TRACE.VERBOSE][6/22/2025 10:11:58 AM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 10:11:58 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 10:11:58 AM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=3][TRACE.VERBOSE][6/22/2025 10:11:58 AM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 10:11:58 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 10:11:58 AM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 10:11:58 AM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 10:11:58 AM] [PortfolioManager.Program::Main(args)]There were 43 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 10:11:58 AM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]
[Thread=1][TRACE.VERBOSE][6/22/2025 12:16:45 PM] [PortfolioManager.Program::Main(args)][MAIN:STARTING]
[Thread=1][TRACE.VERBOSE][6/22/2025 12:16:46 PM] [PortfolioManager.Program::Main(args)]Using portfolio_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 12:16:46 PM] [PortfolioManager.Program::Main(args)]Using market_data at Adrastea
[Thread=1][TRACE.VERBOSE][6/22/2025 12:16:46 PM] [PortfolioManager.Program::Main(args)]Using user_data at Adrastea
[Thread=1][TRACE.DEBUG][6/22/2025 12:26:04 PM] [PortfolioManager.Cache.ImageCache::.ctor()]Reading assets from C:\Avalonia\PortfolioManager/Assets
[Thread=1][TRACE.DEBUG][6/22/2025 12:53:07 PM] [PortfolioManager.App+<>c__DisplayClass1_1::<OnFrameworkInitializationCompleted>b__1(<p0>,<p1>)]App: Received ClosingHandler event
[Thread=1][TRACE.DEBUG][6/22/2025 12:53:07 PM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose]
[Thread=107][TRACE.VERBOSE][6/22/2025 12:53:07 PM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc] Thread ended. Items in cache:0
[Thread=1][TRACE.VERBOSE][6/22/2025 12:53:07 PM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 12:53:07 PM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End
[Thread=106][TRACE.VERBOSE][6/22/2025 12:53:07 PM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended.
[Thread=1][TRACE.VERBOSE][6/22/2025 12:53:07 PM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'Running'. Joining main thread...
[Thread=1][TRACE.VERBOSE][6/22/2025 12:53:07 PM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End.
[Thread=1][TRACE.DEBUG][6/22/2025 12:53:07 PM] [PortfolioManager.ViewModels.MainWindowViewModel::OnDispose()][MainWindowViewModel:OnDispose] LEAVE
[Thread=1][TRACE.VERBOSE][6/22/2025 12:53:07 PM] [PortfolioManager.Program::Main(args)]There were 36 threads still running at application shutdown.
[Thread=1][TRACE.VERBOSE][6/22/2025 12:53:07 PM] [PortfolioManager.Program::Main(args)][MAIN:EXIT]