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