- @foreach (PurchasedStock cur in Session.TrackedStocks){
-
-
-
@cur.Symbol
-
Purchased Price: @cur.PurchasePrice
-
Purchased Quantity: @cur.Quantity
-
Purchased Date: @cur.PurchaseDate.ToString("M-dd-yyyy")
- @if (Debounce){
-
- }else{
-
- }
-
-
- ->
-
- @if (cur.PredictedMovement == -1){
-
- } else if (cur.PredictedMovement == 1){
-
- } else{
-
- }
-
+
+
+
+
+
Current Signal
- }
+ @foreach (Stock cur in Session.TrackedStocks){
+
+
@cur.Symbol
+
AI Predicted Score: @cur.Score
+
+
+ }
+
+
+
+
+
Trade History
+
+ @foreach (PurchasedStock cur in Session.TradeHistory){
+
+
@cur.Symbol
+
Purchased Quantity: @cur.Quantity
+
Purchased Price: @cur.PurchasePrice
+
Sell Price: @cur.PurchasePrice
+
+ }
+
}
@@ -108,16 +93,8 @@
/////////////////////////////////////////////////////////////////////////////////////////////
loginSession? Session = null;
-
- // On Page Load
- string PaymentKey = "";
- protected override async Task OnInitializedAsync(){
-
- }
-
-
-
-
+ string resultError = "";
+
@@ -126,213 +103,96 @@
string passWord = "";
string loginError = "";
async Task LoginSession(){
- string dbPrefix = $"[{userName.ToLower()}]:"; // Set the DB prefix for the get and set
- string passwordhash = dbDriver.Get( dbPrefix + "password" ); // Pull the password hash
+ string dbPrefix = $"[{userName.ToLower()}]:";
+
+ // Check if user already exists
+ string passwordhash = dbDriver.Get( dbPrefix + "password" );
if (string.IsNullOrEmpty(passwordhash)){
loginError = "no account found with that username";
return;
}
- if (BCrypt.Verify( passWord, passwordhash )){ // If the password is valid
- List
? stocks = JsonConvert.DeserializeObject>( dbDriver.Get( dbPrefix + "Stocks" ) );
- bool moneyLoaded = float.TryParse(dbDriver.Get( dbPrefix + "money" ), out float moneyResult);
- Session = new loginSession(){
- UserName = userName.ToLower(),
- TrackedStocks = stocks != null ? stocks : new List(),
- Money = moneyLoaded ? moneyResult : 1000
- };
- (bool, string) result = PaymentProcessor.CreatePayment(Session.UserName);
- if (!result.Item1){
- resultError = result.Item2;
- }
- PaymentKey = result.Item2;
- }else{
+
+ // Check the password is valid
+ if (!BCrypt.Verify( passWord, passwordhash )){
loginError = "wrong password";
+ return;
}
+
+ // Load the users account
+ List? history = JsonConvert.DeserializeObject>( dbDriver.Get( dbPrefix + "history" ) );
+ List? stocks = JsonConvert.DeserializeObject>( dbDriver.Get( dbPrefix + "watched" ) );
+ bool moneyLoaded = float.TryParse(dbDriver.Get( dbPrefix + "money" ), out float moneyResult);
+ Session = new loginSession(){
+ UserName = userName.ToLower(),
+ TradeHistory = history != null ? history : new List(),
+ TrackedStocks = stocks != null ? stocks : new List(),
+ Money = moneyLoaded ? moneyResult : 1000
+ };
}
async Task registerSession(){
string dbPrefix = $"[{userName.ToLower()}]:";
+
+ // Check if user already exists
string passwordhash = dbDriver.Get( dbPrefix + "password" );
- if (string.IsNullOrEmpty(passwordhash)){
- dbDriver.Set( dbPrefix + "password", BCrypt.HashPassword( passWord, BCrypt.GenerateSalt() ) );
- dbDriver.Set( dbPrefix + "money", "1000" );
- Session = new loginSession(){
- UserName = userName.ToLower(),
- TrackedStocks = new List(),
- Money = 1000
- };
- (bool, string) result = PaymentProcessor.CreatePayment(Session.UserName);
- if (!result.Item1){
- resultError = result.Item2;
- }
- PaymentKey = result.Item2;
- }else{
+ if (!string.IsNullOrEmpty(passwordhash)){
loginError = "account is taken";
+ return;
}
+
+ // Create User Object on the database
+ dbDriver.Set( dbPrefix + "password", BCrypt.HashPassword( passWord, BCrypt.GenerateSalt() ) );
+ dbDriver.Set( dbPrefix + "money", "1000" );
+ Session = new loginSession(){
+ UserName = userName.ToLower(),
+ TradeHistory = new List(),
+ TrackedStocks = new List(),
+ Money = 1000
+ };
+
+ // Add the users to a global table for automation
+ List? Users = JsonConvert.DeserializeObject>( dbDriver.Get( "Users" ) );
+ List verifiedUsers = Users != null ? Users : new List();
+ verifiedUsers.Add(userName.ToLower());
+ dbDriver.Set( "Users", JsonConvert.SerializeObject(verifiedUsers) );
}
+ string addStockSymbol = "";
+ async Task addStock(){
-
-
- // AI Stuff
-
- string trainButtonText = "Force Retrain AI";
- string predictButtonText = "Predict AI";
- string resultError = "";
- bool Debounce = true;
-
- async Task train(){
- resultError = "";
- if (Debounce){
- Debounce = false;
- trainButtonText = "Do not refresh the page. The AI is training.";
- await Task.Delay(1);
- Task thread = new Task(async () => {
- aiModule.TrainAI();
- trainButtonText = "AI Trained";
- await Task.Delay(2000);
- trainButtonText = "Train AI";
- await Task.Delay(1);
- Debounce = true;
- });
- thread.Start();
+ // Make sure a session exists
+ if (Session == null){
+ return;
}
- }
- async Task predict(){
- resultError = "";
- if (Debounce && Session != null){
- Debounce = false;
- predictButtonText = "Do not refresh the page. The AI is predicting";
- await Task.Delay(1);
- List threadpool = new List();
- foreach(PurchasedStock cur in Session.TrackedStocks){
- Task thread = new Task(() => {
- (string, int)Result = aiModule.PredictAI(cur.Symbol);
- if (string.IsNullOrEmpty(Result.Item1)){
- cur.PredictedMovement = Result.Item2;
- }else{
- resultError = Result.Item1;
- }
- Console.WriteLine("Received Signal [" + cur.Symbol + "] : " + cur.PredictedMovement);
- });
- thread.Start();
- threadpool.Add(thread);
- }
- await Task.WhenAll(threadpool);
- predictButtonText = "Predictions loaded";
- await Task.Delay(2000);
- predictButtonText = "Predict AI";
- Debounce = true;
- await Task.Delay(1);
- }
+ // Add a tracked stock to the users account
+ Session.TrackedStocks.Add(new Stock(){
+ Symbol = addStockSymbol.ToUpper()
+ });
+
+ // Save the users account
+ string dbPrefix = $"[{userName.ToLower()}]:";
+ dbDriver.Set(dbPrefix + "watched", JsonConvert.SerializeObject(Session.TrackedStocks) );
}
+ async Task removeStock(Stock stock){
-
-
- // Stock Manipulation
-
- string buyStockSymbol = "";
- string buyStockQuantity = "";
- async Task buyStock(){
- if (Debounce && Session != null){
- Debounce = false;
- await Task.Delay(1);
-
- string dbPrefix = $"[{userName.ToLower()}]:";
- // Try Parse the quantitiy input
- bool success = float.TryParse(buyStockQuantity, out float QuantityResult);
- if (!success){
- resultError = "Quantity field is not a number";
- Debounce = true;
- await Task.Delay(1);
- return;
- }
-
- // Get Stock Price
- float stockPrice = aiModule.GetCurrentPrice( buyStockSymbol );
-
- // Try Pay for the stock
- (bool, string) result = PaymentProcessor.TryPayment(PaymentKey, QuantityResult * stockPrice);
- if (!result.Item1){
- resultError = result.Item2;
- Debounce = true;
- await Task.Delay(1);
- return;
- }
-
- // Add the stock
- Session.TrackedStocks.Add( new PurchasedStock(){
- Symbol = buyStockSymbol.ToUpper(),
- PurchasePrice = stockPrice,
- Quantity = QuantityResult,
- PurchaseDate = DateTime.Now
- } );
- dbDriver.Set( dbPrefix + "Stocks", Newtonsoft.Json.JsonConvert.SerializeObject(Session.TrackedStocks) );
-
- // Reload the users money
- bool moneyLoaded = float.TryParse(dbDriver.Get( dbPrefix + "money" ), out float moneyResult);
- Session.Money = moneyLoaded ? moneyResult : 1000;
-
- // Reset the Impodent Key
- result = PaymentProcessor.CreatePayment(Session.UserName);
- if (!result.Item1){
- resultError = "[New payment session failed] : " + result.Item2;
- Debounce = true;
- await Task.Delay(1);
- return;
- }
- PaymentKey = result.Item2;
- Debounce = true;
- await Task.Delay(1);
+ // Make sure a session exists
+ if (Session == null){
+ return;
}
- }
+
+ // Remove the stock
+ Session.TrackedStocks.Remove(stock);
- async Task sellStock(PurchasedStock stock){
- string dbPrefix = $"[{userName.ToLower()}]:";
- if (Debounce && Session != null){
- Debounce = false;
- await Task.Delay(1);
-
- // Get sell price
- float sellPrice = stock.Quantity * aiModule.GetCurrentPrice( stock.Symbol );
-
- // Try to sell the stock
- (bool, string) result = PaymentProcessor.TrySell(PaymentKey, sellPrice);
- if (!result.Item1){
- resultError = result.Item2;
- Debounce = true;
- await Task.Delay(1);
- return;
- }
-
- // Remove Stock
- Session.TrackedStocks.Remove(stock);
- dbDriver.Set( dbPrefix + "Stocks", Newtonsoft.Json.JsonConvert.SerializeObject(Session.TrackedStocks) );
-
- // Reload the users money
- bool moneyLoaded = float.TryParse(dbDriver.Get( dbPrefix + "money" ), out float moneyResult);
- Session.Money = moneyLoaded ? moneyResult : 1000;
-
- // Reset the Impodent Key
- result = PaymentProcessor.CreatePayment(Session.UserName);
- if (!result.Item1){
- resultError = "[New payment session failed] : " + result.Item2;
- Debounce = true;
- await Task.Delay(1);
- return;
- }
- PaymentKey = result.Item2;
-
- Debounce = true;
- await Task.Delay(1);
- }
+ // Save the users account
+ string dbPrefix = $"[{userName.ToLower()}]:";
+ dbDriver.Set(dbPrefix + "watched", JsonConvert.SerializeObject(Session.TrackedStocks) );
}
}
\ No newline at end of file
diff --git a/WebServer/Controllers/Automation.cs b/WebServer/Controllers/Automation.cs
new file mode 100644
index 00000000..85a18f8e
--- /dev/null
+++ b/WebServer/Controllers/Automation.cs
@@ -0,0 +1,145 @@
+using Controllers.DataBase;
+using Entities;
+using Newtonsoft.Json;
+
+namespace Controllers.PythonInterop {
+
+ public class Automation {
+
+ AIModule _aiModule;
+ DbDriver _dbDriver;
+ public Automation(AIModule aiModule, DbDriver dbDriver) {
+ _aiModule = aiModule;
+ _dbDriver = dbDriver;
+ }
+
+ public void GlobalPredictAI() {
+
+ // Start this process on a background thread so its non-blocking
+ Task thread = new Task(async () => {
+
+ // 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
+
+ // 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(async () => {
+ _aiModule.TrainAI();
+ });
+ thread.Start();
+ }
+
+ void sellStock(PurchasedStock stock){
+ string dbPrefix = $"[{userName.ToLower()}]:";
+ if (Session != null){
+
+ // Get sell price
+ float sellPrice = stock.Quantity * aiModule.GetCurrentPrice( stock.Symbol );
+
+ // Try to sell the stock
+ (bool, string) result = PaymentProcessor.TrySell(PaymentKey, sellPrice);
+ if (!result.Item1){
+ resultError = result.Item2;
+ return;
+ }
+
+ // Remove Stock
+ Session.TradeHistory.Remove(stock);
+ dbDriver.Set( dbPrefix + "Stocks", Newtonsoft.Json.JsonConvert.SerializeObject(Session.TradeHistory) );
+
+ // Reload the users money
+ bool moneyLoaded = float.TryParse(dbDriver.Get( dbPrefix + "money" ), out float moneyResult);
+ Session.Money = moneyLoaded ? moneyResult : 1000;
+
+ // Reset the Impodent Key
+ result = PaymentProcessor.CreatePayment(Session.UserName);
+ if (!result.Item1){
+ resultError = "[New payment session failed] : " + result.Item2;
+ return;
+ }
+ PaymentKey = result.Item2;
+ }
+ }
+
+ void buyStock(string StockSymbol){
+ if (Session != null){
+ string dbPrefix = $"[{userName.ToLower()}]:";
+
+ // Try Parse the quantitiy input
+ // Get the max quantity that I can Afford
+ float QuantityResult = 0;
+
+ // Get Stock Price
+ float stockPrice = aiModule.GetCurrentPrice( StockSymbol );
+
+ // Try Pay for the stock
+ (bool, string) result = PaymentProcessor.TryPayment(PaymentKey, QuantityResult * stockPrice);
+ if (!result.Item1){
+ resultError = result.Item2;
+ return;
+ }
+
+ // Add the stock
+ Session.TradeHistory.Add( new PurchasedStock(){
+ Symbol = StockSymbol.ToUpper(),
+ PurchasePrice = stockPrice,
+ Quantity = QuantityResult,
+ } );
+ dbDriver.Set( dbPrefix + "Stocks", Newtonsoft.Json.JsonConvert.SerializeObject(Session.TradeHistory) );
+
+ // Reload the users money
+ bool moneyLoaded = float.TryParse(dbDriver.Get( dbPrefix + "money" ), out float moneyResult);
+ Session.Money = moneyLoaded ? moneyResult : 1000;
+
+ // Reset the Impodent Key
+ result = PaymentProcessor.CreatePayment(Session.UserName);
+ if (!result.Item1){
+ resultError = "[New payment session failed] : " + result.Item2;
+ return;
+ }
+ PaymentKey = result.Item2;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/WebServer/Entities/LoginSession.cs b/WebServer/Entities/LoginSession.cs
index ce4d1dc7..a384c1f0 100644
--- a/WebServer/Entities/LoginSession.cs
+++ b/WebServer/Entities/LoginSession.cs
@@ -3,7 +3,8 @@ namespace Entities {
class loginSession {
public string UserName { get; set; } = "";
public float Money { get; set; } = 0;
- public List TrackedStocks { get; set; } = new List();
+ public List TrackedStocks { get; set; } = new List();
+ public List TradeHistory { get; set; } = new List();
}
}
\ No newline at end of file
diff --git a/WebServer/Entities/PurchasedStock.cs b/WebServer/Entities/PurchasedStock.cs
index 7936aa19..1cfd5046 100644
--- a/WebServer/Entities/PurchasedStock.cs
+++ b/WebServer/Entities/PurchasedStock.cs
@@ -2,10 +2,9 @@ namespace Entities {
class PurchasedStock {
public string Symbol { get; set; } = "";
- public float PurchasePrice { get; set; } = 0;
public float Quantity { get; set; } = 0;
- public DateTime PurchaseDate { get; set; } = DateTime.Now;
- public int PredictedMovement { get; set; } = 0;
+ public float PurchasePrice { get; set; } = 0;
+ public float SellPrice { get; set; } = 0;
}
}
\ No newline at end of file
diff --git a/WebServer/Entities/Stock.cs b/WebServer/Entities/Stock.cs
new file mode 100644
index 00000000..077ef013
--- /dev/null
+++ b/WebServer/Entities/Stock.cs
@@ -0,0 +1,8 @@
+namespace Entities {
+
+ class Stock {
+ public string Symbol { get; set; } = "";
+ public float Score { get; set; } = 0;
+ }
+
+}
\ No newline at end of file