Multiple Bots
This commit is contained in:
parent
7f2ce392ac
commit
6b0f6c0c27
|
@ -36,8 +36,10 @@ namespace Core.Main.DataObjects.PTMagicData
|
||||||
public bool TestMode { get; set; } = true;
|
public bool TestMode { get; set; } = true;
|
||||||
public bool EnableBetaFeatures { get; set; } = false;
|
public bool EnableBetaFeatures { get; set; } = false;
|
||||||
public string ProfitTrailerLicense { get; set; } = "";
|
public string ProfitTrailerLicense { get; set; } = "";
|
||||||
|
public string ProfitTrailerLicenseXtra { get; set; } = "";
|
||||||
public string ProfitTrailerServerAPIToken { 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 string ProfitTrailerDefaultSettingName { get; set; } = "default";
|
||||||
public int FloodProtectionMinutes { get; set; } = 15;
|
public int FloodProtectionMinutes { get; set; } = 15;
|
||||||
public string Exchange { get; set; }
|
public string Exchange { get; set; }
|
||||||
|
|
|
@ -19,95 +19,122 @@ namespace Core.ProfitTrailer
|
||||||
bool transferCompleted = false;
|
bool transferCompleted = false;
|
||||||
bool transferCanceled = 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<string> 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<string> 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;
|
try
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
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.");
|
|
||||||
}
|
}
|
||||||
|
catch (TimeoutException ex)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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++;
|
retryCount++;
|
||||||
if (retryCount <= maxRetries)
|
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
|
else
|
||||||
{
|
{
|
||||||
transferCanceled = true;
|
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);
|
log.DoLogCritical("Saving Properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex);
|
||||||
transferCanceled = true;
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -144,9 +144,8 @@ namespace Core.ProfitTrailer
|
||||||
|
|
||||||
foreach (string line in pairsLines)
|
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("enabled_pairs", "", StringComparison.InvariantCultureIgnoreCase);
|
||||||
result = result.Replace("#", "");
|
result = result.Replace("#", "");
|
||||||
result = result.Replace("=", "").Trim();
|
result = result.Replace("=", "").Trim();
|
||||||
|
|
|
@ -6,7 +6,7 @@ using Core.Helper;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
|
||||||
[assembly: AssemblyVersion("2.5.11")]
|
[assembly: AssemblyVersion("2.5.12")]
|
||||||
[assembly: AssemblyProduct("PT Magic")]
|
[assembly: AssemblyProduct("PT Magic")]
|
||||||
|
|
||||||
namespace PTMagic
|
namespace PTMagic
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
"Application": {
|
"Application": {
|
||||||
"IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect)
|
"IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect)
|
||||||
"TestMode": false, // If TestMode is active, no properties files will be changed
|
"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
|
"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)
|
"ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings)
|
||||||
"ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings for PT 2.0 and above)
|
"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
|
"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
|
"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
|
"TimezoneOffset": "+0:00", // Your timezone offset from UTC time
|
||||||
|
@ -19,9 +21,9 @@
|
||||||
"Monitor": {
|
"Monitor": {
|
||||||
"IsPasswordProtected": true, // Defines if your monitor will be asking to setup a password on its first start
|
"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
|
"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
|
"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
|
"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
|
"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
|
"RefreshSeconds": 30, // The refresh interval of your monitor main page
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
"Application": {
|
"Application": {
|
||||||
"IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect)
|
"IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect)
|
||||||
"TestMode": false, // If TestMode is active, no properties files will be changed
|
"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
|
"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)
|
"ProfitTrailerMonitorURL": "http://localhost:8081/", // The URL to your profit trailer monitor (needed to change your settings)
|
||||||
"ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings for PT 2.0 and above)
|
"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
|
"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
|
"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
|
"TimezoneOffset": "+0:00", // Your timezone offset from UTC time
|
||||||
|
|
Loading…
Reference in New Issue