using Controllers.DataBase; using Controllers.Payment; using Controllers.PythonInterop; using Entities; using Newtonsoft.Json; namespace Controllers.Automation { public class AutomationController { AIModule _aiModule; DbDriver _dbDriver; IPayment _paymentProcessor; public AutomationController(AIModule aiModule, DbDriver dbDriver, IPayment PaymentProcessor) { _aiModule = aiModule; _dbDriver = dbDriver; _paymentProcessor = PaymentProcessor; } public void GlobalPredictAI() { // Start this process on a background thread so its non-blocking Task thread = new Task(() => { // Load the userlist List? UserList = JsonConvert.DeserializeObject>(_dbDriver.Get("Users")); List VerifiedUserList = UserList != null ? UserList : new List(); // Process each request at the same time for speed improvement Parallel.ForEach(VerifiedUserList, async (username) => { string dbPrefix = $"[{username.ToLower()}]:"; // Load the Tracked stocks for each user List? TrackedStocks = JsonConvert.DeserializeObject>( _dbDriver.Get( dbPrefix + "watched" ) ); List VerifiedTrackedStocks = TrackedStocks != null ? TrackedStocks : new List(); // Go through each stock List threadpool = new List(); foreach(Stock cur in VerifiedTrackedStocks) { // Predict the trend on a new thread Task thread = new Task(() => { (string, float)Result = _aiModule.PredictAI(cur.Symbol); // If error log it if (!string.IsNullOrEmpty(Result.Item1)){ Console.WriteLine(Result.Item1); } // Write the score to the users tracked stocks cur.Score = Result.Item2; }); thread.Start(); threadpool.Add(thread); } // Wait for all the threads to finish await Task.WhenAll(threadpool); // Process Stocks -> Buy Sell Hold / Based on the global data from earlier sellStock(username); // Save the new scores to the database for reference from the UI _dbDriver.Set( dbPrefix + "watched", JsonConvert.SerializeObject( VerifiedTrackedStocks ) ); }); }); thread.Start(); } public void GlobalTrainAI(){ Task thread = new Task(() => { _aiModule.PullAI(); _aiModule.TrainAI(); }); thread.Start(); } void sellStock(string username){ string dbPrefix = $"[{username.ToLower()}]:"; // Get all stock history List? PurchaseHistory = JsonConvert.DeserializeObject>( _dbDriver.Get( dbPrefix + "history" ) ); List VerifiedPurchaseHistory = PurchaseHistory != null ? PurchaseHistory : new List(); // Find the stocks that need to be sold foreach(PurchasedStock cur in VerifiedPurchaseHistory) { if (cur.Sold == false) { // Get sell price float sellPrice = cur.Quantity * _aiModule.GetCurrentPrice( cur.Symbol ); // Try create payment session (bool, string) createResult = _paymentProcessor.CreatePayment(username); if (!createResult.Item1) { Console.WriteLine("Create Payment Failure: " + createResult.Item2); return; } // Try to sell the stock (bool, string) paymentResult = _paymentProcessor.TrySell(createResult.Item2, sellPrice); if (!paymentResult.Item1){ Console.WriteLine("Process Payment Failure: " + paymentResult.Item2); return; } } } // Save the stock history _dbDriver.Set( dbPrefix + "Stocks", JsonConvert.SerializeObject(VerifiedPurchaseHistory) ); } void buyStock(string username, string stockSymbol){ string dbPrefix = $"[{username.ToLower()}]:"; // Get all stock history List? PurchaseHistory = JsonConvert.DeserializeObject>( _dbDriver.Get( dbPrefix + "history" ) ); List VerifiedPurchaseHistory = PurchaseHistory != null ? PurchaseHistory : new List(); // Get users money string MoneyStr = _dbDriver.Get( dbPrefix + "money"); bool Money = float.TryParse( MoneyStr, out float VerifiedMoney ); if (!Money) { Console.WriteLine( "Unable to load users money" ); VerifiedMoney = 0; } // Get Stock Price float stockPrice = _aiModule.GetCurrentPrice( stockSymbol ); // Get max stocks user can purchase [ int cast truncates the decimal ] int MaxQty = (int)( VerifiedMoney / stockPrice ); // Try create payment session (bool, string) createResult = _paymentProcessor.CreatePayment(username); if (!createResult.Item1) { Console.WriteLine("Create Payment Failure: " + createResult.Item2); return; } // Try Pay for the stock (bool, string) result = _paymentProcessor.TryPayment(createResult.Item2, stockPrice * MaxQty); if (!result.Item1){ Console.WriteLine("Process Payment Failure: " + result.Item2); return; } // Add the stock VerifiedPurchaseHistory.Add( new PurchasedStock(){ Symbol = stockSymbol.ToUpper(), PurchasePrice = stockPrice, Quantity = MaxQty, } ); _dbDriver.Set( dbPrefix + "Stocks", JsonConvert.SerializeObject(VerifiedPurchaseHistory) ); } } }