using System; using System.Linq; using Eremex.AvaloniaUI.Charts; using MarketData.MarketDataModel; using MarketData.MarketDataModel.GainLoss; using MarketData.Numerical; using MarketData.Utils; using PortfolioManager.DataSeriesViewModels; namespace PortfolioManager.Models { public class GainLossModel { private GainLossModel() { } public static CompositeDataSource Empty() { CompositeDataSource compositeDataSource = new CompositeDataSource() { DataAdapter = new SortedDateTimeDataAdapter() }; return compositeDataSource; } public static CompositeDataSource Price(Price price) { if (null == price) return Empty(); SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter(); sortedDateTimeDataAdapter.Add(price.Date, price.Close); CompositeDataSource compositeDataSource = new CompositeDataSource() { DataAdapter = sortedDateTimeDataAdapter }; return compositeDataSource; } // public static CompositeDataSource CreateCompositeDataSource(DateTime xSource, double ySource) // { // if (Utility.IsEpoch(xSource)) return Empty(); // SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter(); // sortedDateTimeDataAdapter.Add(xSource, ySource); // CompositeDataSource compositeDataSource = new CompositeDataSource() // { // DataAdapter = sortedDateTimeDataAdapter // }; // return compositeDataSource; // } // This is the active gain/loss as number or percent. public static CompositeDataSource GainLoss(ModelPerformanceSeries gainLossList, bool useGainLoss) { if (null == gainLossList) return Empty(); SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter(); foreach (ModelPerformanceItem modelPerformanceItem in gainLossList) { sortedDateTimeDataAdapter.Add(modelPerformanceItem.Date, useGainLoss ? modelPerformanceItem.CumulativeGainLoss : modelPerformanceItem.CumProdMinusOne * 100.00); } CompositeDataSource compositeDataSource = new CompositeDataSource() { DataAdapter = sortedDateTimeDataAdapter }; return compositeDataSource; } // This is the active gain/loss as number or percent. public static CompositeDataSource GainLoss(GainLossCompoundModelCollection gainLossList, bool useGainLoss) { if (null == gainLossList) return Empty(); GainLossCompoundModelCollection sortedCollection = new GainLossCompoundModelCollection(gainLossList.OrderBy(x => x.Date).ToList()); SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter(); foreach (GainLossCompoundModel gainLossCompoundModel in sortedCollection) { sortedDateTimeDataAdapter.Add(gainLossCompoundModel.Date, useGainLoss ? gainLossCompoundModel.ActiveGainLoss : gainLossCompoundModel.ActiveGainLossPercent); } CompositeDataSource compositeDataSource = new CompositeDataSource() { DataAdapter = sortedDateTimeDataAdapter }; return compositeDataSource; } // This is the total gain loss as number or percent public static CompositeDataSource TotalGainLoss(GainLossCompoundModelCollection gainLossList, bool useGainLoss) { if (null == gainLossList) return Empty(); GainLossCompoundModelCollection sortedCollection = new GainLossCompoundModelCollection(gainLossList.OrderBy(x => x.Date).ToList()); SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter(); foreach (GainLossCompoundModel gainLossCompoundModel in sortedCollection) { sortedDateTimeDataAdapter.Add(gainLossCompoundModel.Date, useGainLoss ? gainLossCompoundModel.TotalGainLoss : gainLossCompoundModel.TotalGainLossPercent); } CompositeDataSource compositeDataSource = new CompositeDataSource() { DataAdapter = sortedDateTimeDataAdapter }; return compositeDataSource; } // This is the least squares composite data source based on the active gain/loss public static CompositeDataSource LeastSquares(GainLossCompoundModelCollection gainLossList, bool useGainLoss) { if (null == gainLossList) return Empty(); LeastSquaresResult leastSquaresResult = LeastSquaresFit(gainLossList, useGainLoss); GainLossCompoundModelCollection sortedCollection = new GainLossCompoundModelCollection(gainLossList.OrderBy(x => x.Date).ToList()); SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter(); for (int index = 0; index < sortedCollection.Count; index++) { GainLossCompoundModel gainLossCompoundModel = sortedCollection[index]; int leastSquaresIndex = (leastSquaresResult.LeastSquares.Length - 1) - index; sortedDateTimeDataAdapter.Add(gainLossCompoundModel.Date, leastSquaresResult.LeastSquares[leastSquaresIndex]); } CompositeDataSource compositeDataSource = new CompositeDataSource() { DataAdapter = sortedDateTimeDataAdapter }; return compositeDataSource; } // This is the least squares composite data source based on the active gain/loss public static CompositeDataSource TotalLeastSquares(GainLossCompoundModelCollection gainLossList, bool useGainLoss) { if (null == gainLossList) return Empty(); LeastSquaresResult leastSquaresResult = TotalLeastSquaresFit(gainLossList, useGainLoss); GainLossCompoundModelCollection sortedCollection = new GainLossCompoundModelCollection(gainLossList.OrderBy(x => x.Date).ToList()); SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter(); for (int index = 0; index < sortedCollection.Count; index++) { GainLossCompoundModel gainLossCompoundModel = sortedCollection[index]; int leastSquaresIndex = (leastSquaresResult.LeastSquares.Length - 1) - index; sortedDateTimeDataAdapter.Add(gainLossCompoundModel.Date, leastSquaresResult.LeastSquares[leastSquaresIndex]); } CompositeDataSource compositeDataSource = new CompositeDataSource() { DataAdapter = sortedDateTimeDataAdapter }; return compositeDataSource; } // ***************************************** C A L C U L A T O R S ********************************** // This is the LeastSquares fit based on the active gain/loss public static LeastSquaresResult LeastSquaresFit(GainLossCompoundModelCollection gainLossList, bool useGainLoss) { double[] values = null; if (useGainLoss) values = (from GainLossCompoundModel gainLoss in gainLossList select gainLoss.ActiveGainLoss).ToList().ToArray(); else values = (from GainLossCompoundModel gainLoss in gainLossList select gainLoss.ActiveGainLossPercent).ToList().ToArray(); LeastSquaresResult leastSquaresResult = Numerics.LeastSquares(values); return leastSquaresResult; } // This is the LeastSquares fit based on the total gain/loss public static LeastSquaresResult TotalLeastSquaresFit(GainLossCompoundModelCollection gainLossList,bool useGainLoss) { double[] values=null; if(useGainLoss)values=(from GainLossCompoundModel gainLoss in gainLossList select gainLoss.TotalGainLoss).ToList().ToArray(); else values=(from GainLossCompoundModel gainLoss in gainLossList select gainLoss.TotalGainLossPercent).ToList().ToArray(); LeastSquaresResult leastSquaresResult=Numerics.LeastSquares(values); return leastSquaresResult; } } }