From 2cd76014bb013930086590b70c3dd551521e296c Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Sat, 10 Apr 2021 12:22:24 +0900 Subject: [PATCH 01/17] Poloniex allowed markets --- Core/MarketAnalyzer/BaseAnalyzer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/MarketAnalyzer/BaseAnalyzer.cs b/Core/MarketAnalyzer/BaseAnalyzer.cs index 4f0ff6d..ea9c210 100644 --- a/Core/MarketAnalyzer/BaseAnalyzer.cs +++ b/Core/MarketAnalyzer/BaseAnalyzer.cs @@ -316,7 +316,7 @@ namespace Core.MarketAnalyzer market = market.Replace("-", ""); break; case "poloniex": - market = market.Replace("-", ""); + market = market.Replace("_", ""); break; } if (recentMarkets.TryGetValue(recentMarketPair.Key, out recentMarket)) From d8bdc68f804c0551fb5ae5df840481848e7acb8c Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Sat, 10 Apr 2021 12:23:01 +0900 Subject: [PATCH 02/17] increment version --- PTMagic/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PTMagic/Program.cs b/PTMagic/Program.cs index fbebbf2..73e595d 100644 --- a/PTMagic/Program.cs +++ b/PTMagic/Program.cs @@ -6,7 +6,7 @@ using Core.Helper; using Microsoft.Extensions.DependencyInjection; -[assembly: AssemblyVersion("2.5.9")] +[assembly: AssemblyVersion("2.5.10")] [assembly: AssemblyProduct("PT Magic")] namespace PTMagic From a8278bae4d834b630567f432381424860250fd5a Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Sat, 10 Apr 2021 12:31:22 +0900 Subject: [PATCH 03/17] poloniex ignored/allowed fix --- Core/Main/PTMagic.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Main/PTMagic.cs b/Core/Main/PTMagic.cs index 9600417..7001425 100644 --- a/Core/Main/PTMagic.cs +++ b/Core/Main/PTMagic.cs @@ -1538,7 +1538,7 @@ namespace Core.Main market = market.Replace("-", ""); break; case "poloniex": - market = market.Replace("-", ""); + market = market.Replace("_", ""); break; } bool stopTriggers = false; From 7010e5bf7a06e71b6393993f3e9332cd35a9c934 Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Fri, 16 Apr 2021 12:26:31 +0900 Subject: [PATCH 04/17] fix missing quotes in default analyzer --- .../settings.analyzer.json | 90 +++++++++---------- .../DevSettings/settings.analyzer.json | 50 +++++------ 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json b/PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json index db5f9c9..d1b0744 100644 --- a/PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json +++ b/PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json @@ -11,20 +11,20 @@ "AnalyzerSettings": { "MarketAnalyzer": { "StoreDataMaxHours": 48, // Number of hours to store market data - "IntervalMinutes": 2, // Interval in minutes for PTMagic to check market trends and triggers + "IntervalMinutes": 2, // Interval in minutes for PTMagic to check market trends and triggers "ExcludeMainCurrency": true, // Excludes the main currency (for example BTC) from market trend analysis "MarketTrends": [ { "Name": "1h", // UNIQUE market trend name (to be referenced by your triggers below) "Platform": "Exchange", // Platform to grab prices from (Allowed values are: CoinMarketCap, Exchange) - "MaxMarkets": 50, // Number of markets/pairs to analyze sorted by 24h volume + "MaxMarkets": 50, // Number of markets/pairs to analyze sorted by 24h volume "TrendMinutes": 60, // Number of minutes to build a trend (1440 = 24h, 720 = 12h, 60 = 1h) "TrendCurrency": "Market", // Trend Currency to build the trend against. If set to "Fiat", the trend will - // take the USD value of your main currency into account to build the trend. + // take the USD value of your main currency into account to build the trend. // "Market" will build a trend against your base currency, such as BTC or USDT. "TrendThreshold": 15, // Any coin that is above 15% or below -15% for this timeframe will not be used when calculating the market average. - "DisplayGraph": false, // Use this trend in the graph on the PTM Monitor dashboard and market analyzer - "DisplayOnMarketAnalyzerList": false // Disply this trend for all coins on the PTM Monitor market analyzer + "DisplayGraph": false, // Use this trend in the graph on the PTM Monitor dashboard and market analyzer + "DisplayOnMarketAnalyzerList": false // Disply this trend for all coins on the PTM Monitor market analyzer }, { "Name": "6h", @@ -33,8 +33,8 @@ "TrendMinutes": 360, "TrendCurrency": "Market", "TrendThreshold": 30, - "DisplayGraph": true, - "DisplayOnMarketAnalyzerList": true + "DisplayGraph": true, + "DisplayOnMarketAnalyzerList": true }, { "Name": "12h", @@ -43,8 +43,8 @@ "TrendMinutes": 720, "TrendCurrency": "Market", "TrendThreshold": 50, - "DisplayGraph": true, - "DisplayOnMarketAnalyzerList": true + "DisplayGraph": true, + "DisplayOnMarketAnalyzerList": true }, { "Name": "24h", @@ -53,17 +53,17 @@ "TrendMinutes": 1440, "TrendCurrency": "Market", "TrendThreshold": 75, - "DisplayGraph": true, - "DisplayOnMarketAnalyzerList": true + "DisplayGraph": true, + "DisplayOnMarketAnalyzerList": true } ] }, // ================================ GLOBAL SETTINGS ================================ // "GlobalSettings": [ // Global settings for Profit Trailer properties - // - // =================================================================================== - // ----------------------------- + // + // =================================================================================== + // ----------------------------- { "SettingName": "EndOfTheWorld", // ANY UNIQUE name of your setting "TriggerConnection": "AND", // Define if triggers will be connected by AND or OR @@ -84,14 +84,14 @@ "PairsProperties": { // Properties for PAIRS.PROPERTIES // Any valid setting from https://wiki.profittrailer.com/en/config can be used here. // You can use a specific value, or apply a discrete OFFSET or OFFSETPERCENT to the value in your default PAIRS setting. - "DEFAULT_sell_only_mode_enabled": true, + "DEFAULT_sell_only_mode_enabled": "true", "DEFAULT_trailing_profit_OFFSETPERCENT": -50 }, "DCAProperties": { // Properties for DCA.PROPERTIES "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -75 } }, - // ----------------------------- + // ----------------------------- { "SettingName": "TankingDown", "TriggerConnection": "AND", @@ -123,10 +123,10 @@ "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 25, "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50 }, - "IndicatorsProperties": { + "IndicatorsProperties": { } }, - // ----------------------------- + // ----------------------------- { "SettingName": "BearSighted", "TriggerConnection": "AND", @@ -156,7 +156,7 @@ "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 10, "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10, }, - "IndicatorsProperties": { + "IndicatorsProperties": { } }, // ----------------------------- @@ -182,17 +182,17 @@ "max_trading_pairs_OFFSET": 1, //"DEFAULT_initial_cost_OFFSETPERCENT": 10, //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 10, - "DEFAULT_trailing_buy_OFFSETPERCENT": -10, + "DEFAULT_trailing_buy_OFFSETPERCENT": -10, "DEFAULT_A_sell_value_OFFSETPERCENT": 10 }, "DCAProperties": { "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -10, "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 10, }, - "IndicatorsProperties": { + "IndicatorsProperties": { } }, - // ----------------------------- + // ----------------------------- { "SettingName": "ToTheMoon", "TriggerConnection": "AND", @@ -214,14 +214,14 @@ "max_trading_pairs_OFFSET": 2, //"DEFAULT_initial_cost_OFFSETPERCENT": 20, //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 20, - "DEFAULT_trailing_buy_OFFSETPERCENT": -10, + "DEFAULT_trailing_buy_OFFSETPERCENT": -10, "DEFAULT_A_sell_value_OFFSETPERCENT": 20 }, "DCAProperties": { "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -20, "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 20, }, - "IndicatorsProperties": { + "IndicatorsProperties": { } }, // ----------------------------- @@ -241,9 +241,9 @@ // ================================ COIN-SPECIFIC SETTINGS ================================ // "SingleMarketSettings": [ // Single market/pair settings for Profit Trailer properties - // Any setting from https://wiki.profittrailer.com/doku.php?id=pairs.properties - // marked as CS (coin-specific) can be used here. - // Only coins that meet the triggered conditions will have the settings applied. + // Any setting from https://wiki.profittrailer.com/en/config + // marked as CS (coin-specific) can be used here. + // Only coins that meet the triggered conditions will have the settings applied. { "SettingName": "BlacklistCoins", "StopProcessWhenTriggered": true, @@ -253,12 +253,12 @@ } ], "PairsProperties": { - "DEFAULT_trading_enabled": false, - "DEFAULT_sell_only_mode_enabled": true, - "DEFAULT_DCA_enabled": false + "DEFAULT_trading_enabled": "false", + "DEFAULT_sell_only_mode_enabled": "true", + "DEFAULT_DCA_enabled": "false" } }, - // ----------------------------- + // ----------------------------- { "SettingName": "PumpNDumpProtection", "TriggerConnection": "OR", @@ -266,8 +266,8 @@ { "MarketTrendName": "1h", "MarketTrendRelation": "Relative", // The relation of the single market trend. Relative = Single market - // trend compared relative to the market trend - // Absolute = Single market trend viewed on its own + // trend compared relative to the market trend + // Absolute = Single market trend viewed on its own "MinChange": 8 }, { @@ -281,18 +281,18 @@ "MinChange": 12 } ], - "OffTriggers": [ - { - "HoursSinceTriggered": 3 // Any coin that triggers this setting, will remain under this setting - // for 3 hours, since the last time it triggered. + "OffTriggers": [ + { + "HoursSinceTriggered": 3 // Any coin that triggers this setting, will remain under this setting + // for 3 hours, since the last time it triggered. } ], "PairsProperties": { - "DEFAULT_sell_only_mode_enabled": true, - "DEFAULT_DCA_enabled": false + "DEFAULT_sell_only_mode_enabled": "true", + "DEFAULT_DCA_enabled": "false" } }, - // ----------------------------- + // ----------------------------- { "SettingName": "FreefallBlock", "TriggerConnection": "OR", @@ -303,14 +303,14 @@ "MaxChange": -5 } ], - "OffTriggers": [ - { + "OffTriggers": [ + { "HoursSinceTriggered": 1 } ], - "PairsProperties": { - "DEFAULT_sell_only_mode_enabled": true, - "DEFAULT_DCA_enabled": false + "PairsProperties": { + "DEFAULT_sell_only_mode_enabled": "true", + "DEFAULT_DCA_enabled": "false" } } ] diff --git a/_Development/DevSettings/settings.analyzer.json b/_Development/DevSettings/settings.analyzer.json index baf14ff..d1b0744 100644 --- a/_Development/DevSettings/settings.analyzer.json +++ b/_Development/DevSettings/settings.analyzer.json @@ -84,7 +84,7 @@ "PairsProperties": { // Properties for PAIRS.PROPERTIES // Any valid setting from https://wiki.profittrailer.com/en/config can be used here. // You can use a specific value, or apply a discrete OFFSET or OFFSETPERCENT to the value in your default PAIRS setting. - "DEFAULT_sell_only_mode_enabled": true, + "DEFAULT_sell_only_mode_enabled": "true", "DEFAULT_trailing_profit_OFFSETPERCENT": -50 }, "DCAProperties": { // Properties for DCA.PROPERTIES @@ -112,16 +112,16 @@ ], "PairsProperties": { "max_trading_pairs_OFFSET": -2, - "DEFAULT_min_buy_volume_OFFSETPERCENT": 100, - //"DEFAULT_initial_cost_OFFSETPERCENT": -50, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -50, + "DEFAULT_min_buy_volume_OFFSETPERCENT": 100, + //"DEFAULT_initial_cost_OFFSETPERCENT": -50, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -50, "DEFAULT_trailing_buy_OFFSETPERCENT": 25, "DEFAULT_trailing_profit_OFFSETPERCENT": -25 }, "DCAProperties": { //"DEFAULT_DCA_rebuy_timeout_OFFSETPERCENT": 100, "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 25, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50 + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50 }, "IndicatorsProperties": { } @@ -147,14 +147,14 @@ ], "PairsProperties": { "max_trading_pairs_OFFSET": -1, - //"DEFAULT_initial_cost_OFFSETPERCENT": -25, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -25, + //"DEFAULT_initial_cost_OFFSETPERCENT": -25, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -25, "DEFAULT_trailing_buy_OFFSETPERCENT": 10, "DEFAULT_trailing_profit_OFFSETPERCENT": -10 }, "DCAProperties": { "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 10, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10, + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10, }, "IndicatorsProperties": { } @@ -180,14 +180,14 @@ ], "PairsProperties": { "max_trading_pairs_OFFSET": 1, - //"DEFAULT_initial_cost_OFFSETPERCENT": 10, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 10, - "DEFAULT_trailing_buy_OFFSETPERCENT": -10, + //"DEFAULT_initial_cost_OFFSETPERCENT": 10, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 10, + "DEFAULT_trailing_buy_OFFSETPERCENT": -10, "DEFAULT_A_sell_value_OFFSETPERCENT": 10 }, "DCAProperties": { "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -10, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 10, + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 10, }, "IndicatorsProperties": { } @@ -212,14 +212,14 @@ ], "PairsProperties": { "max_trading_pairs_OFFSET": 2, - //"DEFAULT_initial_cost_OFFSETPERCENT": 20, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 20, - "DEFAULT_trailing_buy_OFFSETPERCENT": -10, + //"DEFAULT_initial_cost_OFFSETPERCENT": 20, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 20, + "DEFAULT_trailing_buy_OFFSETPERCENT": -10, "DEFAULT_A_sell_value_OFFSETPERCENT": 20 }, "DCAProperties": { "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -20, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 20, + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 20, }, "IndicatorsProperties": { } @@ -253,9 +253,9 @@ } ], "PairsProperties": { - "DEFAULT_trading_enabled": false, - "DEFAULT_sell_only_mode_enabled": true, - "DEFAULT_DCA_enabled": false + "DEFAULT_trading_enabled": "false", + "DEFAULT_sell_only_mode_enabled": "true", + "DEFAULT_DCA_enabled": "false" } }, // ----------------------------- @@ -267,7 +267,7 @@ "MarketTrendName": "1h", "MarketTrendRelation": "Relative", // The relation of the single market trend. Relative = Single market // trend compared relative to the market trend - // Absolute = Single market trend viewed on its own + // Absolute = Single market trend viewed on its own "MinChange": 8 }, { @@ -284,12 +284,12 @@ "OffTriggers": [ { "HoursSinceTriggered": 3 // Any coin that triggers this setting, will remain under this setting - // for 3 hours, since the last time it triggered. + // for 3 hours, since the last time it triggered. } ], "PairsProperties": { - "DEFAULT_sell_only_mode_enabled": true, - "DEFAULT_DCA_enabled": false + "DEFAULT_sell_only_mode_enabled": "true", + "DEFAULT_DCA_enabled": "false" } }, // ----------------------------- @@ -309,8 +309,8 @@ } ], "PairsProperties": { - "DEFAULT_sell_only_mode_enabled": true, - "DEFAULT_DCA_enabled": false + "DEFAULT_sell_only_mode_enabled": "true", + "DEFAULT_DCA_enabled": "false" } } ] From c02b16b948e71d629ac07f59c8e9d4fa46624925 Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Wed, 21 Apr 2021 15:33:07 +0900 Subject: [PATCH 05/17] Settings GUI changes --- Core/Main/PTMagic.cs | 19 +++++++------ Monitor/Pages/SettingsGeneral.cshtml | 37 ++++++++++++------------- Monitor/Pages/SettingsGeneral.cshtml.cs | 10 +++---- PTMagic/Program.cs | 2 +- 4 files changed, 35 insertions(+), 33 deletions(-) diff --git a/Core/Main/PTMagic.cs b/Core/Main/PTMagic.cs index 7001425..29b198d 100644 --- a/Core/Main/PTMagic.cs +++ b/Core/Main/PTMagic.cs @@ -701,13 +701,13 @@ namespace Core.Main // Check if the program is enabled if (this.PTMagicConfiguration.GeneralSettings.Application.IsEnabled) { + result = RunProfitTrailerSettingsAPIChecks(); try { if (this.PTMagicConfiguration.GeneralSettings.Application.TestMode) { - this.Log.DoLogInfo("TESTMODE ENABLED - No files will be changed!"); + this.Log.DoLogWarn("TESTMODE ENABLED - No PT settings will be changed!"); } - result = RunProfitTrailerSettingsAPIChecks(); // Check for CoinMarketCap API Key if (!String.IsNullOrEmpty(this.PTMagicConfiguration.GeneralSettings.Application.CoinMarketCapAPIKey)) @@ -731,7 +731,7 @@ namespace Core.Main } catch (System.NullReferenceException) { - this.Log.DoLogError("PTM failed to read the Config File. That means something in the File is either missing or incorrect. If this happend after an update please take a look at the release notes at: https://github.com/PTMagicians/PTMagic/releases"); + this.Log.DoLogError("PTM failed to read the General Settings file. That means something in the file is either missing or incorrect. If this happend after an update please take a look at the release notes at: https://github.com/PTMagicians/PTMagic/releases"); Console.WriteLine("Press enter to close the Application..."); Console.ReadLine(); Environment.Exit(0); @@ -739,7 +739,7 @@ namespace Core.Main } else { - this.Log.DoLogWarn("PTMagic disabled, shutting down..."); + this.Log.DoLogWarn("PTMagic is disabled. The scheduled raid was skipped."); result = false; } @@ -952,7 +952,7 @@ namespace Core.Main this.Log.DoLogInfo("+ Active setting: " + this.LastRuntimeSummary.CurrentGlobalSetting.SettingName); this.Log.DoLogInfo("+ Global setting changed: " + ((this.LastRuntimeSummary.LastGlobalSettingSwitch == this.LastRuntimeSummary.LastRuntime) ? "Yes" : "No") + " " + ((this.LastRuntimeSummary.FloodProtectedSetting != null) ? "(Flood protection!)" : "")); this.Log.DoLogInfo("+ Single Market Settings changed: " + (this.SingleMarketSettingChanged ? "Yes" : "No")); - this.Log.DoLogInfo("+ PT Config updated: " + (((this.GlobalSettingWritten || this.SingleMarketSettingChanged) && !this.PTMagicConfiguration.GeneralSettings.Application.TestMode) ? "Yes" : "No")); + this.Log.DoLogInfo("+ PT Config updated: " + (((this.GlobalSettingWritten || this.SingleMarketSettingChanged) && !this.PTMagicConfiguration.GeneralSettings.Application.TestMode) ? "Yes" : "No") + ((this.PTMagicConfiguration.GeneralSettings.Application.TestMode) ? " - TESTMODE active" : "")); this.Log.DoLogInfo("+ Markets with active single market settings: " + this.TriggeredSingleMarketSettings.Count.ToString()); foreach (string activeSMS in this.SingleMarketSettingsCount.Keys) { @@ -969,7 +969,7 @@ namespace Core.Main else { this.State = Constants.PTMagicBotState_Idle; - Log.DoLogWarn("PTMagic disabled, shutting down until next raid..."); + Log.DoLogWarn("PTMagic is disabled. The scheduled raid was skipped."); } } catch (Exception ex) @@ -2194,9 +2194,12 @@ namespace Core.Main if (!this.PTMagicConfiguration.GeneralSettings.Application.TestMode) { SettingsAPI.SendPropertyLinesToAPI(this.PairsLines, this.DCALines, this.IndicatorsLines, this.PTMagicConfiguration, this.Log); + this.Log.DoLogInfo("Settings updates sent to PT!"); + } + else + { + this.Log.DoLogWarn("TESTMODE enabled -- no updates sent to PT!"); } - - this.Log.DoLogInfo("Properties saved!"); } else { diff --git a/Monitor/Pages/SettingsGeneral.cshtml b/Monitor/Pages/SettingsGeneral.cshtml index bd8a46a..20f0d27 100644 --- a/Monitor/Pages/SettingsGeneral.cshtml +++ b/Monitor/Pages/SettingsGeneral.cshtml @@ -48,24 +48,30 @@
- +
- +
- -
- @Model.PTMagicConfiguration.GeneralSettings.Application.Exchange -
+ +
+ +
@@ -77,16 +83,16 @@
- +
- @Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL +
- @Model.PTMagicConfiguration.GetProfitTrailerServerAPITokenMasked() +
@@ -170,23 +176,16 @@
- +
- +
- @Model.PTMagicConfiguration.GeneralSettings.Monitor.Port -
-
- -
- -
- @Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl +
diff --git a/Monitor/Pages/SettingsGeneral.cshtml.cs b/Monitor/Pages/SettingsGeneral.cshtml.cs index 5a031e3..d5f3c1e 100644 --- a/Monitor/Pages/SettingsGeneral.cshtml.cs +++ b/Monitor/Pages/SettingsGeneral.cshtml.cs @@ -70,19 +70,19 @@ namespace Monitor.Pages PTMagicConfiguration.GeneralSettings.Application.TestMode = HttpContext.Request.Form["Application_TestMode"].Equals("on"); PTMagicConfiguration.GeneralSettings.Application.StartBalance = SystemHelper.TextToDouble(HttpContext.Request.Form["Application_StartBalance"], PTMagicConfiguration.GeneralSettings.Application.StartBalance, "en-US"); PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName = HttpContext.Request.Form["Application_ProfitTrailerDefaultSettingName"]; - + PTMagicConfiguration.GeneralSettings.Application.Exchange = HttpContext.Request.Form["Application_Exchange"]; + PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL = HttpContext.Request.Form["Application_ProfitTrailerMonitorURL"]; + PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerServerAPIToken = HttpContext.Request.Form["Application_ProfitTrailerServerAPIToken"]; PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset = HttpContext.Request.Form["Application_TimezoneOffset"]; PTMagicConfiguration.GeneralSettings.Application.MainFiatCurrency = HttpContext.Request.Form["Application_MainFiatCurrency"]; - - PTMagicConfiguration.GeneralSettings.Application.FloodProtectionMinutes = SystemHelper.TextToInteger(HttpContext.Request.Form["Application_FloodProtectionMinutes"], PTMagicConfiguration.GeneralSettings.Application.FloodProtectionMinutes); PTMagicConfiguration.GeneralSettings.Application.InstanceName = HttpContext.Request.Form["Application_InstanceName"]; PTMagicConfiguration.GeneralSettings.Application.CoinMarketCapAPIKey = HttpContext.Request.Form["Application_CoinMarketCapAPIKey"]; PTMagicConfiguration.GeneralSettings.Application.FreeCurrencyConverterAPIKey = HttpContext.Request.Form["Application_FreeCurrencyConverterAPIKey"]; - PTMagicConfiguration.GeneralSettings.Monitor.IsPasswordProtected = HttpContext.Request.Form["Monitor_IsPasswordProtected"].Equals("on"); PTMagicConfiguration.GeneralSettings.Monitor.OpenBrowserOnStart = HttpContext.Request.Form["Monitor_OpenBrowserOnStart"].Equals("on"); - PTMagicConfiguration.GeneralSettings.Monitor.DefaultDCAMode = HttpContext.Request.Form["Monitor_AnalyzerChart"]; + PTMagicConfiguration.GeneralSettings.Monitor.AnalyzerChart = HttpContext.Request.Form["Monitor_AnalyzerChart"]; + PTMagicConfiguration.GeneralSettings.Monitor.Port = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_Port"], PTMagicConfiguration.GeneralSettings.Monitor.Port); PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_GraphIntervalMinutes"], PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes); PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_GraphMaxTimeframeHours"], PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours); PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_RefreshSeconds"], PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds); diff --git a/PTMagic/Program.cs b/PTMagic/Program.cs index 73e595d..7e510b4 100644 --- a/PTMagic/Program.cs +++ b/PTMagic/Program.cs @@ -6,7 +6,7 @@ using Core.Helper; using Microsoft.Extensions.DependencyInjection; -[assembly: AssemblyVersion("2.5.10")] +[assembly: AssemblyVersion("2.5.11")] [assembly: AssemblyProduct("PT Magic")] namespace PTMagic From 382df91de30c417f17a1bb442aad25f8eeb70d42 Mon Sep 17 00:00:00 2001 From: HojouFotytu Date: Wed, 21 Apr 2021 16:27:06 +0900 Subject: [PATCH 06/17] Undo settings.analyzer.json --- .../settings.analyzer.json | 318 ------------------ 1 file changed, 318 deletions(-) delete mode 100644 PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json diff --git a/PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json b/PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json deleted file mode 100644 index d1b0744..0000000 --- a/PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json +++ /dev/null @@ -1,318 +0,0 @@ -// -// The settings below offer a basic example of some of the options available when using PTMagic. -// You should take your time and adjust these settings according to your own personal preferences. -// Always test your PTMagic settings by running a Profit Trailer bot in TESTMODE, to make sure -// it is performing as you expect. -// -// For more information on these settings, see the wiki at: https://github.com/PTMagicians/PTMagic/wiki/settings.analyzer - - -{ - "AnalyzerSettings": { - "MarketAnalyzer": { - "StoreDataMaxHours": 48, // Number of hours to store market data - "IntervalMinutes": 2, // Interval in minutes for PTMagic to check market trends and triggers - "ExcludeMainCurrency": true, // Excludes the main currency (for example BTC) from market trend analysis - "MarketTrends": [ - { - "Name": "1h", // UNIQUE market trend name (to be referenced by your triggers below) - "Platform": "Exchange", // Platform to grab prices from (Allowed values are: CoinMarketCap, Exchange) - "MaxMarkets": 50, // Number of markets/pairs to analyze sorted by 24h volume - "TrendMinutes": 60, // Number of minutes to build a trend (1440 = 24h, 720 = 12h, 60 = 1h) - "TrendCurrency": "Market", // Trend Currency to build the trend against. If set to "Fiat", the trend will - // take the USD value of your main currency into account to build the trend. - // "Market" will build a trend against your base currency, such as BTC or USDT. - "TrendThreshold": 15, // Any coin that is above 15% or below -15% for this timeframe will not be used when calculating the market average. - "DisplayGraph": false, // Use this trend in the graph on the PTM Monitor dashboard and market analyzer - "DisplayOnMarketAnalyzerList": false // Disply this trend for all coins on the PTM Monitor market analyzer - }, - { - "Name": "6h", - "Platform": "Exchange", - "MaxMarkets": 50, - "TrendMinutes": 360, - "TrendCurrency": "Market", - "TrendThreshold": 30, - "DisplayGraph": true, - "DisplayOnMarketAnalyzerList": true - }, - { - "Name": "12h", - "Platform": "Exchange", - "MaxMarkets": 50, - "TrendMinutes": 720, - "TrendCurrency": "Market", - "TrendThreshold": 50, - "DisplayGraph": true, - "DisplayOnMarketAnalyzerList": true - }, - { - "Name": "24h", - "Platform": "Exchange", - "MaxMarkets": 50, - "TrendMinutes": 1440, - "TrendCurrency": "Market", - "TrendThreshold": 75, - "DisplayGraph": true, - "DisplayOnMarketAnalyzerList": true - } - ] - }, - // ================================ GLOBAL SETTINGS ================================ - // - "GlobalSettings": [ // Global settings for Profit Trailer properties - // - // =================================================================================== - // ----------------------------- - { - "SettingName": "EndOfTheWorld", // ANY UNIQUE name of your setting - "TriggerConnection": "AND", // Define if triggers will be connected by AND or OR - "Triggers": [ // Your triggers for this setting. You can use any of your defined trends from above - { - "MarketTrendName": "1h", // Reference to the market trend specified above - "MaxChange": 0 // The maximum value for this trigger to be true. (Any value below "0" will trigger this) - }, - { - "MarketTrendName": "12h", - "MaxChange": -2 - }, - { - "MarketTrendName": "24h", - "MaxChange": -5 - } - ], - "PairsProperties": { // Properties for PAIRS.PROPERTIES - // Any valid setting from https://wiki.profittrailer.com/en/config can be used here. - // You can use a specific value, or apply a discrete OFFSET or OFFSETPERCENT to the value in your default PAIRS setting. - "DEFAULT_sell_only_mode_enabled": "true", - "DEFAULT_trailing_profit_OFFSETPERCENT": -50 - }, - "DCAProperties": { // Properties for DCA.PROPERTIES - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -75 - } - }, - // ----------------------------- - { - "SettingName": "TankingDown", - "TriggerConnection": "AND", - "Triggers": [ - { - "MarketTrendName": "1h", - "MaxChange": 0 - }, - { - "MarketTrendName": "12h", - "MaxChange": 0 - }, - { - "MarketTrendName": "24h", // Any value between -5 and -3 will make this trigger true. - "MaxChange": -3, - "MinChange": -5 // The minimum value for this trigger to be true. (Any value above "-5" will trigger this) - } - ], - "PairsProperties": { - "max_trading_pairs_OFFSET": -2, - "DEFAULT_min_buy_volume_OFFSETPERCENT": 100, - //"DEFAULT_initial_cost_OFFSETPERCENT": -50, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -50, - "DEFAULT_trailing_buy_OFFSETPERCENT": 25, - "DEFAULT_trailing_profit_OFFSETPERCENT": -25 - }, - "DCAProperties": { - //"DEFAULT_DCA_rebuy_timeout_OFFSETPERCENT": 100, - "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 25, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50 - }, - "IndicatorsProperties": { - } - }, - // ----------------------------- - { - "SettingName": "BearSighted", - "TriggerConnection": "AND", - "Triggers": [ - { - "MarketTrendName": "1h", - "MaxChange": 1 - }, - { - "MarketTrendName": "12h", - "MaxChange": 0 - }, - { - "MarketTrendName": "24h", - "MaxChange": -1, - "MinChange": -3 - } - ], - "PairsProperties": { - "max_trading_pairs_OFFSET": -1, - //"DEFAULT_initial_cost_OFFSETPERCENT": -25, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -25, - "DEFAULT_trailing_buy_OFFSETPERCENT": 10, - "DEFAULT_trailing_profit_OFFSETPERCENT": -10 - }, - "DCAProperties": { - "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 10, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10, - }, - "IndicatorsProperties": { - } - }, - // ----------------------------- - { - "SettingName": "ReadyForLiftOff", - "TriggerConnection": "AND", - "Triggers": [ - { - "MarketTrendName": "1h", - "MinChange": 0 - }, - { - "MarketTrendName": "12h", - "MinChange": 0 - }, - { - "MarketTrendName": "24h", - "MinChange": 1, - "MaxChange": 3 - } - ], - "PairsProperties": { - "max_trading_pairs_OFFSET": 1, - //"DEFAULT_initial_cost_OFFSETPERCENT": 10, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 10, - "DEFAULT_trailing_buy_OFFSETPERCENT": -10, - "DEFAULT_A_sell_value_OFFSETPERCENT": 10 - }, - "DCAProperties": { - "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -10, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 10, - }, - "IndicatorsProperties": { - } - }, - // ----------------------------- - { - "SettingName": "ToTheMoon", - "TriggerConnection": "AND", - "Triggers": [ - { - "MarketTrendName": "1h", - "MinChange": 1 - }, - { - "MarketTrendName": "12h", - "MinChange": 1 - }, - { - "MarketTrendName": "24h", - "MinChange": 3 - } - ], - "PairsProperties": { - "max_trading_pairs_OFFSET": 2, - //"DEFAULT_initial_cost_OFFSETPERCENT": 20, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 20, - "DEFAULT_trailing_buy_OFFSETPERCENT": -10, - "DEFAULT_A_sell_value_OFFSETPERCENT": 20 - }, - "DCAProperties": { - "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -20, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 20, - }, - "IndicatorsProperties": { - } - }, - // ----------------------------- - { - "SettingName": "Default", - "PairsProperties": { - "File": "PAIRS.properties" - }, - "DCAProperties": { - "File": "DCA.properties" - }, - "IndicatorsProperties": { - "File": "INDICATORS.properties" - } - } - ], - // ================================ COIN-SPECIFIC SETTINGS ================================ - // - "SingleMarketSettings": [ // Single market/pair settings for Profit Trailer properties - // Any setting from https://wiki.profittrailer.com/en/config - // marked as CS (coin-specific) can be used here. - // Only coins that meet the triggered conditions will have the settings applied. - { - "SettingName": "BlacklistCoins", - "StopProcessWhenTriggered": true, - "Triggers": [ - { - "AgeDaysLowerThan": 21 - } - ], - "PairsProperties": { - "DEFAULT_trading_enabled": "false", - "DEFAULT_sell_only_mode_enabled": "true", - "DEFAULT_DCA_enabled": "false" - } - }, - // ----------------------------- - { - "SettingName": "PumpNDumpProtection", - "TriggerConnection": "OR", - "Triggers": [ - { - "MarketTrendName": "1h", - "MarketTrendRelation": "Relative", // The relation of the single market trend. Relative = Single market - // trend compared relative to the market trend - // Absolute = Single market trend viewed on its own - "MinChange": 8 - }, - { - "MarketTrendName": "12h", - "MarketTrendRelation": "Relative", - "MinChange": 10 - }, - { - "MarketTrendName": "24h", - "MarketTrendRelation": "Relative", - "MinChange": 12 - } - ], - "OffTriggers": [ - { - "HoursSinceTriggered": 3 // Any coin that triggers this setting, will remain under this setting - // for 3 hours, since the last time it triggered. - } - ], - "PairsProperties": { - "DEFAULT_sell_only_mode_enabled": "true", - "DEFAULT_DCA_enabled": "false" - } - }, - // ----------------------------- - { - "SettingName": "FreefallBlock", - "TriggerConnection": "OR", - "Triggers": [ - { - "MarketTrendName": "1h", - "MarketTrendRelation": "Absolute", - "MaxChange": -5 - } - ], - "OffTriggers": [ - { - "HoursSinceTriggered": 1 - } - ], - "PairsProperties": { - "DEFAULT_sell_only_mode_enabled": "true", - "DEFAULT_DCA_enabled": "false" - } - } - ] - } -} \ No newline at end of file From e4e5d924449ae36cd8299a5f28276322b8c224bd Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Wed, 21 Apr 2021 17:14:21 +0900 Subject: [PATCH 07/17] Default settings.analyzer --- .../settings.analyzer.json | 298 ++++++++++++++++++ .../DevSettings/settings.analyzer.json | 138 ++++---- 2 files changed, 357 insertions(+), 79 deletions(-) create mode 100644 PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json diff --git a/PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json b/PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json new file mode 100644 index 0000000..dcbd5bf --- /dev/null +++ b/PTMagic/_defaults/_default_settings_PT_2.x/settings.analyzer.json @@ -0,0 +1,298 @@ +// +// The settings below offer a basic example of some of the options available when using PTMagic. +// You should take your time and adjust these settings according to your own personal preferences, and settings. +// +// Always test your PTMagic settings by running a Profit Trailer bot in TESTMODE, to make sure +// it is performing as you expect. +// +// For more information on these settings, see the wiki at: https://github.com/PTMagicians/PTMagic/wiki/settings.analyzer + + +{ + "AnalyzerSettings": { + "MarketAnalyzer": { + "StoreDataMaxHours": 48, // Number of hours to store market data + "IntervalMinutes": 2, // Interval in minutes for PTMagic to check market trends and triggers + "ExcludeMainCurrency": true, // Excludes the main currency (for example BTC) from market trend analysis + "MarketTrends": [ + { + "Name": "1h", // UNIQUE market trend name (to be referenced by your triggers below) + "Platform": "Exchange", // Platform to grab prices from (Allowed values are: CoinMarketCap, Exchange) + "MaxMarkets": 50, // Number of markets/pairs to analyze sorted by 24h volume + "TrendMinutes": 60, // Number of minutes to build a trend (1440 = 24h, 720 = 12h, 60 = 1h) + "TrendCurrency": "Market", // Trend Currency to build the trend against. If set to "Fiat", the trend will take the USD value of your main currency into account to build the trend. "Market" will build a trend against your base currency, such as BTC or USDT. + "TrendThreshold": 15, // Any coin that is above 15% or below -15% for this timeframe will not be used when calculating the market average. + "DisplayGraph": false, // Use this trend in the graph on the PTM Monitor dashboard and market analyzer? + "DisplayOnMarketAnalyzerList": false // Disply this trend on the PTM Monitor market analyzer? + }, + { + "Name": "6h", + "Platform": "Exchange", + "MaxMarkets": 50, + "TrendMinutes": 360, + "TrendCurrency": "Market", + "TrendThreshold": 30, + "DisplayGraph": true, + "DisplayOnMarketAnalyzerList": true + }, + { + "Name": "12h", + "Platform": "Exchange", + "MaxMarkets": 50, + "TrendMinutes": 720, + "TrendCurrency": "Market", + "TrendThreshold": 50, + "DisplayGraph": true, + "DisplayOnMarketAnalyzerList": true + }, + { + "Name": "24h", + "Platform": "Exchange", + "MaxMarkets": 50, + "TrendMinutes": 1440, + "TrendCurrency": "Market", + "TrendThreshold": 75, + "DisplayGraph": true, + "DisplayOnMarketAnalyzerList": true + } + ] + }, + // ================================ GLOBAL SETTINGS ================================ + // + "GlobalSettings": [ // Global settings for Profit Trailer properties + // + // =================================================================================== + // ----------------------------- + { + "SettingName": "EndOfTheWorld", // ANY UNIQUE name of your setting + "TriggerConnection": "AND", // Define if triggers will be connected by AND or OR + "Triggers": [ // Your triggers for this setting. You can use any of your defined trends from above + { + "MarketTrendName": "1h", // Reference to the market trend specified above + "MaxChange": 0 // The maximum value for this trigger to be true. (Any value below "0" will trigger this) + }, + { + "MarketTrendName": "12h", + "MaxChange": -2 + }, + { + "MarketTrendName": "24h", + "MaxChange": -5 + } + ], + "PairsProperties": { // Changes you wish to make to your PAIRS.properties settings + // Any valid setting from https://wiki.profittrailer.com/en/config can be used here. + // You can use a specific value, or apply a discrete OFFSET or OFFSETPERCENT to the value in your default PAIRS setting. + "DEFAULT_sell_only_mode_enabled": true, + "DEFAULT_trailing_profit_OFFSETPERCENT": -50 + }, + "DCAProperties": { // Changes you wish to make to your DCA.properties settings + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -75 + }, + "IndicatorsProperties": { // Changes you wish to make to your INDICATORS.properties settings + } + }, + // ----------------------------- + { + "SettingName": "TankingDown", + "TriggerConnection": "AND", + "Triggers": [ + { + "MarketTrendName": "1h", + "MaxChange": 0 + } + ], + "PairsProperties": { + "max_trading_pairs_OFFSET": -2, + "DEFAULT_min_buy_volume_OFFSETPERCENT": 100, + //"DEFAULT_initial_cost_OFFSETPERCENT": -50, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -50, + "DEFAULT_trailing_buy_OFFSETPERCENT": 25, + "DEFAULT_trailing_profit_OFFSETPERCENT": -25 + }, + "DCAProperties": { + //"DEFAULT_DCA_rebuy_timeout_OFFSETPERCENT": 100, + "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 25, + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50 + }, + "IndicatorsProperties": { + } + }, + // ----------------------------- + { + "SettingName": "BearSighted", + "TriggerConnection": "AND", + "Triggers": [ + { + "MarketTrendName": "1h", + "MaxChange": 1 + }, + { + "MarketTrendName": "12h", + "MaxChange": 0 + }, + { + "MarketTrendName": "24h", + "MaxChange": -1, + "MinChange": -3 + } + ], + "PairsProperties": { + "max_trading_pairs_OFFSET": -1, + //"DEFAULT_initial_cost_OFFSETPERCENT": -25, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -25, + "DEFAULT_trailing_buy_OFFSETPERCENT": 10, + "DEFAULT_trailing_profit_OFFSETPERCENT": -10 + }, + "DCAProperties": { + "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 10, + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10, + }, + "IndicatorsProperties": { + } + }, + // ----------------------------- + { + "SettingName": "ReadyForLiftOff", + "TriggerConnection": "AND", + "Triggers": [ + { + "MarketTrendName": "1h", + "MinChange": 0 + }, + { + "MarketTrendName": "12h", + "MinChange": 0 + }, + { + "MarketTrendName": "24h", + "MinChange": 1, + "MaxChange": 3 + } + ], + "PairsProperties": { + "max_trading_pairs_OFFSET": 1, + //"DEFAULT_initial_cost_OFFSETPERCENT": 10, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 10, + "DEFAULT_trailing_buy_OFFSETPERCENT": -10, + "DEFAULT_A_sell_value_OFFSETPERCENT": 10 + }, + "DCAProperties": { + "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -10, + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 10, + }, + "IndicatorsProperties": { + } + }, + // ----------------------------- + { + "SettingName": "ToTheMoon", + "TriggerConnection": "AND", + "Triggers": [ + { + "MarketTrendName": "1h", + "MinChange": 1 + }, + { + "MarketTrendName": "12h", + "MinChange": 1 + }, + { + "MarketTrendName": "24h", + "MinChange": 3 + } + ], + "PairsProperties": { + "max_trading_pairs_OFFSET": 2, + //"DEFAULT_initial_cost_OFFSETPERCENT": 20, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 20, + "DEFAULT_trailing_buy_OFFSETPERCENT": -10, + "DEFAULT_A_sell_value_OFFSETPERCENT": 20 + }, + "DCAProperties": { + "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -20, + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 20, + }, + "IndicatorsProperties": { + } + }, + // ----------------------------- + { + "SettingName": "Default", + "PairsProperties": { + "File": "PAIRS.properties" + }, + "DCAProperties": { + "File": "DCA.properties" + }, + "IndicatorsProperties": { + "File": "INDICATORS.properties" + } + } + ], + // + // ================================ COIN-SPECIFIC SETTINGS ================================ + // + "SingleMarketSettings": [ // Single market/pair settings for Profit Trailer properties + // Any setting from https://wiki.profittrailer.com/en/config marked as COIN (coin-specific) can be used here. + // Only coins that meet the triggered conditions will have the settings applied. + // A variety of SMS can be employed to check for long-term down trends, sideways trends, over-extended uptrends, etc. + // If more than one SMS is true, the settings of the last applied SMS over-rides any prior SMS + { + "SettingName": "PumpNDumpProtection", + "TriggerConnection": "OR", + //"StopProcessWhenTriggered": true, // No SMS after this will be analyzed or applied if this SMS is true + //"AllowedGlobalSettings": "Default", // You can specify that this setting will only apply when a specific Global setting is active + //"IgnoredGlobalSettings": "Default", // You can specify that this setting will NOT apply when a specific Global setting is active + "Triggers": [ + { + "MarketTrendName": "1h", + "MarketTrendRelation": "Relative", // Relative = The single market trend is compared to the overall trend of the entire market + // Absolute = The Single market trend is considered on its own + "MinChange": 8 + }, + { + "MarketTrendName": "12h", + "MarketTrendRelation": "Relative", + "MinChange": 10 + }, + { + "MarketTrendName": "24h", + "MarketTrendRelation": "Relative", + "MinChange": 12 + } + ], + "OffTriggers": [ + { + "HoursSinceTriggered": 3 // Any coin that triggers this setting, will remain under this setting + // for 3 hours, since the last time it triggered. + } + ], + "PairsProperties": { + "DEFAULT_sell_only_mode_enabled": "true", + "DEFAULT_DCA_enabled": "false" + } + }, + { + "SettingName": "FreefallBlock", + "TriggerConnection": "OR", + "Triggers": [ + { + "MarketTrendName": "1h", + "MarketTrendRelation": "Absolute", + "MaxChange": -5 + } + ], + "OffTriggers": [ + { + "HoursSinceTriggered": 1 + } + ], + "PairsProperties": { + "DEFAULT_sell_only_mode_enabled": "true", + "DEFAULT_DCA_enabled": "false" + } + } + ] + } +} \ No newline at end of file diff --git a/_Development/DevSettings/settings.analyzer.json b/_Development/DevSettings/settings.analyzer.json index d1b0744..dcbd5bf 100644 --- a/_Development/DevSettings/settings.analyzer.json +++ b/_Development/DevSettings/settings.analyzer.json @@ -1,6 +1,7 @@ // // The settings below offer a basic example of some of the options available when using PTMagic. -// You should take your time and adjust these settings according to your own personal preferences. +// You should take your time and adjust these settings according to your own personal preferences, and settings. +// // Always test your PTMagic settings by running a Profit Trailer bot in TESTMODE, to make sure // it is performing as you expect. // @@ -10,21 +11,19 @@ { "AnalyzerSettings": { "MarketAnalyzer": { - "StoreDataMaxHours": 48, // Number of hours to store market data - "IntervalMinutes": 2, // Interval in minutes for PTMagic to check market trends and triggers - "ExcludeMainCurrency": true, // Excludes the main currency (for example BTC) from market trend analysis + "StoreDataMaxHours": 48, // Number of hours to store market data + "IntervalMinutes": 2, // Interval in minutes for PTMagic to check market trends and triggers + "ExcludeMainCurrency": true, // Excludes the main currency (for example BTC) from market trend analysis "MarketTrends": [ { - "Name": "1h", // UNIQUE market trend name (to be referenced by your triggers below) - "Platform": "Exchange", // Platform to grab prices from (Allowed values are: CoinMarketCap, Exchange) - "MaxMarkets": 50, // Number of markets/pairs to analyze sorted by 24h volume - "TrendMinutes": 60, // Number of minutes to build a trend (1440 = 24h, 720 = 12h, 60 = 1h) - "TrendCurrency": "Market", // Trend Currency to build the trend against. If set to "Fiat", the trend will - // take the USD value of your main currency into account to build the trend. - // "Market" will build a trend against your base currency, such as BTC or USDT. - "TrendThreshold": 15, // Any coin that is above 15% or below -15% for this timeframe will not be used when calculating the market average. - "DisplayGraph": false, // Use this trend in the graph on the PTM Monitor dashboard and market analyzer - "DisplayOnMarketAnalyzerList": false // Disply this trend for all coins on the PTM Monitor market analyzer + "Name": "1h", // UNIQUE market trend name (to be referenced by your triggers below) + "Platform": "Exchange", // Platform to grab prices from (Allowed values are: CoinMarketCap, Exchange) + "MaxMarkets": 50, // Number of markets/pairs to analyze sorted by 24h volume + "TrendMinutes": 60, // Number of minutes to build a trend (1440 = 24h, 720 = 12h, 60 = 1h) + "TrendCurrency": "Market", // Trend Currency to build the trend against. If set to "Fiat", the trend will take the USD value of your main currency into account to build the trend. "Market" will build a trend against your base currency, such as BTC or USDT. + "TrendThreshold": 15, // Any coin that is above 15% or below -15% for this timeframe will not be used when calculating the market average. + "DisplayGraph": false, // Use this trend in the graph on the PTM Monitor dashboard and market analyzer? + "DisplayOnMarketAnalyzerList": false // Disply this trend on the PTM Monitor market analyzer? }, { "Name": "6h", @@ -65,12 +64,12 @@ // =================================================================================== // ----------------------------- { - "SettingName": "EndOfTheWorld", // ANY UNIQUE name of your setting - "TriggerConnection": "AND", // Define if triggers will be connected by AND or OR - "Triggers": [ // Your triggers for this setting. You can use any of your defined trends from above + "SettingName": "EndOfTheWorld", // ANY UNIQUE name of your setting + "TriggerConnection": "AND", // Define if triggers will be connected by AND or OR + "Triggers": [ // Your triggers for this setting. You can use any of your defined trends from above { - "MarketTrendName": "1h", // Reference to the market trend specified above - "MaxChange": 0 // The maximum value for this trigger to be true. (Any value below "0" will trigger this) + "MarketTrendName": "1h", // Reference to the market trend specified above + "MaxChange": 0 // The maximum value for this trigger to be true. (Any value below "0" will trigger this) }, { "MarketTrendName": "12h", @@ -81,14 +80,16 @@ "MaxChange": -5 } ], - "PairsProperties": { // Properties for PAIRS.PROPERTIES - // Any valid setting from https://wiki.profittrailer.com/en/config can be used here. - // You can use a specific value, or apply a discrete OFFSET or OFFSETPERCENT to the value in your default PAIRS setting. - "DEFAULT_sell_only_mode_enabled": "true", + "PairsProperties": { // Changes you wish to make to your PAIRS.properties settings + // Any valid setting from https://wiki.profittrailer.com/en/config can be used here. + // You can use a specific value, or apply a discrete OFFSET or OFFSETPERCENT to the value in your default PAIRS setting. + "DEFAULT_sell_only_mode_enabled": true, "DEFAULT_trailing_profit_OFFSETPERCENT": -50 }, - "DCAProperties": { // Properties for DCA.PROPERTIES + "DCAProperties": { // Changes you wish to make to your DCA.properties settings "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -75 + }, + "IndicatorsProperties": { // Changes you wish to make to your INDICATORS.properties settings } }, // ----------------------------- @@ -99,29 +100,20 @@ { "MarketTrendName": "1h", "MaxChange": 0 - }, - { - "MarketTrendName": "12h", - "MaxChange": 0 - }, - { - "MarketTrendName": "24h", // Any value between -5 and -3 will make this trigger true. - "MaxChange": -3, - "MinChange": -5 // The minimum value for this trigger to be true. (Any value above "-5" will trigger this) } ], "PairsProperties": { - "max_trading_pairs_OFFSET": -2, - "DEFAULT_min_buy_volume_OFFSETPERCENT": 100, - //"DEFAULT_initial_cost_OFFSETPERCENT": -50, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -50, - "DEFAULT_trailing_buy_OFFSETPERCENT": 25, - "DEFAULT_trailing_profit_OFFSETPERCENT": -25 + "max_trading_pairs_OFFSET": -2, + "DEFAULT_min_buy_volume_OFFSETPERCENT": 100, + //"DEFAULT_initial_cost_OFFSETPERCENT": -50, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -50, + "DEFAULT_trailing_buy_OFFSETPERCENT": 25, + "DEFAULT_trailing_profit_OFFSETPERCENT": -25 }, "DCAProperties": { //"DEFAULT_DCA_rebuy_timeout_OFFSETPERCENT": 100, "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 25, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50 + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50 }, "IndicatorsProperties": { } @@ -147,14 +139,14 @@ ], "PairsProperties": { "max_trading_pairs_OFFSET": -1, - //"DEFAULT_initial_cost_OFFSETPERCENT": -25, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -25, - "DEFAULT_trailing_buy_OFFSETPERCENT": 10, - "DEFAULT_trailing_profit_OFFSETPERCENT": -10 + //"DEFAULT_initial_cost_OFFSETPERCENT": -25, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -25, + "DEFAULT_trailing_buy_OFFSETPERCENT": 10, + "DEFAULT_trailing_profit_OFFSETPERCENT": -10 }, "DCAProperties": { "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 10, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10, + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10, }, "IndicatorsProperties": { } @@ -180,14 +172,14 @@ ], "PairsProperties": { "max_trading_pairs_OFFSET": 1, - //"DEFAULT_initial_cost_OFFSETPERCENT": 10, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 10, - "DEFAULT_trailing_buy_OFFSETPERCENT": -10, - "DEFAULT_A_sell_value_OFFSETPERCENT": 10 + //"DEFAULT_initial_cost_OFFSETPERCENT": 10, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 10, + "DEFAULT_trailing_buy_OFFSETPERCENT": -10, + "DEFAULT_A_sell_value_OFFSETPERCENT": 10 }, "DCAProperties": { - "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -10, - "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 10, + "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -10, + "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 10, }, "IndicatorsProperties": { } @@ -212,9 +204,9 @@ ], "PairsProperties": { "max_trading_pairs_OFFSET": 2, - //"DEFAULT_initial_cost_OFFSETPERCENT": 20, - //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 20, - "DEFAULT_trailing_buy_OFFSETPERCENT": -10, + //"DEFAULT_initial_cost_OFFSETPERCENT": 20, + //"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 20, + "DEFAULT_trailing_buy_OFFSETPERCENT": -10, "DEFAULT_A_sell_value_OFFSETPERCENT": 20 }, "DCAProperties": { @@ -238,36 +230,25 @@ } } ], + // // ================================ COIN-SPECIFIC SETTINGS ================================ // - "SingleMarketSettings": [ // Single market/pair settings for Profit Trailer properties - // Any setting from https://wiki.profittrailer.com/en/config - // marked as CS (coin-specific) can be used here. - // Only coins that meet the triggered conditions will have the settings applied. - { - "SettingName": "BlacklistCoins", - "StopProcessWhenTriggered": true, - "Triggers": [ - { - "AgeDaysLowerThan": 21 - } - ], - "PairsProperties": { - "DEFAULT_trading_enabled": "false", - "DEFAULT_sell_only_mode_enabled": "true", - "DEFAULT_DCA_enabled": "false" - } - }, - // ----------------------------- + "SingleMarketSettings": [ // Single market/pair settings for Profit Trailer properties + // Any setting from https://wiki.profittrailer.com/en/config marked as COIN (coin-specific) can be used here. + // Only coins that meet the triggered conditions will have the settings applied. + // A variety of SMS can be employed to check for long-term down trends, sideways trends, over-extended uptrends, etc. + // If more than one SMS is true, the settings of the last applied SMS over-rides any prior SMS { "SettingName": "PumpNDumpProtection", "TriggerConnection": "OR", + //"StopProcessWhenTriggered": true, // No SMS after this will be analyzed or applied if this SMS is true + //"AllowedGlobalSettings": "Default", // You can specify that this setting will only apply when a specific Global setting is active + //"IgnoredGlobalSettings": "Default", // You can specify that this setting will NOT apply when a specific Global setting is active "Triggers": [ { "MarketTrendName": "1h", - "MarketTrendRelation": "Relative", // The relation of the single market trend. Relative = Single market - // trend compared relative to the market trend - // Absolute = Single market trend viewed on its own + "MarketTrendRelation": "Relative", // Relative = The single market trend is compared to the overall trend of the entire market + // Absolute = The Single market trend is considered on its own "MinChange": 8 }, { @@ -283,8 +264,8 @@ ], "OffTriggers": [ { - "HoursSinceTriggered": 3 // Any coin that triggers this setting, will remain under this setting - // for 3 hours, since the last time it triggered. + "HoursSinceTriggered": 3 // Any coin that triggers this setting, will remain under this setting + // for 3 hours, since the last time it triggered. } ], "PairsProperties": { @@ -292,7 +273,6 @@ "DEFAULT_DCA_enabled": "false" } }, - // ----------------------------- { "SettingName": "FreefallBlock", "TriggerConnection": "OR", From d8b3ee612cacdd04c89a60078d47a41de89aecff Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Wed, 21 Apr 2021 19:29:42 +0900 Subject: [PATCH 08/17] Merge Target & Profit --- Monitor/Pages/SettingsGeneral.cshtml | 2 +- Monitor/Pages/_get/DashboardTop.cshtml | 68 +++++++++++--------------- 2 files changed, 29 insertions(+), 41 deletions(-) diff --git a/Monitor/Pages/SettingsGeneral.cshtml b/Monitor/Pages/SettingsGeneral.cshtml index 20f0d27..4989f93 100644 --- a/Monitor/Pages/SettingsGeneral.cshtml +++ b/Monitor/Pages/SettingsGeneral.cshtml @@ -190,7 +190,7 @@
- +
diff --git a/Monitor/Pages/_get/DashboardTop.cshtml b/Monitor/Pages/_get/DashboardTop.cshtml index 80d5569..9bdb3b4 100644 --- a/Monitor/Pages/_get/DashboardTop.cshtml +++ b/Monitor/Pages/_get/DashboardTop.cshtml @@ -98,10 +98,9 @@ 24H Cost - DCA - Sell - Target - Profit + DCA + Sell + Profit @@ -202,42 +201,32 @@ @Html.Raw(buyStrategyText) @Html.Raw(sellStrategyText) - - @if (!sellStrategyText.Contains("WATCHMODE")) - { - @if (sellStrategyText.Contains("CROSSED")) - // if leverage, recalculate profit target - { - string leverageText = sellStrategyText.Remove(0, sellStrategyText.IndexOf("CROSSED")+9); - leverage = leverageText.Remove(leverageText.IndexOf(".0)"), leverageText.Length - leverageText.IndexOf(".0)")); - leverageValue = double.Parse(leverage); - } - @if (sellStrategyText.Contains("ISOLATED")) - { - string leverageText = sellStrategyText.Remove(0, sellStrategyText.IndexOf("ISOLATED")+10); - leverage = leverageText.Remove(leverageText.IndexOf(".0)"), leverageText.Length - leverageText.IndexOf(".0)")); - leverageValue = double.Parse(leverage); - } - @if (leverageValue == 1) - { - @Html.Raw(dcaLogEntry.TargetGainValue.HasValue ? dcaLogEntry.TargetGainValue.Value.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%" : " ") - } - else - { - double TargetGain = leverageValue * dcaLogEntry.TargetGainValue.Value; - @Html.Raw(dcaLogEntry.TargetGainValue.HasValue ? TargetGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%" : " ") - } - } - else - { - - } - + @if (!@lostValue) - { - profitPercentage = profitPercentage * leverageValue; - @profitPercentage.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))% - } + { + @if (!sellStrategyText.Contains("WATCHMODE")) + { + @if (sellStrategyText.Contains("CROSSED")) + // if leverage, recalculate profit target + { + string leverageText = sellStrategyText.Remove(0, sellStrategyText.IndexOf("CROSSED")+9); + leverage = leverageText.Remove(leverageText.IndexOf(".0)"), leverageText.Length - leverageText.IndexOf(".0)")); + leverageValue = double.Parse(leverage); + } + @if (sellStrategyText.Contains("ISOLATED")) + { + string leverageText = sellStrategyText.Remove(0, sellStrategyText.IndexOf("ISOLATED")+10); + leverage = leverageText.Remove(leverageText.IndexOf(".0)"), leverageText.Length - leverageText.IndexOf(".0)")); + leverageValue = double.Parse(leverage); + } + profitPercentage = profitPercentage * leverageValue; + double TargetGain = leverageValue * dcaLogEntry.TargetGainValue.Value; + @TargetGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))% +
+
@profitPercentage.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))%
+ + } + } else { No Value! @@ -258,7 +247,6 @@ - @Html.Raw((((Model.TotalBagGain) / Model.TotalBagCost) * 100).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")))% From 8249e5e1825b474c617a396b23fea3d48a2bbed3 Mon Sep 17 00:00:00 2001 From: djbadders <34887832+djbadders@users.noreply.github.com> Date: Sun, 20 Jun 2021 11:34:37 +0100 Subject: [PATCH 09/17] Improved getting market data performance --- Core/Main/PTMagic.cs | 31 ++++++++++++++--- Core/MarketAnalyzer/BaseAnalyzer.cs | 11 +++--- Core/MarketAnalyzer/Binance.cs | 49 +++++++++++++-------------- Core/MarketAnalyzer/BinanceFutures.cs | 11 +++--- Core/MarketAnalyzer/BinanceUS.cs | 9 ++--- Core/MarketAnalyzer/Bittrex.cs | 8 ++--- Core/MarketAnalyzer/Poloniex.cs | 10 +++--- Monitor/Pages/_get/BagDetails.cshtml | 2 +- 8 files changed, 72 insertions(+), 59 deletions(-) diff --git a/Core/Main/PTMagic.cs b/Core/Main/PTMagic.cs index c585351..405f2eb 100644 --- a/Core/Main/PTMagic.cs +++ b/Core/Main/PTMagic.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Threading; using System.IO; using System.Linq; @@ -52,7 +53,7 @@ namespace Core.Main private List _indicatorsLines = null; private List _exchangeMarketList = null; private List _marketList = new List(); - private Dictionary _marketInfos = new Dictionary(); + private ConcurrentDictionary _marketInfos = new ConcurrentDictionary(); private Dictionary _averageMarketTrendChanges = new Dictionary(); private Dictionary> _singleMarketTrendChanges = new Dictionary>(); private Dictionary> _globalMarketTrendChanges = new Dictionary>(); @@ -432,7 +433,7 @@ namespace Core.Main } } - public Dictionary MarketInfos + public ConcurrentDictionary MarketInfos { get { @@ -903,6 +904,28 @@ namespace Core.Main // Check for single market trend triggers this.ApplySingleMarketSettings(); + // Ignore quarterly futures + if (this.PTMagicConfiguration.GeneralSettings.Application.Exchange.Equals("BinanceFutures", StringComparison.InvariantCultureIgnoreCase)) + { + // Find all quarterly futures pairs + var results = this.MarketList.FindAll(m => m.Contains("_", StringComparison.InvariantCultureIgnoreCase)); + + // Create the settings lines to disable trading + if (results.Count > 0) + { + this.PairsLines.AddRange(new string[] { + "", + "# Binance Futures quarterly futures ignore list", + "###############################################" + }); + + foreach (var marketPair in results) + { + this.PairsLines.Add(String.Format("{0}_trading_enabled = false", marketPair)); + } + } + } + // Save new properties to Profit Trailer this.SaveProfitTrailerProperties(); @@ -1518,7 +1541,7 @@ namespace Core.Main // Check ignore markets List ignoredMarkets = SystemHelper.ConvertTokenStringToList(marketSetting.IgnoredMarkets, ","); - if (ignoredMarkets.Contains(marketPair)) + if (ignoredMarkets.Any(im => marketPair.StartsWith(im, StringComparison.InvariantCultureIgnoreCase))) { this.Log.DoLogDebug("'" + marketPair + "' - Is ignored in '" + marketSetting.SettingName + "'."); continue; @@ -1526,7 +1549,7 @@ namespace Core.Main // Check allowed markets List allowedMarkets = SystemHelper.ConvertTokenStringToList(marketSetting.AllowedMarkets, ","); - if (allowedMarkets.Count > 0 && !allowedMarkets.Contains(marketPair)) + if (allowedMarkets.Count > 0 && !allowedMarkets.Any(am => marketPair.StartsWith(am, StringComparison.InvariantCultureIgnoreCase))) { this.Log.DoLogDebug("'" + marketPair + "' - Is not allowed in '" + marketSetting.SettingName + "'."); continue; diff --git a/Core/MarketAnalyzer/BaseAnalyzer.cs b/Core/MarketAnalyzer/BaseAnalyzer.cs index 51b2628..5c1b66e 100644 --- a/Core/MarketAnalyzer/BaseAnalyzer.cs +++ b/Core/MarketAnalyzer/BaseAnalyzer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.Concurrent; using System.IO; using System.Linq; using System.Net; @@ -153,16 +154,16 @@ namespace Core.MarketAnalyzer return result; } - public static Dictionary GetMarketInfosFromFile(PTMagicConfiguration systemConfiguration, LogHelper log) + public static ConcurrentDictionary GetMarketInfosFromFile(PTMagicConfiguration systemConfiguration, LogHelper log) { - Dictionary result = new Dictionary(); + ConcurrentDictionary result = new ConcurrentDictionary(); string marketInfoFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar + "MarketInfo.json"; if (File.Exists(marketInfoFilePath)) { try { - result = JsonConvert.DeserializeObject>(System.IO.File.ReadAllText(marketInfoFilePath)); + result = JsonConvert.DeserializeObject>(System.IO.File.ReadAllText(marketInfoFilePath)); } catch (Exception ex) { @@ -171,12 +172,12 @@ namespace Core.MarketAnalyzer } if (result == null) { - result = new Dictionary(); + result = new ConcurrentDictionary(); } return result; } - public static void SaveMarketInfosToFile(Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) + public static void SaveMarketInfosToFile(ConcurrentDictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { FileHelper.WriteTextToFile(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar, "MarketInfo.json", JsonConvert.SerializeObject(marketInfos)); } diff --git a/Core/MarketAnalyzer/Binance.cs b/Core/MarketAnalyzer/Binance.cs index 8eae0a7..f6f0bc5 100644 --- a/Core/MarketAnalyzer/Binance.cs +++ b/Core/MarketAnalyzer/Binance.cs @@ -1,17 +1,14 @@ using System; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Linq; using System.IO; -using System.Text; using Core.Main; using Core.Helper; using Core.Main.DataObjects.PTMagicData; using Newtonsoft.Json; -using Core.ProfitTrailer; using System.Net; -using System.Threading; using System.Threading.Tasks; -using System.Collections.Concurrent; namespace Core.MarketAnalyzer { @@ -43,7 +40,7 @@ namespace Core.MarketAnalyzer return result; } - public static List GetMarketData(string mainMarket, Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) + public static List GetMarketData(string mainMarket, ConcurrentDictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { List result = new List(); @@ -163,7 +160,7 @@ namespace Core.MarketAnalyzer return result; } - public static void CheckFirstSeenDates(Dictionary markets, ref Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) + public static void CheckFirstSeenDates(Dictionary markets, ref ConcurrentDictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { log.DoLogInfo("Binance - Checking first seen dates for " + markets.Count + " markets. This may take a while..."); @@ -182,7 +179,7 @@ namespace Core.MarketAnalyzer { marketInfo = new MarketInfo(); marketInfo.Name = key; - marketInfos.Add(key, marketInfo); + marketInfos.TryAdd(key, marketInfo); marketInfo.FirstSeen = Binance.GetFirstSeenDate(key, systemConfiguration, log); } else @@ -375,7 +372,7 @@ namespace Core.MarketAnalyzer } Parallel.ForEach(markets.Keys, - new ParallelOptions { MaxDegreeOfParallelism = ParallelThrottle}, + new ParallelOptions { MaxDegreeOfParallelism = ParallelThrottle }, (key) => { if (!marketTicks.TryAdd(key, GetMarketTicks(key, totalTicks, systemConfiguration, log))) @@ -413,26 +410,28 @@ namespace Core.MarketAnalyzer } } - Dictionary tickMarkets = new Dictionary(); - foreach (string key in markets.Keys) - { - List tickRange = marketTicks[key] != null ? marketTicks[key].FindAll(t => t.Time <= tickTime) : new List(); + ConcurrentDictionary tickMarkets = new ConcurrentDictionary(); - if (tickRange.Count > 0) - { - MarketTick marketTick = tickRange.OrderByDescending(t => t.Time).First(); + Parallel.ForEach(markets.Keys, + (key) => + { + List tickRange = marketTicks[key] != null ? marketTicks[key].FindAll(t => t.Time <= tickTime) : new List(); - Market market = new Market(); - market.Position = markets.Count + 1; - market.Name = key; - market.Symbol = key; - market.Price = marketTick.Price; - //market.Volume24h = marketTick.Volume24h; - market.MainCurrencyPriceUSD = mainCurrencyPrice; + if (tickRange.Count > 0) + { + MarketTick marketTick = tickRange.OrderByDescending(t => t.Time).First(); - tickMarkets.Add(market.Name, market); - } - } + Market market = new Market(); + market.Position = markets.Count + 1; + market.Name = key; + market.Symbol = key; + market.Price = marketTick.Price; + //market.Volume24h = marketTick.Volume24h; + market.MainCurrencyPriceUSD = mainCurrencyPrice; + + tickMarkets.TryAdd(market.Name, market); + } + }); DateTime fileDateTime = new DateTime(tickTime.ToLocalTime().Year, tickTime.ToLocalTime().Month, tickTime.ToLocalTime().Day, tickTime.ToLocalTime().Hour, tickTime.ToLocalTime().Minute, 0).ToUniversalTime(); diff --git a/Core/MarketAnalyzer/BinanceFutures.cs b/Core/MarketAnalyzer/BinanceFutures.cs index de1f962..5a02643 100644 --- a/Core/MarketAnalyzer/BinanceFutures.cs +++ b/Core/MarketAnalyzer/BinanceFutures.cs @@ -1,17 +1,14 @@ using System; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Linq; using System.IO; -using System.Text; using Core.Main; using Core.Helper; using Core.Main.DataObjects.PTMagicData; using Newtonsoft.Json; -using Core.ProfitTrailer; using System.Net; -using System.Threading; using System.Threading.Tasks; -using System.Collections.Concurrent; namespace Core.MarketAnalyzer { @@ -43,7 +40,7 @@ namespace Core.MarketAnalyzer return result; } - public static List GetMarketData(string mainMarket, Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) + public static List GetMarketData(string mainMarket, ConcurrentDictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { List result = new List(); @@ -163,7 +160,7 @@ namespace Core.MarketAnalyzer return result; } - public static void CheckFirstSeenDates(Dictionary markets, ref Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) + public static void CheckFirstSeenDates(Dictionary markets, ref ConcurrentDictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { log.DoLogInfo("BinanceFutures - Checking first seen dates for " + markets.Count + " markets. This may take a while..."); @@ -182,7 +179,7 @@ namespace Core.MarketAnalyzer { marketInfo = new MarketInfo(); marketInfo.Name = key; - marketInfos.Add(key, marketInfo); + marketInfos.TryAdd(key, marketInfo); marketInfo.FirstSeen = BinanceFutures.GetFirstSeenDate(key, systemConfiguration, log); } else diff --git a/Core/MarketAnalyzer/BinanceUS.cs b/Core/MarketAnalyzer/BinanceUS.cs index 63b1318..0b09180 100644 --- a/Core/MarketAnalyzer/BinanceUS.cs +++ b/Core/MarketAnalyzer/BinanceUS.cs @@ -2,14 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.IO; -using System.Text; using Core.Main; using Core.Helper; using Core.Main.DataObjects.PTMagicData; using Newtonsoft.Json; -using Core.ProfitTrailer; using System.Net; -using System.Threading; using System.Threading.Tasks; using System.Collections.Concurrent; @@ -48,7 +45,7 @@ namespace Core.MarketAnalyzer } } - public static List GetMarketData(string mainMarket, Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) + public static List GetMarketData(string mainMarket, ConcurrentDictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { List result = new List(); @@ -168,7 +165,7 @@ namespace Core.MarketAnalyzer return result; } - public static void CheckFirstSeenDates(Dictionary markets, ref Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) + public static void CheckFirstSeenDates(Dictionary markets, ref ConcurrentDictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { log.DoLogInfo("BinanceUS - Checking first seen dates for " + markets.Count + " markets. This may take a while..."); @@ -187,7 +184,7 @@ namespace Core.MarketAnalyzer { marketInfo = new MarketInfo(); marketInfo.Name = key; - marketInfos.Add(key, marketInfo); + marketInfos.TryAdd(key, marketInfo); marketInfo.FirstSeen = BinanceUS.GetFirstSeenDate(key, systemConfiguration, log); } else diff --git a/Core/MarketAnalyzer/Bittrex.cs b/Core/MarketAnalyzer/Bittrex.cs index c7ede44..e5470e1 100644 --- a/Core/MarketAnalyzer/Bittrex.cs +++ b/Core/MarketAnalyzer/Bittrex.cs @@ -1,14 +1,12 @@ using System; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Linq; using System.IO; -using System.Text; using Core.Main; using Core.Helper; using Core.Main.DataObjects.PTMagicData; using Newtonsoft.Json; -using Core.ProfitTrailer; -using System.Threading; using System.Threading.Tasks; namespace Core.MarketAnalyzer @@ -44,7 +42,7 @@ namespace Core.MarketAnalyzer return result; } - public static List GetMarketData(string mainMarket, Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) + public static List GetMarketData(string mainMarket, ConcurrentDictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { List result = new List(); @@ -104,7 +102,7 @@ namespace Core.MarketAnalyzer { marketInfo = new MarketInfo(); marketInfo.Name = marketName; - marketInfos.Add(marketName, marketInfo); + marketInfos.TryAdd(marketName, marketInfo); } if (currencyTicker["Summary"]["Created"].Type == Newtonsoft.Json.Linq.JTokenType.Date) marketInfo.FirstSeen = (DateTime)currencyTicker["Summary"]["Created"]; marketInfo.LastSeen = DateTime.UtcNow; diff --git a/Core/MarketAnalyzer/Poloniex.cs b/Core/MarketAnalyzer/Poloniex.cs index 84a5848..64f29aa 100644 --- a/Core/MarketAnalyzer/Poloniex.cs +++ b/Core/MarketAnalyzer/Poloniex.cs @@ -1,14 +1,12 @@ using System; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Linq; using System.IO; -using System.Text; using Core.Main; using Core.Helper; using Core.Main.DataObjects.PTMagicData; using Newtonsoft.Json; -using Core.ProfitTrailer; -using System.Threading; using System.Threading.Tasks; namespace Core.MarketAnalyzer @@ -44,7 +42,7 @@ namespace Core.MarketAnalyzer return result; } - public static List GetMarketData(string mainMarket, Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) + public static List GetMarketData(string mainMarket, ConcurrentDictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { List result = new List(); @@ -125,7 +123,7 @@ namespace Core.MarketAnalyzer return result; } - public static void CheckFirstSeenDates(Dictionary markets, ref Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) + public static void CheckFirstSeenDates(Dictionary markets, ref ConcurrentDictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { log.DoLogInfo("Poloniex - Checking first seen dates for " + markets.Count + " markets. This may take a while..."); @@ -142,7 +140,7 @@ namespace Core.MarketAnalyzer { marketInfo = new MarketInfo(); marketInfo.Name = key; - marketInfos.Add(key, marketInfo); + marketInfos.TryAdd(key, marketInfo); marketInfo.FirstSeen = Poloniex.GetFirstSeenDate(key, systemConfiguration, log); } else diff --git a/Monitor/Pages/_get/BagDetails.cshtml b/Monitor/Pages/_get/BagDetails.cshtml index 087a4e1..2c5e4f8 100644 --- a/Monitor/Pages/_get/BagDetails.cshtml +++ b/Monitor/Pages/_get/BagDetails.cshtml @@ -103,7 +103,7 @@ From a797561a97275817f5cd3638bd15a2f057ccf707 Mon Sep 17 00:00:00 2001 From: djbadders <34887832+djbadders@users.noreply.github.com> Date: Sun, 20 Jun 2021 18:19:30 +0100 Subject: [PATCH 10/17] Updated to work with latest Telegram library --- Core/Helper/TelegramHelper.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Core/Helper/TelegramHelper.cs b/Core/Helper/TelegramHelper.cs index 16754ac..cd7d391 100644 --- a/Core/Helper/TelegramHelper.cs +++ b/Core/Helper/TelegramHelper.cs @@ -8,19 +8,15 @@ namespace Core.Helper { public static class TelegramHelper { - public static void SendMessage(string botToken, Int64 chatId, string message, bool useSilentMode, LogHelper log) + public async static void SendMessage(string botToken, Int64 chatId, string message, bool useSilentMode, LogHelper log) { if (!botToken.Equals("") && chatId != 0) { try { TelegramBotClient botClient = new TelegramBotClient(botToken); - System.Threading.Tasks.Task sentMessage = botClient.SendTextMessageAsync(chatId, message, ParseMode.Markdown, false, useSilentMode); - - if (sentMessage.IsCompleted) - { - log.DoLogDebug("Telegram message sent to ChatId " + chatId.ToString() + " on Bot Token '" + botToken + "'"); - } + await botClient.SendTextMessageAsync(chatId: chatId, text: message, parseMode: ParseMode.Markdown,disableNotification: useSilentMode); + log.DoLogDebug("Telegram message sent to ChatId " + chatId.ToString() + " on Bot Token '" + botToken + "'"); } catch (Exception ex) { From 6b0f6c0c27507dcbd0b248d1677fef40db0083e4 Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Mon, 21 Jun 2021 03:07:55 +0900 Subject: [PATCH 11/17] Multiple Bots --- Core/DataObjects/PTMagicData.cs | 6 +- Core/ProfitTrailer/SettingsAPI.cs | 161 ++++++++++-------- Core/ProfitTrailer/SettingsHandler.cs | 5 +- PTMagic/Program.cs | 2 +- .../settings.general.json | 12 +- .../DevSettings/settings.general.json | 8 +- 6 files changed, 113 insertions(+), 81 deletions(-) diff --git a/Core/DataObjects/PTMagicData.cs b/Core/DataObjects/PTMagicData.cs index 0083de6..25865a1 100644 --- a/Core/DataObjects/PTMagicData.cs +++ b/Core/DataObjects/PTMagicData.cs @@ -36,8 +36,10 @@ namespace Core.Main.DataObjects.PTMagicData public bool TestMode { get; set; } = true; public bool EnableBetaFeatures { get; set; } = false; public string ProfitTrailerLicense { get; set; } = ""; + public string ProfitTrailerLicenseXtra { get; set; } = ""; public string ProfitTrailerServerAPIToken { get; set; } - public string ProfitTrailerMonitorURL { get; set; } = "http://localhost:8081/"; + public string ProfitTrailerMonitorURL { get; set; } = ""; + public string ProfitTrailerMonitorURLXtra { get; set; } = ""; public string ProfitTrailerDefaultSettingName { get; set; } = "default"; public int FloodProtectionMinutes { get; set; } = 15; public string Exchange { get; set; } @@ -517,4 +519,4 @@ namespace Core.Main.DataObjects.PTMagicData } #endregion -} +} \ No newline at end of file diff --git a/Core/ProfitTrailer/SettingsAPI.cs b/Core/ProfitTrailer/SettingsAPI.cs index 83dd315..ef77c4d 100644 --- a/Core/ProfitTrailer/SettingsAPI.cs +++ b/Core/ProfitTrailer/SettingsAPI.cs @@ -19,95 +19,122 @@ namespace Core.ProfitTrailer bool transferCompleted = false; bool transferCanceled = false; - while (!transferCompleted && !transferCanceled) + // get PT license list + string licenses = systemConfiguration.GeneralSettings.Application.ProfitTrailerLicense; + if (systemConfiguration.GeneralSettings.Application.ProfitTrailerLicenseXtra != "") { - try + licenses = licenses + ", " + systemConfiguration.GeneralSettings.Application.ProfitTrailerLicenseXtra; + } + List licenseList = SystemHelper.ConvertTokenStringToList(licenses, ","); + int licenseCount = licenseList.Count; + + // get URL list + string urls = systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL; + if (systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURLXtra != "") + { + urls = urls + ", " + systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURLXtra; + } + List urlList = SystemHelper.ConvertTokenStringToList(urls, ","); + int urlCount = urlList.Count; + + log.DoLogInfo("Found " + licenseCount + " licenses and " + urlCount + " URLs"); + if (urlCount != licenseCount) + { + log.DoLogWarn("ERROR - urlCount must match licenseCount"); + } + for (int i = 0; i < licenseCount; i++) + { + transferCompleted = false; + while (!transferCompleted && !transferCanceled) { - ServicePointManager.Expect100Continue = true; - ServicePointManager.DefaultConnectionLimit = 9999; - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; - ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(CertificateHelper.AllwaysGoodCertificate); - - HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL + "settingsapi/settings/saveAll"); - httpWebRequest.ContentType = "application/x-www-form-urlencoded"; - httpWebRequest.Method = "POST"; - httpWebRequest.Proxy = null; - httpWebRequest.Timeout = 30000; - - // PT is using ordinary POST data, not JSON - string query = "configName=" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "&license=" + systemConfiguration.GeneralSettings.Application.ProfitTrailerLicense; - string pairsPropertiesString = SystemHelper.ConvertListToTokenString(pairsLines, Environment.NewLine, false); - string dcaPropertiesString = SystemHelper.ConvertListToTokenString(dcaLines, Environment.NewLine, false); - string indicatorsPropertiesString = SystemHelper.ConvertListToTokenString(indicatorsLines, Environment.NewLine, false); - query += "&pairsData=" + WebUtility.UrlEncode(pairsPropertiesString) + "&dcaData=" + WebUtility.UrlEncode(dcaPropertiesString) + "&indicatorsData=" + WebUtility.UrlEncode(indicatorsPropertiesString); - - byte[] formData = Encoding.ASCII.GetBytes(query); - httpWebRequest.ContentLength = formData.Length; - - using (Stream stream = httpWebRequest.GetRequestStream()) + try { - stream.Write(formData, 0, formData.Length); + ServicePointManager.Expect100Continue = true; + ServicePointManager.DefaultConnectionLimit = 9999; + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; + ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(CertificateHelper.AllwaysGoodCertificate); + HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(urlList[i] + "settingsapi/settings/saveAll"); + httpWebRequest.ContentType = "application/x-www-form-urlencoded"; + httpWebRequest.Method = "POST"; + httpWebRequest.Proxy = null; + httpWebRequest.Timeout = 30000; + + // PT is using ordinary POST data, not JSON + string query = "configName=" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName; + query = query + "&license=" + licenseList[i]; + string pairsPropertiesString = SystemHelper.ConvertListToTokenString(pairsLines, Environment.NewLine, false); + string dcaPropertiesString = SystemHelper.ConvertListToTokenString(dcaLines, Environment.NewLine, false); + string indicatorsPropertiesString = SystemHelper.ConvertListToTokenString(indicatorsLines, Environment.NewLine, false); + query += "&pairsData=" + WebUtility.UrlEncode(pairsPropertiesString) + "&dcaData=" + WebUtility.UrlEncode(dcaPropertiesString) + "&indicatorsData=" + WebUtility.UrlEncode(indicatorsPropertiesString); + byte[] formData = Encoding.ASCII.GetBytes(query); + httpWebRequest.ContentLength = formData.Length; + using (Stream stream = httpWebRequest.GetRequestStream()) + { + stream.Write(formData, 0, formData.Length); + } + log.DoLogDebug("Built POST request for Properties"); + int adjustedCount = i+1; + log.DoLogInfo("Sending Properties to license " + adjustedCount + " at " + urlList[i]); + using (HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse()) + { + log.DoLogInfo("Properties sent!"); + httpResponse.Close(); + log.DoLogDebug("Properties response object closed."); + } + + transferCompleted = true; } - log.DoLogDebug("Built POST request for Properties"); + catch (WebException ex) + { + // Manual error handling as PT doesn't seem to provide a proper error response... + if (ex.Message.IndexOf("401") > -1) + { + log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Unauthorized! The specified Profit Trailer license key '" + systemConfiguration.GetProfitTrailerLicenseKeyMasked() + "' is invalid!"); + transferCanceled = true; + } + else if (ex.Message.IndexOf("timed out") > -1) + { + // Handle timeout seperately + retryCount++; + if (retryCount <= maxRetries) + { + log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!"); + } + else + { + transferCanceled = true; + log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Canceling transfer after " + maxRetries.ToString() + " failed retries."); + } + } + else + { + log.DoLogCritical("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex); + transferCanceled = true; + } - log.DoLogInfo("Sending Properties..."); - using (HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse()) - { - log.DoLogInfo("Properties sent!"); - httpResponse.Close(); - log.DoLogDebug("Properties response object closed."); } - - transferCompleted = true; - } - catch (WebException ex) - { - // Manual error handling as PT doesn't seem to provide a proper error response... - if (ex.Message.IndexOf("401") > -1) + catch (TimeoutException ex) { - log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Unauthorized! The specified Profit Trailer license key '" + systemConfiguration.GetProfitTrailerLicenseKeyMasked() + "' is invalid!"); - transferCanceled = true; - } - else if (ex.Message.IndexOf("timed out") > -1) - { - // Handle timeout seperately retryCount++; if (retryCount <= maxRetries) { - log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!"); + log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!"); } else { transferCanceled = true; - log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Canceling transfer after " + maxRetries.ToString() + " failed retries."); + log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Canceling transfer after " + maxRetries.ToString() + " failed retries."); } } - else + catch (Exception ex) { log.DoLogCritical("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex); transferCanceled = true; } - - } - catch (TimeoutException ex) - { - retryCount++; - if (retryCount <= maxRetries) - { - log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!"); - } - else - { - transferCanceled = true; - log.DoLogError("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Canceling transfer after " + maxRetries.ToString() + " failed retries."); - } - } - catch (Exception ex) - { - log.DoLogCritical("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex); - transferCanceled = true; } } + + } } } \ No newline at end of file diff --git a/Core/ProfitTrailer/SettingsHandler.cs b/Core/ProfitTrailer/SettingsHandler.cs index 71bac93..c119c64 100644 --- a/Core/ProfitTrailer/SettingsHandler.cs +++ b/Core/ProfitTrailer/SettingsHandler.cs @@ -144,9 +144,8 @@ namespace Core.ProfitTrailer foreach (string line in pairsLines) { - if (line.Replace(" ", "").StartsWith("ALL_enabled_pairs", StringComparison.InvariantCultureIgnoreCase) || line.Replace(" ", "").StartsWith("enabled_pairs", StringComparison.InvariantCultureIgnoreCase)) + if (line.Replace(" ", "").StartsWith("enabled_pairs", StringComparison.InvariantCultureIgnoreCase)) { - result = line.Replace("ALL_enabled_pairs", "", StringComparison.InvariantCultureIgnoreCase); result = result.Replace("enabled_pairs", "", StringComparison.InvariantCultureIgnoreCase); result = result.Replace("#", ""); result = result.Replace("=", "").Trim(); @@ -644,4 +643,4 @@ namespace Core.ProfitTrailer } #endregion } -} +} \ No newline at end of file diff --git a/PTMagic/Program.cs b/PTMagic/Program.cs index 7e510b4..a4be87c 100644 --- a/PTMagic/Program.cs +++ b/PTMagic/Program.cs @@ -6,7 +6,7 @@ using Core.Helper; using Microsoft.Extensions.DependencyInjection; -[assembly: AssemblyVersion("2.5.11")] +[assembly: AssemblyVersion("2.5.12")] [assembly: AssemblyProduct("PT Magic")] namespace PTMagic diff --git a/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json b/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json index eac6cf2..510a0ce 100644 --- a/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json +++ b/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json @@ -3,10 +3,12 @@ "Application": { "IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect) "TestMode": false, // If TestMode is active, no properties files will be changed - "ProfitTrailerLicense": "YOUR PROFIT TRAILER LICENSE KEY", // Your Profit Trailer license key (needed to change your settings for PT 2.0 and above) + "ProfitTrailerLicense": "ptlicense1asdf234fljlasdf014325ehm", // Your Profit Trailer license key (needed to change your settings) + "ProfitTrailerLicenseXtra": "ptlicense1asdf234fljlasdf014325ehm, ptlicense2asdfou12987uasdflkj122134jkr", // Licenses for additional bots you want PTM to update (optional) "ProfitTrailerServerAPIToken": "", //Your Profit Trailer Server API Token - "ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings for PT 2.0 and above) - "ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings for PT 2.0 and above) + "ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings) + "ProfitTrailerMonitorURLXtra": "http://localhost:8082/, http://localhost:8083/", // URLs for additional bots you want PTM to update (optional) + "ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings) "Exchange": "Bittrex", // The exchange your are running Profit Trailer on "StartBalance": 0, // The balance you had in your wallet when you started working with Profit Trailer "TimezoneOffset": "+0:00", // Your timezone offset from UTC time @@ -19,9 +21,9 @@ "Monitor": { "IsPasswordProtected": true, // Defines if your monitor will be asking to setup a password on its first start "OpenBrowserOnStart": false, // If active, a browser window will open as soon as you start the monitor - "Port": 5000, // The port you want to run your monitor on + "Port": 8080, // The port you want to run your monitor on "RootUrl": "/", // The root Url of your monitor - "AnalyzerChart":"", // By default the chart on the market analyzer page displays your base currency against USD. You may change this if you like (eg., BTCEUR) + "AnalyzerChart": "", // By default the chart on the Market Analyzer page will use your default currency against USD. You can change that here. (eg., BTCEUR) "GraphIntervalMinutes": 60, // The interval for the monitor market trend graph to draw points "GraphMaxTimeframeHours": 24, // This will enable you to define the timeframe that your graph for market trends covers "RefreshSeconds": 30, // The refresh interval of your monitor main page diff --git a/_Development/DevSettings/settings.general.json b/_Development/DevSettings/settings.general.json index 33b8405..510a0ce 100644 --- a/_Development/DevSettings/settings.general.json +++ b/_Development/DevSettings/settings.general.json @@ -3,10 +3,12 @@ "Application": { "IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect) "TestMode": false, // If TestMode is active, no properties files will be changed - "ProfitTrailerLicense": "YOUR PROFIT TRAILER LICENSE KEY", // Your Profit Trailer license key (needed to change your settings for PT 2.0 and above) + "ProfitTrailerLicense": "ptlicense1asdf234fljlasdf014325ehm", // Your Profit Trailer license key (needed to change your settings) + "ProfitTrailerLicenseXtra": "ptlicense1asdf234fljlasdf014325ehm, ptlicense2asdfou12987uasdflkj122134jkr", // Licenses for additional bots you want PTM to update (optional) "ProfitTrailerServerAPIToken": "", //Your Profit Trailer Server API Token - "ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings for PT 2.0 and above) - "ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings for PT 2.0 and above) + "ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings) + "ProfitTrailerMonitorURLXtra": "http://localhost:8082/, http://localhost:8083/", // URLs for additional bots you want PTM to update (optional) + "ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings) "Exchange": "Bittrex", // The exchange your are running Profit Trailer on "StartBalance": 0, // The balance you had in your wallet when you started working with Profit Trailer "TimezoneOffset": "+0:00", // Your timezone offset from UTC time From ab9e6f2977198fbc4025f87ae63ef5a0be206f87 Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Mon, 21 Jun 2021 03:15:13 +0900 Subject: [PATCH 12/17] changed default settings.general --- .../_defaults/_default_settings_PT_2.x/settings.general.json | 4 ++-- _Development/DevSettings/settings.general.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json b/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json index 510a0ce..4f9bb22 100644 --- a/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json +++ b/PTMagic/_defaults/_default_settings_PT_2.x/settings.general.json @@ -4,10 +4,10 @@ "IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect) "TestMode": false, // If TestMode is active, no properties files will be changed "ProfitTrailerLicense": "ptlicense1asdf234fljlasdf014325ehm", // Your Profit Trailer license key (needed to change your settings) - "ProfitTrailerLicenseXtra": "ptlicense1asdf234fljlasdf014325ehm, ptlicense2asdfou12987uasdflkj122134jkr", // Licenses for additional bots you want PTM to update (optional) + "ProfitTrailerLicenseXtra": "", // Licenses for additional bots for PTM to update (optional - comma separated list) "ProfitTrailerServerAPIToken": "", //Your Profit Trailer Server API Token "ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings) - "ProfitTrailerMonitorURLXtra": "http://localhost:8082/, http://localhost:8083/", // URLs for additional bots you want PTM to update (optional) + "ProfitTrailerMonitorURLXtra": "", // URLs for additional bots you want PTM to update (optional - comma separated list) "ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings) "Exchange": "Bittrex", // The exchange your are running Profit Trailer on "StartBalance": 0, // The balance you had in your wallet when you started working with Profit Trailer diff --git a/_Development/DevSettings/settings.general.json b/_Development/DevSettings/settings.general.json index 510a0ce..4f9bb22 100644 --- a/_Development/DevSettings/settings.general.json +++ b/_Development/DevSettings/settings.general.json @@ -4,10 +4,10 @@ "IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect) "TestMode": false, // If TestMode is active, no properties files will be changed "ProfitTrailerLicense": "ptlicense1asdf234fljlasdf014325ehm", // Your Profit Trailer license key (needed to change your settings) - "ProfitTrailerLicenseXtra": "ptlicense1asdf234fljlasdf014325ehm, ptlicense2asdfou12987uasdflkj122134jkr", // Licenses for additional bots you want PTM to update (optional) + "ProfitTrailerLicenseXtra": "", // Licenses for additional bots for PTM to update (optional - comma separated list) "ProfitTrailerServerAPIToken": "", //Your Profit Trailer Server API Token "ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings) - "ProfitTrailerMonitorURLXtra": "http://localhost:8082/, http://localhost:8083/", // URLs for additional bots you want PTM to update (optional) + "ProfitTrailerMonitorURLXtra": "", // URLs for additional bots you want PTM to update (optional - comma separated list) "ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings) "Exchange": "Bittrex", // The exchange your are running Profit Trailer on "StartBalance": 0, // The balance you had in your wallet when you started working with Profit Trailer From 393d922e5022bb68063e5b718c4ac5003846a53c Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Thu, 5 Aug 2021 13:45:24 +0900 Subject: [PATCH 13/17] Conditional Formulas --- Core/ProfitTrailer/StrategyHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/ProfitTrailer/StrategyHelper.cs b/Core/ProfitTrailer/StrategyHelper.cs index b211fe0..cdd873b 100644 --- a/Core/ProfitTrailer/StrategyHelper.cs +++ b/Core/ProfitTrailer/StrategyHelper.cs @@ -272,7 +272,7 @@ namespace Core.ProfitTrailer if (!string.IsNullOrEmpty(strategyName)) { // buy/sell strategies beginning with PT 2.3.3 contain the letter followed by a colon and space. - if (strategyName.Contains(":")) + if (strategyName.Contains(":") && !strategyName.Contains("FORMULA")) { result = true; } From 9c9b6c5749d1e7b5e17c18bb3bd41635f8549da4 Mon Sep 17 00:00:00 2001 From: djbadders <34887832+djbadders@users.noreply.github.com> Date: Sun, 8 Aug 2021 17:29:37 +0100 Subject: [PATCH 14/17] Fix possible exception when PTM last run file is being written --- Monitor/_Internal/BasePageModel.cs | 339 +++++++++++++++-------------- 1 file changed, 178 insertions(+), 161 deletions(-) diff --git a/Monitor/_Internal/BasePageModel.cs b/Monitor/_Internal/BasePageModel.cs index b3ee870..d05f2eb 100644 --- a/Monitor/_Internal/BasePageModel.cs +++ b/Monitor/_Internal/BasePageModel.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Threading; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Configuration; @@ -15,170 +16,186 @@ using Core.Main.DataObjects; namespace Monitor._Internal { - public class BasePageModel : PageModel - { - public string PTMagicBasePath = ""; - public string PTMagicMonitorBasePath = ""; - public PTMagicConfiguration PTMagicConfiguration = null; - public Summary Summary { get; set; } = new Summary(); - public LogHelper Log = null; - public string LatestVersion = ""; - public string CurrentBotVersion = ""; - public string NotifyHeadline = ""; - public string NotifyMessage = ""; - public string NotifyType = ""; - - public string MainFiatCurrencySymbol = "$"; - private volatile object _ptDataLock = new object(); - private static ProfitTrailerData _ptData = null; - - // Profit Trailer data accessor object - public ProfitTrailerData PtDataObject + public class BasePageModel : PageModel { - get - { - if (_ptData == null) + public string PTMagicBasePath = ""; + public string PTMagicMonitorBasePath = ""; + public PTMagicConfiguration PTMagicConfiguration = null; + public Summary Summary { get; set; } = new Summary(); + public LogHelper Log = null; + public string LatestVersion = ""; + public string CurrentBotVersion = ""; + public string NotifyHeadline = ""; + public string NotifyMessage = ""; + public string NotifyType = ""; + + public string MainFiatCurrencySymbol = "$"; + private volatile object _ptDataLock = new object(); + private static ProfitTrailerData _ptData = null; + + // Profit Trailer data accessor object + public ProfitTrailerData PtDataObject { - lock (_ptDataLock) - { - _ptData = new ProfitTrailerData(PTMagicConfiguration); - } + get + { + if (_ptData == null) + { + lock (_ptDataLock) + { + _ptData = new ProfitTrailerData(PTMagicConfiguration); + } + } + + return _ptData; + } } - return _ptData; - } + public void PreInit() + { + PTMagicMonitorBasePath = Directory.GetCurrentDirectory(); + if (!System.IO.File.Exists(PTMagicMonitorBasePath + Path.DirectorySeparatorChar + "appsettings.json")) + { + PTMagicMonitorBasePath += Path.DirectorySeparatorChar + "Monitor"; + } + + if (!PTMagicMonitorBasePath.EndsWith(Path.DirectorySeparatorChar)) + { + PTMagicMonitorBasePath += Path.DirectorySeparatorChar; + } + + IConfiguration config = new ConfigurationBuilder() + .SetBasePath(PTMagicMonitorBasePath) + .AddJsonFile("appsettings.json", false) + .Build(); + + PTMagicBasePath = config.GetValue("PTMagicBasePath"); + + if (!PTMagicBasePath.EndsWith(Path.DirectorySeparatorChar)) + { + PTMagicBasePath += Path.DirectorySeparatorChar; + } + + PTMagicConfiguration = new PTMagicConfiguration(PTMagicBasePath); + + IServiceProvider logProvider = ServiceHelper.BuildLoggerService(PTMagicBasePath); + Log = logProvider.GetRequiredService(); + + bool exitLoop = false; + + while (!exitLoop) + { + try + { + // Try to read the current runtime summary, but may be being written, so retry if necessary. + Summary = JsonConvert.DeserializeObject(System.IO.File.ReadAllText(PTMagicBasePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar + "LastRuntimeSummary.json")); + exitLoop = true; + } + catch (IOException e) + { + // Squash exception and try again, as file was locked. + Thread.Sleep(250); + } + } + + if (Summary.CurrentGlobalSetting == null) Summary.CurrentGlobalSetting = PTMagicConfiguration.AnalyzerSettings.GlobalSettings.Find(s => s.SettingName.IndexOf("default", StringComparison.InvariantCultureIgnoreCase) > -1); + + MainFiatCurrencySymbol = SystemHelper.GetCurrencySymbol(Summary.MainFiatCurrency); + + try + { + // Get latest release from GitHub + if (!String.IsNullOrEmpty(HttpContext.Session.GetString("LatestVersion"))) + { + LatestVersion = HttpContext.Session.GetString("LatestVersion"); + } + else + { + LatestVersion = BaseAnalyzer.GetLatestGitHubRelease(Log, Summary.Version); + HttpContext.Session.SetString("LatestVersion", LatestVersion); + } + } + catch { } + + try + { + // Get current bot version + if (!String.IsNullOrEmpty(HttpContext.Session.GetString("CurrentBotVersion"))) + { + CurrentBotVersion = HttpContext.Session.GetString("CurrentBotVersion"); + } + else + { + string ptMagicBotDllPath = PTMagicBasePath + "PTMagic.dll"; + if (System.IO.File.Exists(ptMagicBotDllPath)) + { + FileVersionInfo ptMagicDllInfo = FileVersionInfo.GetVersionInfo(ptMagicBotDllPath); + + CurrentBotVersion = ptMagicDllInfo.ProductVersion.Substring(0, ptMagicDllInfo.ProductVersion.LastIndexOf(".")); + HttpContext.Session.SetString("CurrentBotVersion", CurrentBotVersion); + } + else + { + CurrentBotVersion = Summary.Version; + } + } + + } + catch + { + CurrentBotVersion = Summary.Version; + } + } + + protected string GetStringParameter(string paramName, string defaultValue) + { + string result = defaultValue; + + if (HttpContext.Request.Query.ContainsKey(paramName)) + { + result = HttpContext.Request.Query[paramName]; + } + else if (HttpContext.Request.Method.Equals("POST") && HttpContext.Request.Form.ContainsKey(paramName)) + { + result = HttpContext.Request.Form[paramName]; + } + + return result; + } + + /// + /// Holt einen Url-Parameter als Integer, wenn vorhanden. + /// + /// Name des Parameters + /// Defaultvalue, wenn Parameter nicht vorhanden ist. + /// Der Wert des Parameters als Integer. + protected int GetIntParameter(string paramName, int defaultValue) + { + int result = defaultValue; + + if (HttpContext.Request.Query.ContainsKey(paramName)) + { + try + { + result = Int32.Parse(HttpContext.Request.Query[paramName]); + } + catch + { + result = defaultValue; + } + } + else if (HttpContext.Request.Method.Equals("POST") && HttpContext.Request.Form.ContainsKey(paramName)) + { + try + { + result = Int32.Parse(HttpContext.Request.Form[paramName]); + } + catch + { + result = defaultValue; + } + } + + return result; + } } - - public void PreInit() - { - PTMagicMonitorBasePath = Directory.GetCurrentDirectory(); - if (!System.IO.File.Exists(PTMagicMonitorBasePath + Path.DirectorySeparatorChar + "appsettings.json")) - { - PTMagicMonitorBasePath += Path.DirectorySeparatorChar + "Monitor"; - } - - if (!PTMagicMonitorBasePath.EndsWith(Path.DirectorySeparatorChar)) - { - PTMagicMonitorBasePath += Path.DirectorySeparatorChar; - } - - IConfiguration config = new ConfigurationBuilder() - .SetBasePath(PTMagicMonitorBasePath) - .AddJsonFile("appsettings.json", false) - .Build(); - - PTMagicBasePath = config.GetValue("PTMagicBasePath"); - - if (!PTMagicBasePath.EndsWith(Path.DirectorySeparatorChar)) - { - PTMagicBasePath += Path.DirectorySeparatorChar; - } - - PTMagicConfiguration = new PTMagicConfiguration(PTMagicBasePath); - - IServiceProvider logProvider = ServiceHelper.BuildLoggerService(PTMagicBasePath); - Log = logProvider.GetRequiredService(); - - Summary = JsonConvert.DeserializeObject(System.IO.File.ReadAllText(PTMagicBasePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar + "LastRuntimeSummary.json")); - if (Summary.CurrentGlobalSetting == null) Summary.CurrentGlobalSetting = PTMagicConfiguration.AnalyzerSettings.GlobalSettings.Find(s => s.SettingName.IndexOf("default", StringComparison.InvariantCultureIgnoreCase) > -1); - - MainFiatCurrencySymbol = SystemHelper.GetCurrencySymbol(Summary.MainFiatCurrency); - - try - { - // Get latest release from GitHub - if (!String.IsNullOrEmpty(HttpContext.Session.GetString("LatestVersion"))) - { - LatestVersion = HttpContext.Session.GetString("LatestVersion"); - } - else - { - LatestVersion = BaseAnalyzer.GetLatestGitHubRelease(Log, Summary.Version); - HttpContext.Session.SetString("LatestVersion", LatestVersion); - } - } - catch { } - - try - { - // Get current bot version - if (!String.IsNullOrEmpty(HttpContext.Session.GetString("CurrentBotVersion"))) - { - CurrentBotVersion = HttpContext.Session.GetString("CurrentBotVersion"); - } - else - { - string ptMagicBotDllPath = PTMagicBasePath + "PTMagic.dll"; - if (System.IO.File.Exists(ptMagicBotDllPath)) - { - FileVersionInfo ptMagicDllInfo = FileVersionInfo.GetVersionInfo(ptMagicBotDllPath); - - CurrentBotVersion = ptMagicDllInfo.ProductVersion.Substring(0, ptMagicDllInfo.ProductVersion.LastIndexOf(".")); - HttpContext.Session.SetString("CurrentBotVersion", CurrentBotVersion); - } - else - { - CurrentBotVersion = Summary.Version; - } - } - - } - catch - { - CurrentBotVersion = Summary.Version; - } - } - - protected string GetStringParameter(string paramName, string defaultValue) - { - string result = defaultValue; - - if (HttpContext.Request.Query.ContainsKey(paramName)) - { - result = HttpContext.Request.Query[paramName]; - } - else if (HttpContext.Request.Method.Equals("POST") && HttpContext.Request.Form.ContainsKey(paramName)) - { - result = HttpContext.Request.Form[paramName]; - } - - return result; - } - - /// - /// Holt einen Url-Parameter als Integer, wenn vorhanden. - /// - /// Name des Parameters - /// Defaultvalue, wenn Parameter nicht vorhanden ist. - /// Der Wert des Parameters als Integer. - protected int GetIntParameter(string paramName, int defaultValue) - { - int result = defaultValue; - - if (HttpContext.Request.Query.ContainsKey(paramName)) - { - try - { - result = Int32.Parse(HttpContext.Request.Query[paramName]); - } - catch - { - result = defaultValue; - } - } - else if (HttpContext.Request.Method.Equals("POST") && HttpContext.Request.Form.ContainsKey(paramName)) - { - try - { - result = Int32.Parse(HttpContext.Request.Form[paramName]); - } - catch - { - result = defaultValue; - } - } - - return result; - } - } } From 309e4dfe7d02ba63296732db2007e4c1d927e7b4 Mon Sep 17 00:00:00 2001 From: djbadders <34887832+djbadders@users.noreply.github.com> Date: Sun, 8 Aug 2021 17:30:01 +0100 Subject: [PATCH 15/17] Implement paged retrieval of sales dat --- Core/DataObjects/ProfitTrailerData.cs | 28 +++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/Core/DataObjects/ProfitTrailerData.cs b/Core/DataObjects/ProfitTrailerData.cs index 6cc70b1..b49fa63 100644 --- a/Core/DataObjects/ProfitTrailerData.cs +++ b/Core/DataObjects/ProfitTrailerData.cs @@ -108,7 +108,28 @@ namespace Core.Main.DataObjects if (_sellLog == null || (DateTime.UtcNow > _sellLogRefresh)) { _sellLog.Clear(); - this.BuildSellLogData(GetDataFromProfitTrailer("/api/v2/data/sales")); + + // Page through the sales data summarizing it. + bool exitLoop = false; + int pageIndex = 1; + + while (!exitLoop) + { + var sellDataPage = GetDataFromProfitTrailer("/api/v2/data/sales?perPage=5000&sort=SOLDDATE&sortDirection=ASCENDING&page=" + pageIndex); + if (sellDataPage != null && sellDataPage.data.Count > 0) + { + // Add sales data page to collection + this.BuildSellLogData(sellDataPage); + pageIndex++; + } + else + { + // All data retrieved + exitLoop = true; + } + } + + // Update sell log refresh time _sellLogRefresh = DateTime.UtcNow.AddSeconds(_systemConfiguration.GeneralSettings.Monitor.RefreshSeconds - 1); } } @@ -265,7 +286,10 @@ namespace Core.Main.DataObjects private dynamic GetDataFromProfitTrailer(string callPath, bool arrayReturned = false) { string rawBody = ""; - string url = string.Format("{0}{1}?token={2}", _systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL, callPath, _systemConfiguration.GeneralSettings.Application.ProfitTrailerServerAPIToken); + string url = string.Format("{0}{1}{2}token={3}", _systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL, + callPath, + callPath.Contains("?") ? "&" : "?", + _systemConfiguration.GeneralSettings.Application.ProfitTrailerServerAPIToken); // Get the data from PT Debug.WriteLine(String.Format("{0} - Calling '{1}'", DateTime.UtcNow, url)); From 51988666072ff08bae3dc615616ccce952881797 Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Tue, 24 Aug 2021 12:48:50 +0900 Subject: [PATCH 16/17] shorting calculations --- Core/DataObjects/ProfitTrailerData.cs | 10 +---- Monitor/Pages/SalesAnalyzer.cshtml | 40 ++--------------- Monitor/Pages/SalesAnalyzer.cshtml.cs | 36 ++-------------- Monitor/Pages/_get/DashboardBottom.cshtml | 45 +++----------------- Monitor/Pages/_get/DashboardBottom.cshtml.cs | 4 -- 5 files changed, 15 insertions(+), 120 deletions(-) diff --git a/Core/DataObjects/ProfitTrailerData.cs b/Core/DataObjects/ProfitTrailerData.cs index b49fa63..df01a9a 100644 --- a/Core/DataObjects/ProfitTrailerData.cs +++ b/Core/DataObjects/ProfitTrailerData.cs @@ -355,15 +355,9 @@ namespace Core.Main.DataObjects sellLogData.ProfitPercent = rsld.profit; sellLogData.SoldPrice = rsld.currentPrice; sellLogData.AverageBuyPrice = rsld.avgPrice; - sellLogData.TotalCost = sellLogData.SoldAmount * sellLogData.AverageBuyPrice; + sellLogData.TotalCost = rsld.totalCost; + sellLogData.Profit = rsld.profitCurrency; - // check if bot is a shortbot via PT API. Losses on short bot currently showing as gains. Issue #195 - // code removed - - double soldValueRaw = (sellLogData.SoldAmount * sellLogData.SoldPrice); - double soldValueAfterFees = soldValueRaw - (soldValueRaw * ((double)rsld.fee / 100)); - sellLogData.SoldValue = soldValueAfterFees; - sellLogData.Profit = Math.Round(sellLogData.SoldValue - sellLogData.TotalCost, 8); //Convert Unix Timestamp to Datetime System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc); diff --git a/Monitor/Pages/SalesAnalyzer.cshtml b/Monitor/Pages/SalesAnalyzer.cshtml index 79e99b7..f75c554 100644 --- a/Monitor/Pages/SalesAnalyzer.cshtml +++ b/Monitor/Pages/SalesAnalyzer.cshtml @@ -62,14 +62,7 @@

Sales Analysis

@{ double totalProfit = 0; - if (Model.PTData.Properties.Shorting) - { - totalProfit = Model.PTData.SellLog.Sum(s => s.Profit * (-1)); - } - else - { - totalProfit = Model.PTData.SellLog.Sum(s => s.Profit); - } + totalProfit = Model.PTData.SellLog.Sum(s => s.Profit); double totalProfitFiat = Math.Round(totalProfit * Model.Summary.MainMarketPrice, 2); double percentGain = Math.Round(totalProfit / Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance * 100, 2); double avgDailyGain = Model.DailyGains.Values.Average(dg => dg); @@ -205,14 +198,7 @@ @for (DateTime salesDate = Model.DateTimeNow.DateTime.Date; salesDate >= Model.DateTimeNow.DateTime.AddDays(-Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDailySummaries) && salesDate >= Model.MinSellLogDate; salesDate = salesDate.AddDays(-1)) { List salesDateSales = Model.PTData.SellLog.FindAll(sl => sl.SoldDate.Date == salesDate); double salesDateProfit = 0; - if (Model.PTData.Properties.Shorting) - { - salesDateProfit = salesDateSales.Sum(sl => sl.Profit * (-1)); - } - else - { - salesDateProfit = salesDateSales.Sum(sl => sl.Profit); - } + salesDateProfit = salesDateSales.Sum(sl => sl.Profit); double salesDateProfitFiat = Math.Round(salesDateProfit * Model.Summary.MainMarketPrice, 2); double salesDateStartBalance = Model.PTData.GetSnapshotBalance(salesDate); double salesDateGain = Math.Round(salesDateProfit / salesDateStartBalance * 100, 2); @@ -252,14 +238,7 @@ @for (DateTime salesMonthDate = salesMonthStartDate.Date; salesMonthDate >= Model.DateTimeNow.DateTime.AddMonths(-Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxMonthlySummaries) && salesMonthDate >= minSellLogMonthDate; salesMonthDate = salesMonthDate.AddMonths(-1)) { List salesMonthSales = Model.PTData.SellLog.FindAll(sl => sl.SoldDate.Date.Month == salesMonthDate.Month && sl.SoldDate.Date.Year == salesMonthDate.Year); double salesDateProfit = 0; - if (Model.PTData.Properties.Shorting) - { - salesDateProfit = salesMonthSales.Sum(sl => sl.Profit * (-1)); - } - else - { - salesDateProfit = salesMonthSales.Sum(sl => sl.Profit); - } + salesDateProfit = salesMonthSales.Sum(sl => sl.Profit); double salesDateProfitFiat = Math.Round(salesDateProfit * Model.Summary.MainMarketPrice, 2); double salesDateStartBalance = Model.PTData.GetSnapshotBalance(salesMonthDate); double salesDateGain = Math.Round(salesDateProfit / salesDateStartBalance * 100, 2); @@ -272,14 +251,7 @@ days++; List monthDaySales = Model.PTData.SellLog.FindAll(sl => sl.SoldDate.Date == monthDay.Date); double monthDayProfit = 0; - if (Model.PTData.Properties.Shorting) - { - monthDayProfit = monthDaySales.Sum(sl => sl.Profit * (-1)); - } - else - { - monthDayProfit = monthDaySales.Sum(sl => sl.Profit); - } + monthDayProfit = monthDaySales.Sum(sl => sl.Profit); double monthDayStartBalance = Model.PTData.GetSnapshotBalance(monthDay); monthDailyProfit += Math.Round(monthDayProfit / monthDayStartBalance * 100, 2); } @@ -319,10 +291,6 @@ @{ var topMarkets = Model.PTData.SellLog.GroupBy(m => m.Market).Select(mg => mg.Sum(m => m.Profit)); - if (Model.PTData.Properties.Shorting) - { - topMarkets = Model.PTData.SellLog.GroupBy(m => m.Market).Select(mg => mg.Sum(m => m.Profit) * (-1)); - } int marketRank = 0; } @foreach (KeyValuePair marketData in Model.TopMarkets) { diff --git a/Monitor/Pages/SalesAnalyzer.cshtml.cs b/Monitor/Pages/SalesAnalyzer.cshtml.cs index 1b2a00f..74d1b73 100644 --- a/Monitor/Pages/SalesAnalyzer.cshtml.cs +++ b/Monitor/Pages/SalesAnalyzer.cshtml.cs @@ -46,14 +46,7 @@ namespace Monitor.Pages foreach (var market in markets) { double totalProfit = 0; - if (PTData.Properties.Shorting) - { - totalProfit = PTData.SellLog.FindAll(m => m.Market == market.Key).Sum(m => m.Profit * (-1)); - } - else - { - totalProfit = PTData.SellLog.FindAll(m => m.Market == market.Key).Sum(m => m.Profit); - } + totalProfit = PTData.SellLog.FindAll(m => m.Market == market.Key).Sum(m => m.Profit); topMarketsDic.Add(market.Key, totalProfit); } TopMarkets = new SortedDictionary(topMarketsDic).OrderByDescending(m => m.Value).Take(PTMagicConfiguration.GeneralSettings.Monitor.MaxTopMarkets); @@ -81,14 +74,7 @@ namespace Monitor.Pages } double profit = 0; int trades = PTData.SellLog.FindAll(t => t.SoldDate.Date == salesDate.Date).Count; - if (PTData.Properties.Shorting) - { - profit = PTData.SellLog.FindAll(t => t.SoldDate.Date == salesDate.Date).Sum(t => t.Profit * (-1)); - } - else - { - profit = PTData.SellLog.FindAll(t => t.SoldDate.Date == salesDate.Date).Sum(t => t.Profit); - } + profit = PTData.SellLog.FindAll(t => t.SoldDate.Date == salesDate.Date).Sum(t => t.Profit); double profitFiat = Math.Round(profit * Summary.MainMarketPrice, 2); balance += profitFiat; tradesPerDayJSON += "{x: new Date('" + salesDate.Date.ToString("yyyy-MM-dd") + "'), y: " + trades + "}"; @@ -124,14 +110,7 @@ namespace Monitor.Pages { List salesDateSales = PTData.SellLog.FindAll(sl => sl.SoldDate.Date == salesDate); double salesDateProfit; - if (PTData.Properties.Shorting) - { - salesDateProfit = salesDateSales.Sum(sl => sl.Profit * (-1)); - } - else - { - salesDateProfit = salesDateSales.Sum(sl => sl.Profit); - } + salesDateProfit = salesDateSales.Sum(sl => sl.Profit); double salesDateStartBalance = PTData.GetSnapshotBalance(salesDate); double salesDateGain = Math.Round(salesDateProfit / salesDateStartBalance * 100, 2); DailyGains.Add(salesDate, salesDateGain); @@ -142,14 +121,7 @@ namespace Monitor.Pages { List salesMonthSales = PTData.SellLog.FindAll(sl => sl.SoldDate.Date.Month == salesMonthDate.Month && sl.SoldDate.Date.Year == salesMonthDate.Year); double salesDateProfit; - if (PTData.Properties.Shorting) - { - salesDateProfit = salesMonthSales.Sum(sl => sl.Profit * (-1)); - } - else - { - salesDateProfit = salesMonthSales.Sum(sl => sl.Profit); - } + salesDateProfit = salesMonthSales.Sum(sl => sl.Profit); double salesDateStartBalance = PTData.GetSnapshotBalance(salesMonthDate); double salesDateGain = Math.Round(salesDateProfit / salesDateStartBalance * 100, 2); MonthlyGains.Add(salesMonthDate, salesDateGain); diff --git a/Monitor/Pages/_get/DashboardBottom.cshtml b/Monitor/Pages/_get/DashboardBottom.cshtml index 03cff44..823b6f6 100644 --- a/Monitor/Pages/_get/DashboardBottom.cshtml +++ b/Monitor/Pages/_get/DashboardBottom.cshtml @@ -121,14 +121,7 @@ @{ double totalProfit = 0; - if (Model.PTData.Properties.Shorting) - { - totalProfit = Model.PTData.SellLog.Sum(s => s.Profit * (-1)); - } - else - { - totalProfit = Model.PTData.SellLog.Sum(s => s.Profit); - } + totalProfit = Model.PTData.SellLog.Sum(s => s.Profit); double totalProfitFiat = Math.Round(totalProfit * Model.Summary.MainMarketPrice, 2); double percentGain = Math.Round(totalProfit / Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance * 100, 2); string percentGainText = percentGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%"; @@ -138,53 +131,25 @@ } double todaysProfit = 0; - if (Model.PTData.Properties.Shorting) - { - todaysProfit = Model.PTData.SellLogToday.Sum(s => s.Profit * (-1)); - } - else - { - todaysProfit = Model.PTData.SellLogToday.Sum(s => s.Profit); - } + todaysProfit = Model.PTData.SellLogToday.Sum(s => s.Profit); double todaysStartBalance = Model.PTData.GetSnapshotBalance(Model.DateTimeNow.DateTime); double todaysProfitFiat = Math.Round(todaysProfit * Model.Summary.MainMarketPrice, 2); double todaysPercentGain = Math.Round(todaysProfit / todaysStartBalance * 100, 2); double yesterdaysProfit = 0; - if (Model.PTData.Properties.Shorting) - { - yesterdaysProfit = Model.PTData.SellLogYesterday.Sum(s => s.Profit * (-1)); - } - else - { - yesterdaysProfit = Model.PTData.SellLogYesterday.Sum(s => s.Profit); - } + yesterdaysProfit = Model.PTData.SellLogYesterday.Sum(s => s.Profit); double yesterdaysStartBalance = Model.PTData.GetSnapshotBalance(Model.DateTimeNow.DateTime.AddDays(-1)); double yesterdaysProfitFiat = Math.Round(yesterdaysProfit * Model.Summary.MainMarketPrice, 2); double yesterdaysPercentGain = Math.Round(yesterdaysProfit / yesterdaysStartBalance * 100, 2); double last7DaysProfit = 0; - if (Model.PTData.Properties.Shorting) - { - last7DaysProfit = Model.PTData.SellLogLast7Days.Sum(s => s.Profit * (-1)); - } - else - { - last7DaysProfit = Model.PTData.SellLogLast7Days.Sum(s => s.Profit); - } + last7DaysProfit = Model.PTData.SellLogLast7Days.Sum(s => s.Profit); double last7DaysStartBalance = Model.PTData.GetSnapshotBalance(Model.DateTimeNow.DateTime.AddDays(-7)); double last7DaysProfitFiat = Math.Round(last7DaysProfit * Model.Summary.MainMarketPrice, 2); double last7DaysPercentGain = Math.Round(last7DaysProfit / last7DaysStartBalance * 100, 2); double last30DaysProfit = 0; - if (Model.PTData.Properties.Shorting) - { - last30DaysProfit = Model.PTData.SellLogLast30Days.Sum(s => s.Profit * (-1)); - } - else - { - last30DaysProfit = Model.PTData.SellLogLast30Days.Sum(s => s.Profit); - } + last30DaysProfit = Model.PTData.SellLogLast30Days.Sum(s => s.Profit); double last30DaysStartBalance = Model.PTData.GetSnapshotBalance(Model.DateTimeNow.DateTime.AddDays(-30)); double last30DaysProfitFiat = Math.Round(last30DaysProfit * Model.Summary.MainMarketPrice, 2); double last30DaysPercentGain = Math.Round(last30DaysProfit / last30DaysStartBalance * 100, 2); diff --git a/Monitor/Pages/_get/DashboardBottom.cshtml.cs b/Monitor/Pages/_get/DashboardBottom.cshtml.cs index 5eb3390..0ff5157 100644 --- a/Monitor/Pages/_get/DashboardBottom.cshtml.cs +++ b/Monitor/Pages/_get/DashboardBottom.cshtml.cs @@ -145,10 +145,6 @@ namespace Monitor.Pages } int trades = PTData.SellLog.FindAll(t => t.SoldDate.Date == salesDate).Count; double profit = PTData.SellLog.FindAll(t => t.SoldDate.Date == salesDate).Sum(t => t.Profit); - if (PTData.Properties.Shorting) - { - profit = profit * (-1); - } double profitFiat = Math.Round(profit * Summary.MainMarketPrice, 2); profitPerDayJSON += "{x: new Date('" + salesDate.ToString("yyyy-MM-dd") + "'), y: " + profitFiat.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "}"; tradeDayIndex++; From 7362cd2e92c62f40bc91606f38575282f343895c Mon Sep 17 00:00:00 2001 From: HojouFotytu <36724681+HojouFotytu@users.noreply.github.com> Date: Mon, 30 Aug 2021 13:02:50 +0900 Subject: [PATCH 17/17] Shorting Indicator --- Monitor/Pages/_get/TickerWidgets.cshtml | 17 +++++++++++------ Monitor/Pages/_get/TickerWidgets.cshtml.cs | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Monitor/Pages/_get/TickerWidgets.cshtml b/Monitor/Pages/_get/TickerWidgets.cshtml index 7f2fb03..89d2529 100644 --- a/Monitor/Pages/_get/TickerWidgets.cshtml +++ b/Monitor/Pages/_get/TickerWidgets.cshtml @@ -11,24 +11,29 @@ } // Global setting tool tip - string globalSettingInfoIcon = "Instance: " + Model.PTMagicConfiguration.GeneralSettings.Application.InstanceName + "\" data-template=\"\">"; + string globalIconColor = "text-success"; + string globalSettingInfoIcon = "Instance: " + Model.PTMagicConfiguration.GeneralSettings.Application.InstanceName + "\" data-template=\"\">"; + if (Model.PTData.Properties.Shorting) + { + globalIconColor = "text-danger"; + } // Health indicator DateTime lastRuntime = Model.Summary.LastRuntime; double elapsedSecondsSinceRuntime = DateTime.UtcNow.Subtract(lastRuntime).TotalSeconds; double intervalSeconds = Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes * 60.0; - string iconColor = "text-success"; + string healthIconColor = "text-success"; string ptMagicHealthIcon = "fa-heartbeat"; string ptMagicHealthTooltip = "PT Magic is alive and healthy! Time elapsed since last run: " + Math.Round(elapsedSecondsSinceRuntime / 60, 1) + " mins."; if (elapsedSecondsSinceRuntime > (intervalSeconds * 2)) { ptMagicHealthIcon = "fa-exclamation-triangle"; ptMagicHealthTooltip = "PT Magic seems to have problems, check the logs! Time elapsed since last run: " + Math.Round(elapsedSecondsSinceRuntime / 60, 1) + " mins."; - iconColor = "text-danger"; + healthIconColor = "text-danger"; } } -
+
@Core.Helper.SystemHelper.SplitCamelCase(Model.Summary.CurrentGlobalSetting.SettingName)@Html.Raw(" " + globalSettingInfoIcon)
@@ -37,8 +42,8 @@ SMS: @Html.Raw(activeSingleSettings + " " + singleSettingInfoIcon)
-
- +
+