From 6172d1c373ec437110260347694f9a97da6f2214 Mon Sep 17 00:00:00 2001 From: derek holloway Date: Thu, 19 Feb 2026 15:09:06 -0800 Subject: [PATCH] Use threading for python. and make singals from python --- WebServer/AIPython/ai-predictor.py | 16 +++++++++-- WebServer/Components/Pages/Home.razor | 39 +++++++++++++++++++++++--- WebServer/Controllers/PythonInterop.cs | 8 ++---- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/WebServer/AIPython/ai-predictor.py b/WebServer/AIPython/ai-predictor.py index 8570261b..1934b4b6 100644 --- a/WebServer/AIPython/ai-predictor.py +++ b/WebServer/AIPython/ai-predictor.py @@ -8,18 +8,20 @@ import features import matplotlib matplotlib.use("Agg") -def Predict(): +def Predict(Symbol): # Define paths (consistent with your previous script) SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) DATA_DIR = os.path.join(SCRIPT_DIR, "data") MODEL_PATH = os.path.join(DATA_DIR, "model.keras") # Pull 1 month of current data to make prediction against | for volatility 20 - df = yf.download("NVDA", period="2mo", auto_adjust=True) + df = yf.download(Symbol, period="2mo", auto_adjust=True) if not df.empty: df = features.MakeFeatures(df, 1) df = features.CleanDF(df) + print(Symbol) + # Drop our predictor df.drop('Target_Close', axis=1, inplace=True) @@ -50,7 +52,15 @@ def Predict(): print(f"Predicted Target_Close: {flat_predictions}") - return json.dumps(flat_predictions) + movement_indicator = 0 + if (np.mean(flat_predictions) > 0.01): + movement_indicator = 1 + elif (np.mean(flat_predictions) < -0.01): + movement_indicator = -1 + else: + movement_indicator = 0 + + return movement_indicator if __name__ == "__main__": Predict() \ No newline at end of file diff --git a/WebServer/Components/Pages/Home.razor b/WebServer/Components/Pages/Home.razor index 801b9559..bef96989 100644 --- a/WebServer/Components/Pages/Home.razor +++ b/WebServer/Components/Pages/Home.razor @@ -22,8 +22,17 @@ - @foreach(double cur in predictions){ -

@cur


+ @foreach (stockPredictionPair cur in predictions){ +
+

Symbol: @cur.Symbol


+ @if (cur.Movement == -1){ +

Sell

+ } else if (cur.Movement == 1){ +

Buy

+ } else{ +

Hold

+ } +
} @@ -34,7 +43,13 @@ string button1Text = "Train AI"; string button2Text = "Predict AI"; - double[] predictions = {}; + + List predictions = new List(){ + new stockPredictionPair(){ Symbol = "AAPL" }, + new stockPredictionPair(){ Symbol = "AAPL" }, + new stockPredictionPair(){ Symbol = "TTD" }, + new stockPredictionPair(){ Symbol = "FUN" } + }; async Task pullandtrain(){ button1Text = "Do not refresh the page. The data is refreshing."; @@ -46,8 +61,24 @@ async Task predict(){ button2Text = "Do not refresh the page. The data is refreshing."; await Task.Delay(1); - predictions = aiModule.PredictAI(); + List threadpool = new List(); + foreach(stockPredictionPair cur in predictions){ + Task thread = new Task(() => { + cur.Movement = aiModule.PredictAI(cur.Symbol); + Console.WriteLine("Received Signal [" + cur.Symbol + "] : " + cur.Movement); + }); + thread.Start(); + threadpool.Add(thread); + } + await Task.WhenAll(threadpool); button2Text = "Refresh Completed"; + StateHasChanged(); + await Task.Delay(1); + } + + class stockPredictionPair{ + public string Symbol = ""; + public int Movement = 0; } } \ No newline at end of file diff --git a/WebServer/Controllers/PythonInterop.cs b/WebServer/Controllers/PythonInterop.cs index c9c080ef..dfe303b4 100644 --- a/WebServer/Controllers/PythonInterop.cs +++ b/WebServer/Controllers/PythonInterop.cs @@ -30,13 +30,11 @@ namespace PythonInterop { } } - public double[] PredictAI() { + public int PredictAI(string StockSymbol) { using (Py.GIL()) { dynamic main = Py.Import("ai-predictor"); - string result = main.Predict(); - double[]? predictions = JsonSerializer.Deserialize(result); - double[] nullCasted = predictions != null ? predictions : []; - return nullCasted; + int result = main.Predict(StockSymbol); + return result; } }