using Microsoft.AspNetCore.Components; using MudBlazor; using MarketData.Service; using Microsoft.AspNetCore.Components.Authorization; using eNavigator.Routes; using MarketData.Utils; using MarketData.MarketDataModel; using eNavigator.Models; using System.Text; namespace eNavigator.Pages { public partial class BollingerBands { [Inject] private AuthenticationStateProvider authenticationStateProvider { get; set; } = default; [Inject] private NavigationManager NavigationManager { get; set; } = default!; protected bool IsBusy { get; set; } = false; protected String BusyMessage { get; set;} = ""; protected List AvailableSymbols { get; set;} = new List{new SelectableSymbol(){Index=0,Name="---"}}; protected SelectableSymbol SelectedSymbol { get; set; } = new SelectableSymbol(){Index=0,Name="---"}; protected List BollingerBandElements { get; set; } = new List(); protected List AvailableDayCounts { get; set; } = new List{60,90,120,180,360,720,1440}; protected int SelectedDayCount { get; set; } = 120; protected String Heading { get; set; } = ""; protected List ChartSeriesCollection { get; set; } = new List(); protected ChartOptions ChartingOptions{ get; set; } = new ChartOptions(); protected String[] XAxisLabels { get; set; } = new String[]{""}; protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); AuthenticationState authenticationState = await authenticationStateProvider.GetAuthenticationStateAsync(); if(!authenticationState.User.Identity.IsAuthenticated) { NavigationManager.NavigateTo(PageRoute.Login); return; } await LoadSymbols(); SelectedSymbol = AvailableSymbols.Count()>0 ? AvailableSymbols[0] : SelectedSymbol; await LoadBollingerBands(SelectedSymbol.Name, SelectedDayCount); StateHasChanged(); Task.Run(async () => await Task.Yield()).GetAwaiter(); } private async Task LoadSymbols() { BusyMessage = $"Loading symbols..."; IsBusy = true; ServiceResult serviceResult = await marketDataServiceClient.GetWatchList("Valuations"); if(!serviceResult.Success) { DisplayToast("Error contacting server, could not load latest headlines."); return; } List availableSymbolsList = (serviceResult.ContextSpecificResult as List); List availableSymbols = new List(); for(int index=0;index); DisplayToast($"Loaded {AvailableSymbols.Count} symbols in {Utility.FormatNumber(serviceResult.ElapsedTimeMS,0,true)}(ms)."); IsBusy = false; } private async Task LoadBollingerBands(String symbol,int dayCount) { String companyName = ""; BusyMessage = $"Loading {dayCount} day bollinger bands for {symbol} ..."; IsBusy = true; ServiceResult serviceResult = await marketDataServiceClient.GetCompanyNameForSymbol(symbol); if(serviceResult.Success) { companyName = (serviceResult.ContextSpecificResult as String); } serviceResult = await marketDataServiceClient.GetBollingerBands(symbol,dayCount); if(!serviceResult.Success) { DisplayToast("Error contacting server, could not load bollinger bands."); return; } BollingerBandElements = (serviceResult.ContextSpecificResult as List); // if(BollingerBandElements.Count()>0) // { // Heading = SelectedSymbol + " - " + companyName + "("+ BollingerBandElements[BollingerBandElements.Count()-1].Date.ToShortDateString() + " Thru " + BollingerBandElements[0].Date.ToShortDateString()+ ")"; // } DisplayToast($"Loaded {Utility.FormatNumber(BollingerBandElements.Count*13,0,true)} data points in {Utility.FormatNumber(serviceResult.ElapsedTimeMS,0,true)}(ms)."); CreateHeading(companyName); CreateChartSeries(); CreateChartOptions(); CreateXAxisLabels(); IsBusy = false; } private void DisplayToast(String message) { snackbarService.Add(new MarkupString($"
  • {message}
")); } private async Task OnSymbolChanged() { await LoadBollingerBands(SelectedSymbol.Name, SelectedDayCount); } private async Task OnDayCountChanged() { await LoadBollingerBands(SelectedSymbol.Name, SelectedDayCount); } protected async Task RefreshClicked() { await Task.FromResult(true); await LoadBollingerBands(SelectedSymbol.Name,SelectedDayCount); StateHasChanged(); Task.Run(async () => await Task.Yield()).GetAwaiter(); } private void CreateHeading(String companyName) { if(0==BollingerBandElements.Count()) { Heading = ""; return; } BollingerBandElement bollingerBandElementCurrent = BollingerBandElements[0]; BollingerBandElement bollingerBandElementPrev = BollingerBandElements[1]; StringBuilder sb = new StringBuilder(); sb.Append(companyName); sb.Append(" ("); sb.Append(SelectedSymbol ); sb.Append(") "); sb.Append(BollingerBandElements[BollingerBandElements.Count()-1].Date.ToShortDateString()); sb.Append(" Thru "); sb.Append(BollingerBandElements[0].Date.ToShortDateString()); if(BollingerBandElements.Count()<2) { Heading = sb.ToString(); return; } double change=double.NaN; if(0.00!=bollingerBandElementCurrent.Close) { change = (bollingerBandElementCurrent.Close - bollingerBandElementPrev.Close) / bollingerBandElementCurrent.Close; } sb.Append(" "); sb.Append("("); sb.Append(Utility.FormatCurrency(bollingerBandElementCurrent.Close)); sb.Append("/"); sb.Append(Utility.FormatCurrency(bollingerBandElementCurrent.Low)); if(!double.IsNaN(change)) { sb.Append(","); sb.Append(change>=0.00?"+":"").Append(Utility.FormatPercent((double)change,2)); } sb.Append(")"); Heading = sb.ToString(); } private void CreateXAxisLabels() { if(0==BollingerBandElements.Count()) { return; } XAxisLabels = BuildXAxisLabels(6).ToArray(); } private List BuildXAxisLabels(int labels) { List axisLabels = new List(); if(0==BollingerBandElements.Count()) { return axisLabels; } long dataPoints = BollingerBandElements.Count(); int intervals = (int)( (double)dataPoints/(double)labels); for(int index=BollingerBandElements.Count()-1;index>=0;index--) { if(0==(index%intervals)) { StringBuilder sb = new StringBuilder(); DateTime date = BollingerBandElements[index].Date; sb.Append(date.Month.ToString()); sb.Append("/"); sb.Append(date.Year.ToString()); axisLabels.Add(sb.ToString()); } else { axisLabels.Add(""); } } return axisLabels; } private void CreateChartOptions() { ChartingOptions = new ChartOptions() { LineStrokeWidth = 1, XAxisLines = true, YAxisFormat="c2", ChartPalette = new[] { "#0000FF", // High "#FF0000", // Low "#000000", // Close "#800080", // SMAN "#13A10E", // K "#13A10E", // L "#13A10E", // KL1 "#13A10E" // LP1 } }; } private void CreateChartSeries() { ChartSeriesCollection = new List(); if(0==BollingerBandElements.Count()) { return; } double[] highData = new double[BollingerBandElements.Count()]; double[] lowData = new double[BollingerBandElements.Count()]; double[] closeData = new double[BollingerBandElements.Count()]; double[] smanData = new double[BollingerBandElements.Count()]; double[] kData = new double[BollingerBandElements.Count()]; double[] lData = new double[BollingerBandElements.Count()]; double[] kl1Data = new double[BollingerBandElements.Count()]; double[] lp1Data = new double[BollingerBandElements.Count()]; for(int index=0;index