diff --git a/loader/loader.go b/loader/loader.go index 6e2afa3..a1fb2f8 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -8,6 +8,7 @@ import ( "encoding/json" "math" "strconv" + "time" "github.com/aleibovici/cryptopump/functions" "github.com/aleibovici/cryptopump/logger" @@ -56,6 +57,7 @@ func LoadSessionDataAdditionalComponents( RateCounter int64 /* Average Number of transactions per second proccessed by WsBookTicker */ BuyDecisionTreeResult string /* Hold BuyDecisionTree result */ SellDecisionTreeResult string /* Hold SellDecisionTree result */ + QuantityOffset float64 /* Quantity offset */ Orders []Order } @@ -83,6 +85,7 @@ func LoadSessionDataAdditionalComponents( sessiondata.Session.RateCounter = sessionData.RateCounter.Rate() / 5 /* Average Number of transactions per second proccessed by WsBookTicker */ sessiondata.Session.BuyDecisionTreeResult = sessionData.BuyDecisionTreeResult /* Hold BuyDecisionTree result*/ sessiondata.Session.SellDecisionTreeResult = sessionData.SellDecisionTreeResult /* Hold SellDecisionTree result */ + sessiondata.Session.QuantityOffset = sessiondata.Session.SymbolFunds /* Quantity offset */ sessiondata.Session.Profit = math.Round(sessionData.Global.Profit*100) / 100 /* Sessions.Global loaded from mySQL via loadSessionDataAdditionalComponentsAsync */ sessiondata.Session.ProfitPct = math.Round(sessionData.Global.ProfitPct*100) / 100 /* Sessions.Global loaded from mySQL via loadSessionDataAdditionalComponentsAsync */ @@ -104,6 +107,13 @@ func LoadSessionDataAdditionalComponents( tmp.Diff = math.Round((((key.ExecutedQuantity*sessiondata.Market.Price)*(1+configData.ExchangeComission))-key.CumulativeQuoteQuantity)*10) / 10 /* Difference between target and market price */ sessiondata.Session.Orders = append(sessiondata.Session.Orders, tmp) + sessiondata.Session.QuantityOffset -= tmp.Quantity /* Quantity offset */ + } + + if sessiondata.Session.QuantityOffset >= 0 { /* Only display Quantity offset if negative */ + sessiondata.Session.QuantityOffset = 0 + } else { + sessiondata.Session.QuantityOffset = math.Round(sessiondata.Session.QuantityOffset*100) / 100 /* Quantity offset */ } } @@ -132,10 +142,39 @@ func LoadSessionDataAdditionalComponentsAsync(sessionData *types.Session) { } }() - /* Load total profit and total profit percentage */ - if sessionData.Global.Profit, sessionData.Global.ProfitPct, err = mysql.GetProfit(sessionData); err != nil { + /* Get global data and execute GetProfit if more than 10 seconds since last update. + This function is used to prevent multiple threads from running mysql.GetProfit and + overloading mySQL server since this is a high cost SQL statement. */ + if profit, profitPct, transactTime, err := mysql.GetGlobal(sessionData); err == nil { - return + sessionData.Global.Profit = profit /* Load global profit from db */ + sessionData.Global.ProfitPct = profitPct /* Load global profit from db */ + + if transactTime == 0 { /* If transactTime is 0 then this is the first time this function is called and insert record into db */ + + if err := mysql.SaveGlobal(sessionData); err != nil { + + return /* Return if error */ + + } + + } + + if time.Since(time.Unix(transactTime, 0)).Seconds() > 10 { /* Only execute GetProfit if more than 10 seconds since last update */ + + if sessionData.Global.Profit, sessionData.Global.ProfitPct, err = mysql.GetProfit(sessionData); err != nil { /* Recalculate total profit and total profit percentage */ + + return /* Return if error */ + + } + + if err = mysql.UpdateGlobal(sessionData); err != nil { /* Update global data */ + + return /* Return if error */ + + } + + } } diff --git a/mysql/cryptopump.sql b/mysql/cryptopump.sql index dd6e1b2..b96fee1 100644 --- a/mysql/cryptopump.sql +++ b/mysql/cryptopump.sql @@ -17,6 +17,22 @@ USE `cryptopump`; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +-- +-- Table structure for table `global` +-- + +DROP TABLE IF EXISTS `global`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `global` ( + `ID` int NOT NULL AUTO_INCREMENT, + `Profit` float NOT NULL, + `ProfitPct` float NOT NULL, + `TransactTime` varchar(45) NOT NULL, + PRIMARY KEY (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci MAX_ROWS=1; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `orders` -- @@ -59,7 +75,7 @@ CREATE TABLE `session` ( `Status` tinyint(1) NOT NULL, PRIMARY KEY (`ID`), UNIQUE KEY `ThreadID_UNIQUE` (`ThreadID`) -) ENGINE=InnoDB AUTO_INCREMENT=1047 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +) ENGINE=InnoDB AUTO_INCREMENT=1406 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -78,7 +94,7 @@ CREATE TABLE `thread` ( `Price` float NOT NULL, `ExecutedQuantity` float NOT NULL, PRIMARY KEY (`ID`) -) ENGINE=InnoDB AUTO_INCREMENT=7380 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +) ENGINE=InnoDB AUTO_INCREMENT=8755 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -153,6 +169,33 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 DROP PROCEDURE IF EXISTS `GetGlobal` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_0900_ai_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +CREATE DEFINER=`root`@`%` PROCEDURE `GetGlobal`() +BEGIN +SELECT + `global`.`Profit` AS `Profit`, + `global`.`ProfitPct` AS `ProfitPct`, + `global`.`TransactTime` AS `TransactTime` +FROM + `global` +WHERE + `global`.`ID` = 1 +LIMIT 1; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 DROP PROCEDURE IF EXISTS `GetLastOrderTransactionPrice` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -557,6 +600,43 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 DROP PROCEDURE IF EXISTS `GetThreadTransactionByPriceHigher` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_0900_ai_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +CREATE DEFINER=`root`@`%` PROCEDURE `GetThreadTransactionByPriceHigher`(IN in_param_ThreadID varchar(45), IN in_param_Price float) +BEGIN + DECLARE declared_in_param_ThreadID CHAR(50); + DECLARE declared_in_param_Price FLOAT; + SET declared_in_param_ThreadID = in_param_ThreadID; + SET declared_in_param_Price = in_param_Price; + SELECT + `thread`.`CummulativeQuoteQty` AS `CummulativeQuoteQty`, + `thread`.`OrderID` AS `OrderID`, + `thread`.`Price` AS `Price`, + `thread`.`ExecutedQuantity` AS `ExecutedQuantity`, + `Orders`.`TransactTime` AS `TransactTime` +FROM + `thread` + LEFT JOIN + `orders` `Orders` ON `thread`.`OrderID` = `Orders`.`OrderID` +WHERE + (`thread`.`ThreadID` = declared_in_param_ThreadID + AND `thread`.`Price` > declared_in_param_Price) +ORDER BY `thread`.`Price` DESC +LIMIT 1; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 DROP PROCEDURE IF EXISTS `GetThreadTransactionByThreadID` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -656,6 +736,26 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 DROP PROCEDURE IF EXISTS `SaveGlobal` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_0900_ai_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +CREATE DEFINER=`root`@`%` PROCEDURE `SaveGlobal`(in_Profit float, in_ProfitPct float, in_TransactTime bigint) +BEGIN +INSERT INTO global (Profit, ProfitPct, TransactTime) +VALUES (in_Profit, in_ProfitPct, in_TransactTime); +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 DROP PROCEDURE IF EXISTS `SaveOrder` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -716,6 +816,33 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 DROP PROCEDURE IF EXISTS `UpdateGlobal` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_0900_ai_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +CREATE DEFINER=`root`@`%` PROCEDURE `UpdateGlobal`(in_Profit float, in_ProfitPct float, in_TransactTime bigint) +BEGIN +SET SQL_SAFE_UPDATES = 0; +UPDATE global +SET + Profit = in_Profit, + ProfitPct = in_ProfitPct, + TransactTime = in_TransactTime +WHERE + ID = 1; +SET SQL_SAFE_UPDATES = 1; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 DROP PROCEDURE IF EXISTS `UpdateOrder` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -776,4 +903,4 @@ DELIMITER ; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2021-08-29 21:35:31 +-- Dump completed on 2021-11-23 21:39:25 diff --git a/mysql/mysql.go b/mysql/mysql.go index 2edf82b..34fb718 100644 --- a/mysql/mysql.go +++ b/mysql/mysql.go @@ -5,6 +5,7 @@ import ( "fmt" "math" "os" + "time" "github.com/aleibovici/cryptopump/functions" "github.com/aleibovici/cryptopump/logger" @@ -271,6 +272,66 @@ func UpdateSession( } +// UpdateGlobal Update global settings +func UpdateGlobal( + sessionData *types.Session) (err error) { + + var rows *sql.Rows + + if rows, err = sessionData.Db.Query("call cryptopump.UpdateGlobal(?,?,?)", + sessionData.Global.Profit, + sessionData.Global.ProfitPct, + time.Now().Unix()); err != nil { + + logger.LogEntry{ + Config: nil, + Market: nil, + Session: sessionData, + Order: &types.Order{}, + Message: functions.GetFunctionName() + " - " + err.Error(), + LogLevel: "DebugLevel", + }.Do() + + return err + + } + + rows.Close() + + return nil + +} + +// SaveGlobal Save initial global settings +func SaveGlobal( + sessionData *types.Session) (err error) { + + var rows *sql.Rows + + if rows, err = sessionData.Db.Query("call cryptopump.SaveGlobal(?,?,?)", + sessionData.Global.Profit, + sessionData.Global.ProfitPct, + time.Now().Unix()); err != nil { + + logger.LogEntry{ + Config: nil, + Market: nil, + Session: sessionData, + Order: &types.Order{}, + Message: functions.GetFunctionName() + " - " + err.Error(), + LogLevel: "DebugLevel", + }.Do() + + return err + + } + + rows.Close() + + return nil + +} + // SaveSession Save new session to Session table. func SaveSession( configData *types.Config, @@ -981,6 +1042,35 @@ func GetProfit( return fiatNullFloat64.Float64, (percentageNullFloat64.Float64 * 100), err } +// GetGlobal get global data +func GetGlobal(sessiondata *types.Session) (profit float64, profitPct float64, transactTime int64, err error) { + + var rows *sql.Rows + + if rows, err = sessiondata.Db.Query("call cryptopump.GetGlobal()"); err != nil { + + logger.LogEntry{ + Config: nil, + Market: nil, + Session: sessiondata, + Order: &types.Order{}, + Message: functions.GetFunctionName() + " - " + err.Error(), + LogLevel: "DebugLevel", + }.Do() + + return 0, 0, 0, err + } + + for rows.Next() { + err = rows.Scan(&profit, &profitPct, &transactTime) + } + + rows.Close() + + return profit, profitPct, transactTime, err + +} + // GetThreadCount Retrieve Running Thread Count func GetThreadCount( sessionData *types.Session) (count int, err error) { diff --git a/templates/index.html b/templates/index.html index c2cd8ba..9827a2f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -52,6 +52,8 @@   + Offset +   Transact./h diff --git a/templates/index_nostart.html b/templates/index_nostart.html index 8d4a85b..fe20d7c 100644 --- a/templates/index_nostart.html +++ b/templates/index_nostart.html @@ -38,6 +38,7 @@ $('#divIDSessionSymbolFunds').html(json.Session.SymbolFunds); $('#divIDSessionSymbol_fiat').html(json.Session.SymbolFiat); $('#divIDSessionSymbol_fiat_funds').html(json.Session.SymbolFiatFunds); + $('#divIDSessionQuantityOffset').html(json.Session.QuantityOffset); $('#divIDSessionProfit').html(json.Session.Profit); $('#divIDSessionProfitPct').html(json.Session.ProfitPct); $('#divIDSessionProfitThreadID').html(json.Session.ProfitThreadID); @@ -122,6 +123,8 @@   + Offset +   Transact./h