Files
ARM64/eNavigator/eNavigatorUI/Pages/BollingerBands.razor.cs
2025-04-03 17:28:36 -04:00

285 lines
10 KiB
C#

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<SelectableSymbol> AvailableSymbols { get; set;} = new List<SelectableSymbol>{new SelectableSymbol(){Index=0,Name="---"}};
protected SelectableSymbol SelectedSymbol { get; set; } = new SelectableSymbol(){Index=0,Name="---"};
protected List<BollingerBandElement> BollingerBandElements { get; set; } = new List<BollingerBandElement>();
protected List<int> AvailableDayCounts { get; set; } = new List<int>{60,90,120,180,360,720,1440};
protected int SelectedDayCount { get; set; } = 120;
protected String Heading { get; set; } = "";
protected List<ChartSeries> ChartSeriesCollection { get; set; } = new List<ChartSeries>();
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<String> availableSymbolsList = (serviceResult.ContextSpecificResult as List<String>);
List<SelectableSymbol> availableSymbols = new List<SelectableSymbol>();
for(int index=0;index<availableSymbolsList.Count;index++)
{
availableSymbols.Add(new SelectableSymbol(){Name=availableSymbolsList[index],Index=index});
}
AvailableSymbols = availableSymbols; //(serviceResult.ContextSpecificResult as List<String>);
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<BollingerBandElement>);
// 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($"<ul><li>{message}</li></ul>"));
}
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<String> BuildXAxisLabels(int labels)
{
List<String> axisLabels = new List<String>();
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<ChartSeries>();
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<BollingerBandElements.Count();index++)
{
BollingerBandElement bollingerBandElement = BollingerBandElements[(BollingerBandElements.Count()-index)-1];
highData[index] = bollingerBandElement.High;
lowData[index] = bollingerBandElement.Low;
closeData[index] = bollingerBandElement.Close;
smanData[index] = bollingerBandElement.SMAN;
kData[index] = bollingerBandElement.K;
lData[index] = bollingerBandElement.L;
kl1Data[index] = bollingerBandElement.KL1;
lp1Data[index] = bollingerBandElement.LP1;
}
ChartSeries highSeries = new ChartSeries(){Name="High", Data=highData};
ChartSeries lowSeries = new ChartSeries(){Name="Low", Data=lowData};
ChartSeries closeSeries = new ChartSeries(){Name="Close", Data=closeData};
ChartSeries smanSeries = new ChartSeries(){Name="SMAN", Data=smanData};
ChartSeries kSeries = new ChartSeries(){Name="K", Data=kData};
ChartSeries lSeries = new ChartSeries(){Name="L", Data=lData};
ChartSeries kl1Series = new ChartSeries(){Name="KL1", Data=kl1Data};
ChartSeries lp1Series = new ChartSeries(){Name="LP1", Data=lp1Data};
ChartSeriesCollection.Add(highSeries);
ChartSeriesCollection.Add(lowSeries);
ChartSeriesCollection.Add(closeSeries);
ChartSeriesCollection.Add(smanSeries);
ChartSeriesCollection.Add(kSeries);
ChartSeriesCollection.Add(lSeries);
ChartSeriesCollection.Add(kl1Series);
ChartSeriesCollection.Add(lp1Series);
}
}
}