2.0.6 Dev (#24)

* Reformat Code (#2)

* Multiple Changes (#13)

* Add "No CMC Key" Log Info

* Larger Tradingview Window

* Update json and NLog to latest version

* Update Remaining Packages

* Include CMC API Key in Settings Web Frontend

* Settings.General are now Collapsible

* Make Settings Analyzer Collapsible

* More Fixup

* Multiple Changes

* Even more fixups

* Add files via upload

* Binance API bad market fix

* Add Git Sync Command

* updated default settings

* Default Settings Fix
This commit is contained in:
HojouFotytu 2018-12-16 06:07:29 +09:00 committed by GitHub
parent 24d5c9d37a
commit 45181915bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 4095 additions and 2816 deletions

3
.gitignore vendored
View File

@ -8,8 +8,9 @@ _[Dd]ata
_[Rr]eleases _[Rr]eleases
_backups _backups
LocalProfitTrailer LocalProfitTrailer
PTMagic/settings.*.json PTMagic/settings.*
Monitor/appsettings.json Monitor/appsettings.json
Monitor/Monitor
Release/ Release/

View File

@ -3,29 +3,35 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Text; using System.Text;
namespace Core.Main.DataObjects.PTMagicData { namespace Core.Main.DataObjects.PTMagicData
{
#region Settings Objects #region Settings Objects
public class GeneralSettingsWrapper { public class GeneralSettingsWrapper
{
public GeneralSettings GeneralSettings { get; set; } public GeneralSettings GeneralSettings { get; set; }
} }
public class AnalyzerSettingsWrapper { public class AnalyzerSettingsWrapper
{
public AnalyzerSettings AnalyzerSettings { get; set; } public AnalyzerSettings AnalyzerSettings { get; set; }
} }
public class SecureSettingsWrapper { public class SecureSettingsWrapper
{
public SecureSettings SecureSettings { get; set; } public SecureSettings SecureSettings { get; set; }
} }
#region GeneralSettings #region GeneralSettings
public class GeneralSettings { public class GeneralSettings
{
public Application Application { get; set; } public Application Application { get; set; }
public Monitor Monitor { get; set; } public Monitor Monitor { get; set; }
public Backup Backup { get; set; } public Backup Backup { get; set; }
public Telegram Telegram { get; set; } public Telegram Telegram { get; set; }
} }
public class Application { public class Application
{
public bool IsEnabled { get; set; } = true; public bool IsEnabled { get; set; } = true;
public bool TestMode { get; set; } = true; public bool TestMode { get; set; } = true;
public bool EnableBetaFeatures { get; set; } = false; public bool EnableBetaFeatures { get; set; } = false;
@ -44,7 +50,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public string CoinMarketCapAPIKey { get; set; } public string CoinMarketCapAPIKey { get; set; }
} }
public class Monitor { public class Monitor
{
private string _rootUrl = "/"; private string _rootUrl = "/";
public bool IsPasswordProtected { get; set; } = true; public bool IsPasswordProtected { get; set; } = true;
@ -65,23 +72,28 @@ namespace Core.Main.DataObjects.PTMagicData {
public string LinkPlatform { get; set; } = "TradingView"; public string LinkPlatform { get; set; } = "TradingView";
public string DefaultDCAMode { get; set; } = "Simple"; public string DefaultDCAMode { get; set; } = "Simple";
public string RootUrl { public string RootUrl
get { {
get
{
if (!_rootUrl.EndsWith("/")) _rootUrl += "/"; if (!_rootUrl.EndsWith("/")) _rootUrl += "/";
return _rootUrl; return _rootUrl;
} }
set { set
{
_rootUrl = value; _rootUrl = value;
} }
} }
} }
public class Backup { public class Backup
{
public bool IsEnabled { get; set; } = true; public bool IsEnabled { get; set; } = true;
public int MaxHours { get; set; } = 48; public int MaxHours { get; set; } = 48;
} }
public class Telegram { public class Telegram
{
public bool IsEnabled { get; set; } = false; public bool IsEnabled { get; set; } = false;
public string BotToken { get; set; } public string BotToken { get; set; }
public Int64 ChatId { get; set; } public Int64 ChatId { get; set; }
@ -90,20 +102,23 @@ namespace Core.Main.DataObjects.PTMagicData {
#endregion #endregion
#region AnalyzerSettings #region AnalyzerSettings
public class AnalyzerSettings { public class AnalyzerSettings
{
public MarketAnalyzer MarketAnalyzer { get; set; } public MarketAnalyzer MarketAnalyzer { get; set; }
public List<GlobalSetting> GlobalSettings { get; set; } public List<GlobalSetting> GlobalSettings { get; set; }
public List<SingleMarketSetting> SingleMarketSettings { get; set; } public List<SingleMarketSetting> SingleMarketSettings { get; set; }
} }
public class MarketAnalyzer { public class MarketAnalyzer
{
public int StoreDataMaxHours { get; set; } public int StoreDataMaxHours { get; set; }
public int IntervalMinutes { get; set; } = 5; public int IntervalMinutes { get; set; } = 5;
public bool ExcludeMainCurrency { get; set; } = true; public bool ExcludeMainCurrency { get; set; } = true;
public List<MarketTrend> MarketTrends { get; set; } public List<MarketTrend> MarketTrends { get; set; }
} }
public class MarketTrend { public class MarketTrend
{
public string Name { get; set; } public string Name { get; set; }
public string Platform { get; set; } = "Exchange"; public string Platform { get; set; } = "Exchange";
@ -130,7 +145,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public bool ExcludeMainCurrency { get; set; } = true; public bool ExcludeMainCurrency { get; set; } = true;
} }
public class GlobalSetting { public class GlobalSetting
{
public string SettingName { get; set; } public string SettingName { get; set; }
public string TriggerConnection { get; set; } = "AND"; public string TriggerConnection { get; set; } = "AND";
public List<Trigger> Triggers { get; set; } = new List<Trigger>(); public List<Trigger> Triggers { get; set; } = new List<Trigger>();
@ -139,7 +155,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public Dictionary<string, object> IndicatorsProperties { get; set; } = new Dictionary<string, object>(); public Dictionary<string, object> IndicatorsProperties { get; set; } = new Dictionary<string, object>();
} }
public class SingleMarketSetting { public class SingleMarketSetting
{
public string SettingName { get; set; } public string SettingName { get; set; }
public string TriggerConnection { get; set; } = "AND"; public string TriggerConnection { get; set; } = "AND";
@ -170,7 +187,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public Dictionary<string, object> IndicatorsProperties { get; set; } = new Dictionary<string, object>(); public Dictionary<string, object> IndicatorsProperties { get; set; } = new Dictionary<string, object>();
} }
public class Trigger { public class Trigger
{
[DefaultValue("")] [DefaultValue("")]
public string MarketTrendName { get; set; } = ""; public string MarketTrendName { get; set; } = "";
@ -193,7 +211,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public int AgeDaysLowerThan { get; set; } = 0; public int AgeDaysLowerThan { get; set; } = 0;
} }
public class OffTrigger { public class OffTrigger
{
[DefaultValue("")] [DefaultValue("")]
public string MarketTrendName { get; set; } = ""; public string MarketTrendName { get; set; } = "";
@ -218,7 +237,8 @@ namespace Core.Main.DataObjects.PTMagicData {
#endregion #endregion
#region SecureSettings #region SecureSettings
public class SecureSettings { public class SecureSettings
{
public string MonitorPassword { get; set; } = ""; public string MonitorPassword { get; set; } = "";
} }
#endregion #endregion
@ -226,7 +246,8 @@ namespace Core.Main.DataObjects.PTMagicData {
#endregion #endregion
#region Market Analyzer Objects #region Market Analyzer Objects
public class Market { public class Market
{
public int Position; public int Position;
public string Name = ""; public string Name = "";
public string Symbol = ""; public string Symbol = "";
@ -236,13 +257,15 @@ namespace Core.Main.DataObjects.PTMagicData {
public double MainCurrencyPriceUSD = 0.0; public double MainCurrencyPriceUSD = 0.0;
} }
public class MarketTick { public class MarketTick
{
public double Volume24h = 0.0; public double Volume24h = 0.0;
public double Price = 0.0; public double Price = 0.0;
public DateTime Time = Constants.confMinDate; public DateTime Time = Constants.confMinDate;
} }
public class MarketTrendChange { public class MarketTrendChange
{
public string MarketTrendName = ""; public string MarketTrendName = "";
public string Market = ""; public string Market = "";
public double LastPrice = 0.0; public double LastPrice = 0.0;
@ -252,7 +275,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public DateTime TrendDateTime = Constants.confMinDate; public DateTime TrendDateTime = Constants.confMinDate;
} }
public class MarketInfo { public class MarketInfo
{
public string Name = ""; public string Name = "";
public DateTime FirstSeen = Constants.confMinDate; public DateTime FirstSeen = Constants.confMinDate;
public DateTime LastSeen = Constants.confMaxDate; public DateTime LastSeen = Constants.confMaxDate;
@ -260,7 +284,8 @@ namespace Core.Main.DataObjects.PTMagicData {
#endregion #endregion
#region Summary Objects #region Summary Objects
public class Summary { public class Summary
{
public string Version { get; set; } = ""; public string Version { get; set; } = "";
public DateTime LastRuntime { get; set; } = Constants.confMinDate; public DateTime LastRuntime { get; set; } = Constants.confMinDate;
public int LastRuntimeSeconds { get; set; } = 0; public int LastRuntimeSeconds { get; set; } = 0;
@ -298,19 +323,22 @@ namespace Core.Main.DataObjects.PTMagicData {
public List<StrategySummary> DCASellStrategies { get; set; } = new List<StrategySummary>(); public List<StrategySummary> DCASellStrategies { get; set; } = new List<StrategySummary>();
} }
public class StrategySummary { public class StrategySummary
{
public string Name { get; set; } = ""; public string Name { get; set; } = "";
public double Value { get; set; } = 0; public double Value { get; set; } = 0;
} }
public class GlobalSettingSummary { public class GlobalSettingSummary
{
public string SettingName { get; set; } public string SettingName { get; set; }
public DateTime SwitchDateTime { get; set; } public DateTime SwitchDateTime { get; set; }
public int ActiveSeconds { get; set; } = 0; public int ActiveSeconds { get; set; } = 0;
public Dictionary<string, MarketTrendChange> MarketTrendChanges { get; set; } = new Dictionary<string, MarketTrendChange>(); public Dictionary<string, MarketTrendChange> MarketTrendChanges { get; set; } = new Dictionary<string, MarketTrendChange>();
} }
public class MarketPairSummary { public class MarketPairSummary
{
public bool IsTradingEnabled { get; set; } = false; public bool IsTradingEnabled { get; set; } = false;
public bool IsSOMActive { get; set; } = false; public bool IsSOMActive { get; set; } = false;
public bool IsDCAEnabled { get; set; } = false; public bool IsDCAEnabled { get; set; } = false;
@ -330,12 +358,14 @@ namespace Core.Main.DataObjects.PTMagicData {
#endregion #endregion
#region Transaction Objects #region Transaction Objects
public class Transaction { public class Transaction
{
public string GUID { get; set; } = ""; public string GUID { get; set; } = "";
public DateTime UTCDateTime { get; set; } = Constants.confMinDate; public DateTime UTCDateTime { get; set; } = Constants.confMinDate;
public double Amount { get; set; } = 0.0; public double Amount { get; set; } = 0.0;
public DateTime GetLocalDateTime(string offset) { public DateTime GetLocalDateTime(string offset)
{
DateTimeOffset result = this.UTCDateTime; DateTimeOffset result = this.UTCDateTime;
// Convert UTC sales time to local offset time // Convert UTC sales time to local offset time
@ -348,14 +378,16 @@ namespace Core.Main.DataObjects.PTMagicData {
#endregion #endregion
#region SingleMarketSettingSummary Objects #region SingleMarketSettingSummary Objects
public class SingleMarketSettingSummary { public class SingleMarketSettingSummary
{
public string Market { get; set; } = ""; public string Market { get; set; } = "";
public DateTime ActivationDateTimeUTC { get; set; } = Constants.confMinDate; public DateTime ActivationDateTimeUTC { get; set; } = Constants.confMinDate;
public SingleMarketSetting SingleMarketSetting { get; set; } = null; public SingleMarketSetting SingleMarketSetting { get; set; } = null;
public TriggerSnapshot TriggerSnapshot { get; set; } = null; public TriggerSnapshot TriggerSnapshot { get; set; } = null;
} }
public class TriggerSnapshot { public class TriggerSnapshot
{
public Dictionary<int, double> RelevantTriggers { get; set; } = new Dictionary<int, double>(); public Dictionary<int, double> RelevantTriggers { get; set; } = new Dictionary<int, double>();
public List<string> MatchedTriggersContent { get; set; } = new List<string>(); public List<string> MatchedTriggersContent { get; set; } = new List<string>();
public double LastPrice { get; set; } = 0; public double LastPrice { get; set; } = 0;
@ -365,14 +397,16 @@ namespace Core.Main.DataObjects.PTMagicData {
#region Profit Trailer JSON Objects #region Profit Trailer JSON Objects
public class PTData { public class PTData
{
public List<sellLogData> SellLogData { get; set; } = new List<sellLogData>(); public List<sellLogData> SellLogData { get; set; } = new List<sellLogData>();
public List<dcaLogData> DCALogData { get; set; } = new List<dcaLogData>(); public List<dcaLogData> DCALogData { get; set; } = new List<dcaLogData>();
public List<dcaLogData> GainLogData { get; set; } = new List<dcaLogData>(); public List<dcaLogData> GainLogData { get; set; } = new List<dcaLogData>();
public List<buyLogData> bbBuyLogData { get; set; } = new List<buyLogData>(); public List<buyLogData> bbBuyLogData { get; set; } = new List<buyLogData>();
} }
public class sellLogData { public class sellLogData
{
public double soldAmount { get; set; } public double soldAmount { get; set; }
public SoldDate soldDate { get; set; } public SoldDate soldDate { get; set; }
public int boughtTimes { get; set; } public int boughtTimes { get; set; }
@ -382,7 +416,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public double currentPrice { get; set; } public double currentPrice { get; set; }
} }
public class SellLogData { public class SellLogData
{
public double SoldAmount { get; set; } public double SoldAmount { get; set; }
public DateTime SoldDate { get; set; } public DateTime SoldDate { get; set; }
public int BoughtTimes { get; set; } public int BoughtTimes { get; set; }
@ -395,30 +430,35 @@ namespace Core.Main.DataObjects.PTMagicData {
public double SoldValue { get; set; } public double SoldValue { get; set; }
} }
public class SoldDate { public class SoldDate
{
public Date date { get; set; } public Date date { get; set; }
public Time time { get; set; } public Time time { get; set; }
} }
public class FirstBoughtDate { public class FirstBoughtDate
{
public Date date { get; set; } public Date date { get; set; }
public Time time { get; set; } public Time time { get; set; }
} }
public class Date { public class Date
{
public int year { get; set; } public int year { get; set; }
public int month { get; set; } public int month { get; set; }
public int day { get; set; } public int day { get; set; }
} }
public class Time { public class Time
{
public int hour { get; set; } public int hour { get; set; }
public int minute { get; set; } public int minute { get; set; }
public int second { get; set; } public int second { get; set; }
public int nano { get; set; } public int nano { get; set; }
} }
public class AverageCalculator { public class AverageCalculator
{
public double totalCost { get; set; } public double totalCost { get; set; }
public double totalAmount { get; set; } public double totalAmount { get; set; }
public double totalAmountWithSold { get; set; } public double totalAmountWithSold { get; set; }
@ -430,7 +470,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public double fee { get; set; } public double fee { get; set; }
} }
public class PTStrategy { public class PTStrategy
{
public string type { get; set; } public string type { get; set; }
public string name { get; set; } public string name { get; set; }
public double entryValue { get; set; } public double entryValue { get; set; }
@ -442,7 +483,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public string positive { get; set; } public string positive { get; set; }
} }
public class dcaLogData { public class dcaLogData
{
public int boughtTimes { get; set; } = 0; public int boughtTimes { get; set; } = 0;
public string market { get; set; } public string market { get; set; }
public string positive { get; set; } public string positive { get; set; }
@ -461,7 +503,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public List<PTStrategy> sellStrategies { get; set; } public List<PTStrategy> sellStrategies { get; set; }
} }
public class Strategy { public class Strategy
{
public string Type { get; set; } public string Type { get; set; }
public string Name { get; set; } public string Name { get; set; }
public double EntryValue { get; set; } public double EntryValue { get; set; }
@ -474,7 +517,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public bool IsTrue { get; set; } public bool IsTrue { get; set; }
} }
public class DCALogData { public class DCALogData
{
public int BoughtTimes { get; set; } public int BoughtTimes { get; set; }
public double CurrentLowBBValue { get; set; } public double CurrentLowBBValue { get; set; }
public double CurrentHighBBValue { get; set; } public double CurrentHighBBValue { get; set; }
@ -497,7 +541,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public List<Strategy> SellStrategies { get; set; } = new List<Strategy>(); public List<Strategy> SellStrategies { get; set; } = new List<Strategy>();
} }
public class buyLogData { public class buyLogData
{
public string market { get; set; } public string market { get; set; }
public string positive { get; set; } public string positive { get; set; }
public double BBLow { get; set; } public double BBLow { get; set; }
@ -512,7 +557,8 @@ namespace Core.Main.DataObjects.PTMagicData {
public List<PTStrategy> buyStrategies { get; set; } public List<PTStrategy> buyStrategies { get; set; }
} }
public class BuyLogData { public class BuyLogData
{
public double CurrentLowBBValue { get; set; } public double CurrentLowBBValue { get; set; }
public double CurrentHighBBValue { get; set; } public double CurrentHighBBValue { get; set; }
public double BBTrigger { get; set; } public double BBTrigger { get; set; }

View File

@ -8,9 +8,11 @@ using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json; using Newtonsoft.Json;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
namespace Core.Main.DataObjects { namespace Core.Main.DataObjects
{
public class ProfitTrailerData { public class ProfitTrailerData
{
private List<SellLogData> _sellLog = new List<SellLogData>(); private List<SellLogData> _sellLog = new List<SellLogData>();
private List<DCALogData> _dcaLog = new List<DCALogData>(); private List<DCALogData> _dcaLog = new List<DCALogData>();
private List<BuyLogData> _buyLog = new List<BuyLogData>(); private List<BuyLogData> _buyLog = new List<BuyLogData>();
@ -19,7 +21,8 @@ namespace Core.Main.DataObjects {
private TransactionData _transactionData = null; private TransactionData _transactionData = null;
private DateTimeOffset _dateTimeNow = Constants.confMinDate; private DateTimeOffset _dateTimeNow = Constants.confMinDate;
public ProfitTrailerData(string ptmBasePath, PTMagicConfiguration systemConfiguration) { public ProfitTrailerData(string ptmBasePath, PTMagicConfiguration systemConfiguration)
{
_ptmBasePath = ptmBasePath; _ptmBasePath = ptmBasePath;
_systemConfiguration = systemConfiguration; _systemConfiguration = systemConfiguration;
@ -38,15 +41,18 @@ namespace Core.Main.DataObjects {
} }
PTData rawPTData = JsonConvert.DeserializeObject<PTData>(File.ReadAllText(ptDataFilePath)); PTData rawPTData = JsonConvert.DeserializeObject<PTData>(File.ReadAllText(ptDataFilePath));
if (rawPTData.SellLogData != null) { if (rawPTData.SellLogData != null)
{
this.BuildSellLogData(rawPTData.SellLogData, _systemConfiguration); this.BuildSellLogData(rawPTData.SellLogData, _systemConfiguration);
} }
if (rawPTData.bbBuyLogData != null) { if (rawPTData.bbBuyLogData != null)
{
this.BuildBuyLogData(rawPTData.bbBuyLogData, _systemConfiguration); this.BuildBuyLogData(rawPTData.bbBuyLogData, _systemConfiguration);
} }
if (rawPTData.DCALogData != null) { if (rawPTData.DCALogData != null)
{
this.BuildDCALogData(rawPTData.DCALogData, rawPTData.GainLogData, _systemConfiguration); this.BuildDCALogData(rawPTData.DCALogData, rawPTData.GainLogData, _systemConfiguration);
} }
@ -55,54 +61,70 @@ namespace Core.Main.DataObjects {
_dateTimeNow = DateTimeOffset.UtcNow.ToOffset(offsetTimeSpan); _dateTimeNow = DateTimeOffset.UtcNow.ToOffset(offsetTimeSpan);
} }
public List<SellLogData> SellLog { public List<SellLogData> SellLog
get { {
get
{
return _sellLog; return _sellLog;
} }
} }
public List<SellLogData> SellLogToday { public List<SellLogData> SellLogToday
get { {
get
{
return _sellLog.FindAll(sl => sl.SoldDate.Date == _dateTimeNow.DateTime.Date); return _sellLog.FindAll(sl => sl.SoldDate.Date == _dateTimeNow.DateTime.Date);
} }
} }
public List<SellLogData> SellLogYesterday { public List<SellLogData> SellLogYesterday
get { {
get
{
return _sellLog.FindAll(sl => sl.SoldDate.Date == _dateTimeNow.DateTime.AddDays(-1).Date); return _sellLog.FindAll(sl => sl.SoldDate.Date == _dateTimeNow.DateTime.AddDays(-1).Date);
} }
} }
public List<SellLogData> SellLogLast7Days { public List<SellLogData> SellLogLast7Days
get { {
get
{
return _sellLog.FindAll(sl => sl.SoldDate.Date >= _dateTimeNow.DateTime.AddDays(-7).Date); return _sellLog.FindAll(sl => sl.SoldDate.Date >= _dateTimeNow.DateTime.AddDays(-7).Date);
} }
} }
public List<DCALogData> DCALog { public List<DCALogData> DCALog
get { {
get
{
return _dcaLog; return _dcaLog;
} }
} }
public List<BuyLogData> BuyLog { public List<BuyLogData> BuyLog
get { {
get
{
return _buyLog; return _buyLog;
} }
} }
public TransactionData TransactionData { public TransactionData TransactionData
get { {
get
{
if (_transactionData == null) _transactionData = new TransactionData(_ptmBasePath); if (_transactionData == null) _transactionData = new TransactionData(_ptmBasePath);
return _transactionData; return _transactionData;
} }
} }
public double GetCurrentBalance() { public double GetCurrentBalance()
{
return this.GetSnapshotBalance(DateTime.Now.ToUniversalTime()); return this.GetSnapshotBalance(DateTime.Now.ToUniversalTime());
} }
public double GetSnapshotBalance(DateTime snapshotDateTime) { public double GetSnapshotBalance(DateTime snapshotDateTime)
{
double result = _systemConfiguration.GeneralSettings.Application.StartBalance; double result = _systemConfiguration.GeneralSettings.Application.StartBalance;
result += this.SellLog.FindAll(sl => sl.SoldDate.Date < snapshotDateTime.Date).Sum(sl => sl.Profit); result += this.SellLog.FindAll(sl => sl.SoldDate.Date < snapshotDateTime.Date).Sum(sl => sl.Profit);
@ -111,8 +133,10 @@ namespace Core.Main.DataObjects {
return result; return result;
} }
private void BuildSellLogData(List<sellLogData> rawSellLogData, PTMagicConfiguration systemConfiguration) { private void BuildSellLogData(List<sellLogData> rawSellLogData, PTMagicConfiguration systemConfiguration)
foreach (sellLogData rsld in rawSellLogData) { {
foreach (sellLogData rsld in rawSellLogData)
{
SellLogData sellLogData = new SellLogData(); SellLogData sellLogData = new SellLogData();
sellLogData.SoldAmount = rsld.soldAmount; sellLogData.SoldAmount = rsld.soldAmount;
sellLogData.BoughtTimes = rsld.boughtTimes; sellLogData.BoughtTimes = rsld.boughtTimes;
@ -140,8 +164,10 @@ namespace Core.Main.DataObjects {
} }
} }
private void BuildDCALogData(List<dcaLogData> rawDCALogData, List<dcaLogData> rawPairsLogData, PTMagicConfiguration systemConfiguration) { private void BuildDCALogData(List<dcaLogData> rawDCALogData, List<dcaLogData> rawPairsLogData, PTMagicConfiguration systemConfiguration)
foreach (dcaLogData rdld in rawDCALogData) { {
foreach (dcaLogData rdld in rawDCALogData)
{
DCALogData dcaLogData = new DCALogData(); DCALogData dcaLogData = new DCALogData();
dcaLogData.Amount = rdld.averageCalculator.totalAmount; dcaLogData.Amount = rdld.averageCalculator.totalAmount;
dcaLogData.BoughtTimes = rdld.boughtTimes; dcaLogData.BoughtTimes = rdld.boughtTimes;
@ -161,12 +187,17 @@ namespace Core.Main.DataObjects {
dcaLogData.SellStrategy = rdld.sellStrategy; dcaLogData.SellStrategy = rdld.sellStrategy;
if (dcaLogData.SellStrategy == null) dcaLogData.SellStrategy = ""; if (dcaLogData.SellStrategy == null) dcaLogData.SellStrategy = "";
if (rdld.positive != null) { if (rdld.positive != null)
{
dcaLogData.IsTrailing = rdld.positive.IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; dcaLogData.IsTrailing = rdld.positive.IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1;
dcaLogData.IsTrue = rdld.positive.IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; dcaLogData.IsTrue = rdld.positive.IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1;
} else { }
if (rdld.buyStrategies != null) { else
foreach (PTStrategy bs in rdld.buyStrategies) { {
if (rdld.buyStrategies != null)
{
foreach (PTStrategy bs in rdld.buyStrategies)
{
Strategy buyStrategy = new Strategy(); Strategy buyStrategy = new Strategy();
buyStrategy.Type = bs.type; buyStrategy.Type = bs.type;
buyStrategy.Name = bs.name; buyStrategy.Name = bs.name;
@ -183,8 +214,10 @@ namespace Core.Main.DataObjects {
} }
} }
if (rdld.sellStrategies != null) { if (rdld.sellStrategies != null)
foreach (PTStrategy ss in rdld.sellStrategies) { {
foreach (PTStrategy ss in rdld.sellStrategies)
{
Strategy sellStrategy = new Strategy(); Strategy sellStrategy = new Strategy();
sellStrategy.Type = ss.type; sellStrategy.Type = ss.type;
sellStrategy.Name = ss.name; sellStrategy.Name = ss.name;
@ -204,7 +237,8 @@ namespace Core.Main.DataObjects {
// Profit Trailer bought times are saved in UTC // Profit Trailer bought times are saved in UTC
if (rdld.averageCalculator.firstBoughtDate != null) { if (rdld.averageCalculator.firstBoughtDate != null)
{
DateTimeOffset ptFirstBoughtDate = DateTimeOffset.Parse(rdld.averageCalculator.firstBoughtDate.date.year.ToString() + "-" + rdld.averageCalculator.firstBoughtDate.date.month.ToString("00") + "-" + rdld.averageCalculator.firstBoughtDate.date.day.ToString("00") + "T" + rdld.averageCalculator.firstBoughtDate.time.hour.ToString("00") + ":" + rdld.averageCalculator.firstBoughtDate.time.minute.ToString("00") + ":" + rdld.averageCalculator.firstBoughtDate.time.second.ToString("00"), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); DateTimeOffset ptFirstBoughtDate = DateTimeOffset.Parse(rdld.averageCalculator.firstBoughtDate.date.year.ToString() + "-" + rdld.averageCalculator.firstBoughtDate.date.month.ToString("00") + "-" + rdld.averageCalculator.firstBoughtDate.date.day.ToString("00") + "T" + rdld.averageCalculator.firstBoughtDate.time.hour.ToString("00") + ":" + rdld.averageCalculator.firstBoughtDate.time.minute.ToString("00") + ":" + rdld.averageCalculator.firstBoughtDate.time.second.ToString("00"), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
// Convert UTC bought time to local offset time // Convert UTC bought time to local offset time
@ -212,14 +246,17 @@ namespace Core.Main.DataObjects {
ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(offsetTimeSpan); ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(offsetTimeSpan);
dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime; dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime;
} else { }
else
{
dcaLogData.FirstBoughtDate = Constants.confMinDate; dcaLogData.FirstBoughtDate = Constants.confMinDate;
} }
_dcaLog.Add(dcaLogData); _dcaLog.Add(dcaLogData);
} }
foreach (dcaLogData rpld in rawPairsLogData) { foreach (dcaLogData rpld in rawPairsLogData)
{
DCALogData dcaLogData = new DCALogData(); DCALogData dcaLogData = new DCALogData();
dcaLogData.Amount = rpld.averageCalculator.totalAmount; dcaLogData.Amount = rpld.averageCalculator.totalAmount;
dcaLogData.BoughtTimes = 0; dcaLogData.BoughtTimes = 0;
@ -237,8 +274,10 @@ namespace Core.Main.DataObjects {
if (dcaLogData.SellStrategy == null) dcaLogData.SellStrategy = ""; if (dcaLogData.SellStrategy == null) dcaLogData.SellStrategy = "";
dcaLogData.IsTrailing = false; dcaLogData.IsTrailing = false;
if (rpld.sellStrategies != null) { if (rpld.sellStrategies != null)
foreach (PTStrategy ss in rpld.sellStrategies) { {
foreach (PTStrategy ss in rpld.sellStrategies)
{
Strategy sellStrategy = new Strategy(); Strategy sellStrategy = new Strategy();
sellStrategy.Type = ss.type; sellStrategy.Type = ss.type;
sellStrategy.Name = ss.name; sellStrategy.Name = ss.name;
@ -256,7 +295,8 @@ namespace Core.Main.DataObjects {
} }
// Profit Trailer bought times are saved in UTC // Profit Trailer bought times are saved in UTC
if (rpld.averageCalculator.firstBoughtDate != null) { if (rpld.averageCalculator.firstBoughtDate != null)
{
DateTimeOffset ptFirstBoughtDate = DateTimeOffset.Parse(rpld.averageCalculator.firstBoughtDate.date.year.ToString() + "-" + rpld.averageCalculator.firstBoughtDate.date.month.ToString("00") + "-" + rpld.averageCalculator.firstBoughtDate.date.day.ToString("00") + "T" + rpld.averageCalculator.firstBoughtDate.time.hour.ToString("00") + ":" + rpld.averageCalculator.firstBoughtDate.time.minute.ToString("00") + ":" + rpld.averageCalculator.firstBoughtDate.time.second.ToString("00"), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); DateTimeOffset ptFirstBoughtDate = DateTimeOffset.Parse(rpld.averageCalculator.firstBoughtDate.date.year.ToString() + "-" + rpld.averageCalculator.firstBoughtDate.date.month.ToString("00") + "-" + rpld.averageCalculator.firstBoughtDate.date.day.ToString("00") + "T" + rpld.averageCalculator.firstBoughtDate.time.hour.ToString("00") + ":" + rpld.averageCalculator.firstBoughtDate.time.minute.ToString("00") + ":" + rpld.averageCalculator.firstBoughtDate.time.second.ToString("00"), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
// Convert UTC bought time to local offset time // Convert UTC bought time to local offset time
@ -264,7 +304,9 @@ namespace Core.Main.DataObjects {
ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(offsetTimeSpan); ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(offsetTimeSpan);
dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime; dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime;
} else { }
else
{
dcaLogData.FirstBoughtDate = Constants.confMinDate; dcaLogData.FirstBoughtDate = Constants.confMinDate;
} }
@ -272,8 +314,10 @@ namespace Core.Main.DataObjects {
} }
} }
private void BuildBuyLogData(List<buyLogData> rawBuyLogData, PTMagicConfiguration systemConfiguration) { private void BuildBuyLogData(List<buyLogData> rawBuyLogData, PTMagicConfiguration systemConfiguration)
foreach (buyLogData rbld in rawBuyLogData) { {
foreach (buyLogData rbld in rawBuyLogData)
{
BuyLogData buyLogData = new BuyLogData(); BuyLogData buyLogData = new BuyLogData();
buyLogData.Market = rbld.market; buyLogData.Market = rbld.market;
buyLogData.ProfitPercent = rbld.profit; buyLogData.ProfitPercent = rbld.profit;
@ -288,12 +332,17 @@ namespace Core.Main.DataObjects {
if (buyLogData.BuyStrategy == null) buyLogData.BuyStrategy = ""; if (buyLogData.BuyStrategy == null) buyLogData.BuyStrategy = "";
if (rbld.positive != null) { if (rbld.positive != null)
{
buyLogData.IsTrailing = rbld.positive.IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; buyLogData.IsTrailing = rbld.positive.IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1;
buyLogData.IsTrue = rbld.positive.IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; buyLogData.IsTrue = rbld.positive.IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1;
} else { }
if (rbld.buyStrategies != null) { else
foreach (PTStrategy bs in rbld.buyStrategies) { {
if (rbld.buyStrategies != null)
{
foreach (PTStrategy bs in rbld.buyStrategies)
{
Strategy buyStrategy = new Strategy(); Strategy buyStrategy = new Strategy();
buyStrategy.Type = bs.type; buyStrategy.Type = bs.type;
buyStrategy.Name = bs.name; buyStrategy.Name = bs.name;

View File

@ -8,25 +8,32 @@ using Newtonsoft.Json;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using Core.Helper; using Core.Helper;
namespace Core.Main.DataObjects { namespace Core.Main.DataObjects
{
public class TransactionData { public class TransactionData
{
private List<Transaction> _transactions = new List<Transaction>(); private List<Transaction> _transactions = new List<Transaction>();
public TransactionData(string basePath) { public TransactionData(string basePath)
{
string transactionsFilePath = basePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar + "Transactions.json"; string transactionsFilePath = basePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar + "Transactions.json";
if (File.Exists(transactionsFilePath)) { if (File.Exists(transactionsFilePath))
{
this._transactions = JsonConvert.DeserializeObject<List<Transaction>>(File.ReadAllText(transactionsFilePath)); this._transactions = JsonConvert.DeserializeObject<List<Transaction>>(File.ReadAllText(transactionsFilePath));
} }
} }
public List<Transaction> Transactions { public List<Transaction> Transactions
get { {
get
{
return _transactions; return _transactions;
} }
} }
public void SaveTransactions(string basePath) { public void SaveTransactions(string basePath)
{
FileHelper.WriteTextToFile(basePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar, "Transactions.json", JsonConvert.SerializeObject(this.Transactions)); FileHelper.WriteTextToFile(basePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar, "Transactions.json", JsonConvert.SerializeObject(this.Transactions));
} }
} }

View File

@ -9,10 +9,13 @@ using System.Net.Http;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Core.Helper { namespace Core.Helper
public static class CertificateHelper { {
public static class CertificateHelper
{
public static bool AllwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) { public static bool AllwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors)
{
return true; return true;
} }
} }

View File

@ -7,29 +7,39 @@ using System.Security.Cryptography;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Configuration; using System.Configuration;
namespace Core.Helper { namespace Core.Helper
public class EncryptionHelper { {
public class EncryptionHelper
{
#region Properties #region Properties
public static string CryptoMainSaltValue { public static string CryptoMainSaltValue
get { {
get
{
return "b3+Pz.~L<R 8NH-p=Ze<smbpb*]dP,%d9d{P{DC)R$xf]s|6UC-d)X[y_kDR^EsL"; return "b3+Pz.~L<R 8NH-p=Ze<smbpb*]dP,%d9d{P{DC)R$xf]s|6UC-d)X[y_kDR^EsL";
} }
} }
public static string CryptoSaltValue { public static string CryptoSaltValue
get { {
get
{
return "/-T:_~Z|j~0%@~|?7,L~]:us9-=VO[.0V[nZDYTjnUeHcka#hdQ{U^YHv:0sJlfk"; return "/-T:_~Z|j~0%@~|?7,L~]:us9-=VO[.0V[nZDYTjnUeHcka#hdQ{U^YHv:0sJlfk";
} }
} }
public static string CryptoInitVector { public static string CryptoInitVector
get { {
get
{
return "qWEE:ADg)}6b;V{B"; return "qWEE:ADg)}6b;V{B";
} }
} }
public static string CryptoPassPhrase { public static string CryptoPassPhrase
get { {
get
{
return "KUBD`o.]*#CCL n9m}tZN4B4~>2EK>((/xnTbWdTo:/5_$hq8ja8yOq% j}M6zTM"; return "KUBD`o.]*#CCL n9m}tZN4B4~>2EK>((/xnTbWdTo:/5_$hq8ja8yOq% j}M6zTM";
} }
} }
@ -39,7 +49,8 @@ namespace Core.Helper {
#region Methoden #region Methoden
#region Passwortverschlüsselung #region Passwortverschlüsselung
public static string CreateHash(string password, string randomSalt) { public static string CreateHash(string password, string randomSalt)
{
// Generate a random salt // Generate a random salt
byte[] salt = Encoding.UTF8.GetBytes(EncryptionHelper.CryptoMainSaltValue + randomSalt); byte[] salt = Encoding.UTF8.GetBytes(EncryptionHelper.CryptoMainSaltValue + randomSalt);
byte[] hash = PBKDF2(password, salt, 64000, 24); byte[] hash = PBKDF2(password, salt, 64000, 24);
@ -47,19 +58,23 @@ namespace Core.Helper {
return Convert.ToBase64String(hash); return Convert.ToBase64String(hash);
} }
public static bool SlowEquals(string aHash, string bHash) { public static bool SlowEquals(string aHash, string bHash)
{
byte[] a = Encoding.UTF8.GetBytes(aHash); byte[] a = Encoding.UTF8.GetBytes(aHash);
byte[] b = Encoding.UTF8.GetBytes(bHash); byte[] b = Encoding.UTF8.GetBytes(bHash);
uint diff = (uint)a.Length ^ (uint)b.Length; uint diff = (uint)a.Length ^ (uint)b.Length;
for (int i = 0; i < a.Length && i < b.Length; i++) { for (int i = 0; i < a.Length && i < b.Length; i++)
{
diff |= (uint)(a[i] ^ b[i]); diff |= (uint)(a[i] ^ b[i]);
} }
return diff == 0; return diff == 0;
} }
private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes) { private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt)) { {
using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt))
{
pbkdf2.IterationCount = iterations; pbkdf2.IterationCount = iterations;
return pbkdf2.GetBytes(outputBytes); return pbkdf2.GetBytes(outputBytes);
} }
@ -69,19 +84,23 @@ namespace Core.Helper {
#endregion #endregion
#region Standardverschlüsselung #region Standardverschlüsselung
public static string Encrypt(string plainText) { public static string Encrypt(string plainText)
{
return Encrypt(plainText, EncryptionHelper.CryptoPassPhrase, EncryptionHelper.CryptoSaltValue, "SHA512", 2, EncryptionHelper.CryptoInitVector, 256); return Encrypt(plainText, EncryptionHelper.CryptoPassPhrase, EncryptionHelper.CryptoSaltValue, "SHA512", 2, EncryptionHelper.CryptoInitVector, 256);
} }
public static string Decrypt(string cipherText) { public static string Decrypt(string cipherText)
{
return Decrypt(cipherText, EncryptionHelper.CryptoPassPhrase, EncryptionHelper.CryptoSaltValue, "SHA512", 2, EncryptionHelper.CryptoInitVector, 256, true); return Decrypt(cipherText, EncryptionHelper.CryptoPassPhrase, EncryptionHelper.CryptoSaltValue, "SHA512", 2, EncryptionHelper.CryptoInitVector, 256, true);
} }
public static string Encrypt(string plainText, string passPhrase) { public static string Encrypt(string plainText, string passPhrase)
{
return Encrypt(plainText, passPhrase, EncryptionHelper.CryptoSaltValue, "SHA512", 2, EncryptionHelper.CryptoInitVector, 256); return Encrypt(plainText, passPhrase, EncryptionHelper.CryptoSaltValue, "SHA512", 2, EncryptionHelper.CryptoInitVector, 256);
} }
public static string Decrypt(string cipherText, string passPhrase) { public static string Decrypt(string cipherText, string passPhrase)
{
return Decrypt(cipherText, passPhrase, EncryptionHelper.CryptoSaltValue, "SHA512", 2, EncryptionHelper.CryptoInitVector, 256, true); return Decrypt(cipherText, passPhrase, EncryptionHelper.CryptoSaltValue, "SHA512", 2, EncryptionHelper.CryptoInitVector, 256, true);
} }
@ -129,7 +148,8 @@ namespace Core.Helper {
string hashAlgorithm, string hashAlgorithm,
int passwordIterations, int passwordIterations,
string initVector, string initVector,
int keySize) { int keySize)
{
// Convert strings into byte arrays. // Convert strings into byte arrays.
byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector); byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector);
byte[] saltValueBytes = Encoding.UTF8.GetBytes(saltValue); byte[] saltValueBytes = Encoding.UTF8.GetBytes(saltValue);
@ -235,8 +255,10 @@ namespace Core.Helper {
int passwordIterations, int passwordIterations,
string initVector, string initVector,
int keySize, int keySize,
bool doDecrypt) { bool doDecrypt)
if (doDecrypt) { {
if (doDecrypt)
{
// Convert strings defining encryption key characteristics into byte // Convert strings defining encryption key characteristics into byte
// arrays. // arrays.
byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector); byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector);
@ -292,7 +314,9 @@ namespace Core.Helper {
// Return decrypted string. // Return decrypted string.
return plainText; return plainText;
} else { }
else
{
return ""; return "";
} }
} }

View File

@ -2,72 +2,91 @@
using System.IO; using System.IO;
using Core.Main; using Core.Main;
namespace Core.Helper { namespace Core.Helper
public static class FileHelper { {
public static void WriteTextToFile(string folderPath, string fileName, string text) { public static class FileHelper
{
public static void WriteTextToFile(string folderPath, string fileName, string text)
{
FileHelper.WriteTextToFile(folderPath, fileName, text, Constants.confMinDate, Constants.confMinDate); FileHelper.WriteTextToFile(folderPath, fileName, text, Constants.confMinDate, Constants.confMinDate);
} }
public static void WriteTextToFile(string folderPath, string fileName, string text, DateTime creationTime, DateTime lastWriteTime) { public static void WriteTextToFile(string folderPath, string fileName, string text, DateTime creationTime, DateTime lastWriteTime)
if (!Directory.Exists(folderPath)) { {
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath); Directory.CreateDirectory(folderPath);
} }
File.WriteAllText(folderPath + fileName, text); File.WriteAllText(folderPath + fileName, text);
if (creationTime != Constants.confMinDate) { if (creationTime != Constants.confMinDate)
{
File.SetCreationTimeUtc(folderPath + fileName, creationTime); File.SetCreationTimeUtc(folderPath + fileName, creationTime);
} }
if (lastWriteTime != Constants.confMinDate) { if (lastWriteTime != Constants.confMinDate)
{
File.SetLastWriteTimeUtc(folderPath + fileName, lastWriteTime); File.SetLastWriteTimeUtc(folderPath + fileName, lastWriteTime);
} }
} }
public static void CreateBackup(string filePath, string backupFolder) { public static void CreateBackup(string filePath, string backupFolder)
{
FileHelper.CreateBackup(filePath, backupFolder, ""); FileHelper.CreateBackup(filePath, backupFolder, "");
} }
public static void CreateBackup(string filePath, string backupFolder, string backupFileName) { public static void CreateBackup(string filePath, string backupFolder, string backupFileName)
if (!Directory.Exists(backupFolder)) { {
if (!Directory.Exists(backupFolder))
{
Directory.CreateDirectory(backupFolder); Directory.CreateDirectory(backupFolder);
} }
FileInfo file = new FileInfo(filePath); FileInfo file = new FileInfo(filePath);
string backupFilePath = backupFolder + DateTime.Now.ToString("yyyy-MM-dd_HH.mm.ss") + "_" + file.Name; string backupFilePath = backupFolder + DateTime.Now.ToString("yyyy-MM-dd_HH.mm.ss") + "_" + file.Name;
if (!backupFileName.Equals("")) { if (!backupFileName.Equals(""))
{
backupFilePath = backupFolder + backupFileName; backupFilePath = backupFolder + backupFileName;
} }
File.Copy(file.FullName, backupFilePath, true); File.Copy(file.FullName, backupFilePath, true);
} }
public static void CleanupFilesMinutes(string folderPath, int maxMinutes) { public static void CleanupFilesMinutes(string folderPath, int maxMinutes)
if (!Directory.Exists(folderPath)) { {
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath); Directory.CreateDirectory(folderPath);
} }
DirectoryInfo folder = new DirectoryInfo(folderPath); DirectoryInfo folder = new DirectoryInfo(folderPath);
foreach (FileInfo file in folder.GetFiles()) { foreach (FileInfo file in folder.GetFiles())
{
DateTime maxAge = DateTime.Now.AddMinutes(-maxMinutes); DateTime maxAge = DateTime.Now.AddMinutes(-maxMinutes);
if (file.LastWriteTime < maxAge) { if (file.LastWriteTime < maxAge)
{
File.Delete(file.FullName); File.Delete(file.FullName);
} }
} }
} }
public static void CleanupFiles(string folderPath, int maxHours) { public static void CleanupFiles(string folderPath, int maxHours)
if (!Directory.Exists(folderPath)) { {
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath); Directory.CreateDirectory(folderPath);
} }
DirectoryInfo folder = new DirectoryInfo(folderPath); DirectoryInfo folder = new DirectoryInfo(folderPath);
foreach (FileInfo file in folder.GetFiles()) { foreach (FileInfo file in folder.GetFiles())
{
DateTime maxAge = DateTime.Now.AddHours(-(maxHours + 1)); DateTime maxAge = DateTime.Now.AddHours(-(maxHours + 1));
if (file.LastWriteTime < maxAge) { if (file.LastWriteTime < maxAge)
{
File.Delete(file.FullName); File.Delete(file.FullName);
} }
} }

View File

@ -3,31 +3,39 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging; using NLog.Extensions.Logging;
namespace Core.Helper { namespace Core.Helper
public class LogHelper { {
public class LogHelper
{
private readonly ILogger<LogHelper> log; private readonly ILogger<LogHelper> log;
public LogHelper(ILogger<LogHelper> logger) { public LogHelper(ILogger<LogHelper> logger)
{
log = logger; log = logger;
} }
public void DoLogInfo(string message) { public void DoLogInfo(string message)
{
if (log.IsEnabled(LogLevel.Information)) log.LogInformation(message); if (log.IsEnabled(LogLevel.Information)) log.LogInformation(message);
} }
public void DoLogWarn(string message) { public void DoLogWarn(string message)
{
if (log.IsEnabled(LogLevel.Warning)) log.LogWarning(message); if (log.IsEnabled(LogLevel.Warning)) log.LogWarning(message);
} }
public void DoLogError(string message) { public void DoLogError(string message)
{
if (log.IsEnabled(LogLevel.Error)) log.LogError(message); if (log.IsEnabled(LogLevel.Error)) log.LogError(message);
} }
public void DoLogCritical(string message, System.Exception ex) { public void DoLogCritical(string message, System.Exception ex)
{
if (log.IsEnabled(LogLevel.Critical)) log.LogCritical(ex, message); if (log.IsEnabled(LogLevel.Critical)) log.LogCritical(ex, message);
} }
public void DoLogDebug(string message) { public void DoLogDebug(string message)
{
if (log.IsEnabled(LogLevel.Debug)) log.LogDebug(message); if (log.IsEnabled(LogLevel.Debug)) log.LogDebug(message);
} }
} }

View File

@ -3,14 +3,18 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging; using NLog.Extensions.Logging;
namespace Core.Helper { namespace Core.Helper
public static class ServiceHelper { {
public static class ServiceHelper
{
public static IServiceProvider BuildLoggerService() { public static IServiceProvider BuildLoggerService()
{
return ServiceHelper.BuildLoggerService(""); return ServiceHelper.BuildLoggerService("");
} }
public static IServiceProvider BuildLoggerService(string basePath) { public static IServiceProvider BuildLoggerService(string basePath)
{
ServiceCollection services = new ServiceCollection(); ServiceCollection services = new ServiceCollection();
services.AddTransient<LogHelper>(); services.AddTransient<LogHelper>();

View File

@ -11,10 +11,13 @@ using System.Text;
using System.Globalization; using System.Globalization;
using Core.Main; using Core.Main;
namespace Core.Helper { namespace Core.Helper
{
public class SystemHelper { public class SystemHelper
private static bool AllwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) { {
private static bool AllwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors)
{
return true; return true;
} }
@ -23,23 +26,32 @@ namespace Core.Helper {
/// </summary> /// </summary>
/// <param name="s">The string to check.</param> /// <param name="s">The string to check.</param>
/// <returns>True, if the string is numeric.</returns> /// <returns>True, if the string is numeric.</returns>
public static bool IsNumeric(string s) { public static bool IsNumeric(string s)
try { {
try
{
Int32.Parse(s); Int32.Parse(s);
} catch { }
catch
{
return false; return false;
} }
return true; return true;
} }
public static bool IsInteger(double d) { public static bool IsInteger(double d)
{
return d % 1 == 0; return d % 1 == 0;
} }
public static bool IsBoolean(string s) { public static bool IsBoolean(string s)
try { {
try
{
Boolean.Parse(s); Boolean.Parse(s);
} catch { }
catch
{
return false; return false;
} }
return true; return true;
@ -50,19 +62,27 @@ namespace Core.Helper {
/// </summary> /// </summary>
/// <param name="s">The string to check.</param> /// <param name="s">The string to check.</param>
/// <returns>True, if the string is a double value.</returns> /// <returns>True, if the string is a double value.</returns>
public static bool IsDouble(string s) { public static bool IsDouble(string s)
try { {
try
{
Double.Parse(s); Double.Parse(s);
} catch { }
catch
{
return false; return false;
} }
return true; return true;
} }
public static bool IsDouble(string s, string culture) { public static bool IsDouble(string s, string culture)
try { {
try
{
Double.Parse(s, new CultureInfo(culture)); Double.Parse(s, new CultureInfo(culture));
} catch { }
catch
{
return false; return false;
} }
return true; return true;
@ -73,10 +93,14 @@ namespace Core.Helper {
/// </summary> /// </summary>
/// <param name="s">The string to check.</param> /// <param name="s">The string to check.</param>
/// <returns>True, if the string is a DateTime value.</returns> /// <returns>True, if the string is a DateTime value.</returns>
public static bool IsDateTime(string s) { public static bool IsDateTime(string s)
try { {
try
{
DateTime.Parse(s); DateTime.Parse(s);
} catch { }
catch
{
return false; return false;
} }
return true; return true;
@ -88,12 +112,15 @@ namespace Core.Helper {
/// <param name="text">Zu konvertierender Text.</param> /// <param name="text">Zu konvertierender Text.</param>
/// <param name="defaultValue">Der Vorgabewert für den Fall, dass keine gültige Zahl eingegeben wurde.</param> /// <param name="defaultValue">Der Vorgabewert für den Fall, dass keine gültige Zahl eingegeben wurde.</param>
/// <returns>Den Text als Integer. Wenn die Konvertierung fehlschlägt, dann wird der Defaultwert zurückgegeben.</returns> /// <returns>Den Text als Integer. Wenn die Konvertierung fehlschlägt, dann wird der Defaultwert zurückgegeben.</returns>
public static int TextToInteger(string text, int defaultValue) { public static int TextToInteger(string text, int defaultValue)
{
int result = defaultValue; int result = defaultValue;
try { try
{
string localText = text.Replace(".", ""); string localText = text.Replace(".", "");
result = Convert.ToInt32(localText.Trim()); result = Convert.ToInt32(localText.Trim());
} catch { } }
catch { }
return result; return result;
} }
@ -104,23 +131,30 @@ namespace Core.Helper {
/// <param name="text">Zu konvertierender Text.</param> /// <param name="text">Zu konvertierender Text.</param>
/// <param name="defaultValue">Der Vorgabewert für den Fall, dass keine gültige Zahl eingegeben wurde.</param> /// <param name="defaultValue">Der Vorgabewert für den Fall, dass keine gültige Zahl eingegeben wurde.</param>
/// <returns>Den Text als Integer64. Wenn die Konvertierung fehlschlägt, dann wird der Defaultwert zurückgegeben.</returns> /// <returns>Den Text als Integer64. Wenn die Konvertierung fehlschlägt, dann wird der Defaultwert zurückgegeben.</returns>
public static Int64 TextToInteger64(string text, Int64 defaultValue) { public static Int64 TextToInteger64(string text, Int64 defaultValue)
{
Int64 result = defaultValue; Int64 result = defaultValue;
try { try
{
string localText = text.Replace(".", ""); string localText = text.Replace(".", "");
result = Convert.ToInt64(localText.Trim()); result = Convert.ToInt64(localText.Trim());
} catch { } }
catch { }
return result; return result;
} }
public static double TextToDouble(string text, double defaultValue, string culture) { public static double TextToDouble(string text, double defaultValue, string culture)
{
double result = defaultValue; double result = defaultValue;
try { try
if (!string.IsNullOrEmpty(text)) { {
if (!string.IsNullOrEmpty(text))
{
double.TryParse(text, NumberStyles.Any, new System.Globalization.CultureInfo(culture), out result); double.TryParse(text, NumberStyles.Any, new System.Globalization.CultureInfo(culture), out result);
} }
} catch { } }
catch { }
return result; return result;
} }
@ -131,20 +165,26 @@ namespace Core.Helper {
/// <param name="text">Zu konvertierender Text.</param> /// <param name="text">Zu konvertierender Text.</param>
/// <param name="defaultValue">Der Vorgabewert für den Fall, dass keine gültige DateTime eingegeben wurde.</param> /// <param name="defaultValue">Der Vorgabewert für den Fall, dass keine gültige DateTime eingegeben wurde.</param>
/// <returns>Den Text als DateTime. Wenn die Konvertierung fehlschlägt, dann wird der Defaultwert zurückgegeben.</returns> /// <returns>Den Text als DateTime. Wenn die Konvertierung fehlschlägt, dann wird der Defaultwert zurückgegeben.</returns>
public static DateTime TextToDateTime(string text, DateTime defaultValue) { public static DateTime TextToDateTime(string text, DateTime defaultValue)
{
DateTime result = defaultValue; DateTime result = defaultValue;
try { try
{
result = Convert.ToDateTime(text.Trim()); result = Convert.ToDateTime(text.Trim());
} catch { } }
catch { }
return result; return result;
} }
public static DateTime TextToDateTime(string text, DateTime defaultValue, string culture) { public static DateTime TextToDateTime(string text, DateTime defaultValue, string culture)
{
DateTime result = defaultValue; DateTime result = defaultValue;
try { try
{
result = Convert.ToDateTime(text.Trim(), new System.Globalization.CultureInfo(culture)); result = Convert.ToDateTime(text.Trim(), new System.Globalization.CultureInfo(culture));
} catch { } }
catch { }
return result; return result;
} }
@ -155,32 +195,46 @@ namespace Core.Helper {
/// <param name="text">Zu konvertierender Text.</param> /// <param name="text">Zu konvertierender Text.</param>
/// <param name="defaultValue">Der Vorgabewert für den Fall, dass keine gültige Boolean eingegeben wurde.</param> /// <param name="defaultValue">Der Vorgabewert für den Fall, dass keine gültige Boolean eingegeben wurde.</param>
/// <returns>Den Text als Boolean. Wenn die Konvertierung fehlschlägt, dann wird der Defaultwert zurückgegeben.</returns> /// <returns>Den Text als Boolean. Wenn die Konvertierung fehlschlägt, dann wird der Defaultwert zurückgegeben.</returns>
public static bool TextToBoolean(string text, bool defaultValue) { public static bool TextToBoolean(string text, bool defaultValue)
{
bool result = defaultValue; bool result = defaultValue;
try { try
{
result = Convert.ToBoolean(text.Trim()); result = Convert.ToBoolean(text.Trim());
} catch { }
try { catch
{
try
{
int intValue = Convert.ToInt32(text.Trim()); int intValue = Convert.ToInt32(text.Trim());
result = intValue == 0 ? false : true; result = intValue == 0 ? false : true;
} catch { } }
catch { }
} }
return result; return result;
} }
public static string SplitCamelCase(string s) { public static string SplitCamelCase(string s)
{
string result = ""; string result = "";
string whiteList = "ABCDEFGHIJKLMNOPQRSTUVWXYZÄÜÖßabcdefghijklmnopqrstuvwxyzäüö0123456789_- "; string whiteList = "ABCDEFGHIJKLMNOPQRSTUVWXYZÄÜÖßabcdefghijklmnopqrstuvwxyzäüö0123456789_- ";
if (!string.IsNullOrEmpty(s)) { if (!string.IsNullOrEmpty(s))
for (int i = 0; i < s.Length; i++) { {
if (char.IsUpper(s[i]) || char.IsNumber(s[i])) { for (int i = 0; i < s.Length; i++)
if (i > 0 && whiteList.Contains(s[i - 1].ToString())) { {
if (char.IsUpper(s[i])) { if (char.IsUpper(s[i]) || char.IsNumber(s[i]))
{
if (i > 0 && whiteList.Contains(s[i - 1].ToString()))
{
if (char.IsUpper(s[i]))
{
if (!char.IsUpper(s[i - 1]) && !char.IsNumber(s[i - 1])) result += " "; if (!char.IsUpper(s[i - 1]) && !char.IsNumber(s[i - 1])) result += " ";
} else if (char.IsNumber(s[i])) { }
else if (char.IsNumber(s[i]))
{
if (!char.IsNumber(s[i - 1])) result += " "; if (!char.IsNumber(s[i - 1])) result += " ";
} }
} }
@ -198,10 +252,13 @@ namespace Core.Helper {
/// <param name="text">Text to clear.</param> /// <param name="text">Text to clear.</param>
/// <param name="allowedCharacters">Allowed characters.</param> /// <param name="allowedCharacters">Allowed characters.</param>
/// <returns>The cleared text.</returns> /// <returns>The cleared text.</returns>
public static string StripBadCode(string text, string allowedCharacters) { public static string StripBadCode(string text, string allowedCharacters)
{
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (text != null) { if (text != null)
for (int i = 0; i < text.Length; i++) { {
for (int i = 0; i < text.Length; i++)
{
if (allowedCharacters.Contains(text[i].ToString())) sb.Append(text[i]); if (allowedCharacters.Contains(text[i].ToString())) sb.Append(text[i]);
} }
} }
@ -209,10 +266,13 @@ namespace Core.Helper {
return sb.ToString(); return sb.ToString();
} }
public static bool CheckForBadCode(string text, string allowedCharacters) { public static bool CheckForBadCode(string text, string allowedCharacters)
{
bool result = false; bool result = false;
for (int i = 0; i < text.Length; i++) { for (int i = 0; i < text.Length; i++)
if (!allowedCharacters.Contains(text[i].ToString())) { {
if (!allowedCharacters.Contains(text[i].ToString()))
{
result = true; result = true;
break; break;
} }
@ -227,10 +287,12 @@ namespace Core.Helper {
/// <param name="text">Der Text, der gekürzt werden soll.</param> /// <param name="text">Der Text, der gekürzt werden soll.</param>
/// <param name="maxLength">Die maximale Länge, auf die der Text gekürzt werden soll.</param> /// <param name="maxLength">Die maximale Länge, auf die der Text gekürzt werden soll.</param>
/// <returns>Der gekürzte Text.</returns> /// <returns>Der gekürzte Text.</returns>
public static string CutText(string text, int maxLength, bool addDots) { public static string CutText(string text, int maxLength, bool addDots)
{
string result = text; string result = text;
if (result.Length > maxLength) { if (result.Length > maxLength)
{
result = result.Substring(0, maxLength); result = result.Substring(0, maxLength);
if (addDots) result += "..."; if (addDots) result += "...";
@ -242,10 +304,12 @@ namespace Core.Helper {
/// <summary> /// <summary>
/// Ermittelt den Teilstring eines Zeitstring, der die Stunden darstellt. /// Ermittelt den Teilstring eines Zeitstring, der die Stunden darstellt.
/// </summary> /// </summary>
public static string GetHourFromString(string timeString) { public static string GetHourFromString(string timeString)
{
string result = ""; string result = "";
if (timeString.Contains(":")) { if (timeString.Contains(":"))
{
string[] arrTime = timeString.Split(":".ToCharArray()); string[] arrTime = timeString.Split(":".ToCharArray());
result = arrTime[0]; result = arrTime[0];
} }
@ -256,10 +320,12 @@ namespace Core.Helper {
/// <summary> /// <summary>
/// Ermittelt den Teilstring eines Zeitstring, der die Minuten darstellt. /// Ermittelt den Teilstring eines Zeitstring, der die Minuten darstellt.
/// </summary> /// </summary>
public static string GetMinutesFromString(string timeString) { public static string GetMinutesFromString(string timeString)
{
string result = ""; string result = "";
if (timeString.Contains(":")) { if (timeString.Contains(":"))
{
string[] arrTime = timeString.Split(":".ToCharArray()); string[] arrTime = timeString.Split(":".ToCharArray());
result = arrTime[1]; result = arrTime[1];
} }
@ -267,12 +333,15 @@ namespace Core.Helper {
return result; return result;
} }
public static List<string> ConvertTokenStringToList(string tokenizedString, string separator) { public static List<string> ConvertTokenStringToList(string tokenizedString, string separator)
{
List<string> result = new List<string>(); List<string> result = new List<string>();
if (!String.IsNullOrEmpty(tokenizedString) && !String.IsNullOrEmpty(separator)) { if (!String.IsNullOrEmpty(tokenizedString) && !String.IsNullOrEmpty(separator))
{
string[] arrTokens = tokenizedString.Split(separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); string[] arrTokens = tokenizedString.Split(separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < arrTokens.Length; i++) { for (int i = 0; i < arrTokens.Length; i++)
{
result.Add(arrTokens[i].Trim()); result.Add(arrTokens[i].Trim());
} }
} }
@ -280,12 +349,15 @@ namespace Core.Helper {
return result; return result;
} }
public static List<int> ConvertTokenStringToListInt(string tokenizedString, string separator) { public static List<int> ConvertTokenStringToListInt(string tokenizedString, string separator)
{
List<int> result = new List<int>(); List<int> result = new List<int>();
if (!String.IsNullOrEmpty(tokenizedString) && !String.IsNullOrEmpty(separator)) { if (!String.IsNullOrEmpty(tokenizedString) && !String.IsNullOrEmpty(separator))
{
string[] arrTokens = tokenizedString.Split(separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); string[] arrTokens = tokenizedString.Split(separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < arrTokens.Length; i++) { for (int i = 0; i < arrTokens.Length; i++)
{
result.Add(Convert.ToInt32(arrTokens[i])); result.Add(Convert.ToInt32(arrTokens[i]));
} }
} }
@ -293,25 +365,31 @@ namespace Core.Helper {
return result; return result;
} }
public static string ConvertListToTokenString(List<string> tokenList, string separator, bool cropDoubleSeparators) { public static string ConvertListToTokenString(List<string> tokenList, string separator, bool cropDoubleSeparators)
{
string result = ""; string result = "";
if (tokenList.Count > 0) { if (tokenList.Count > 0)
for (int i = 0; i < tokenList.Count; i++) { {
for (int i = 0; i < tokenList.Count; i++)
{
result += tokenList[i].Trim() + separator; result += tokenList[i].Trim() + separator;
} }
if (cropDoubleSeparators)result = result.Replace(separator + separator, ""); if (cropDoubleSeparators) result = result.Replace(separator + separator, "");
} }
return result; return result;
} }
public static string ConvertListToTokenString(List<int> tokenList, string separator) { public static string ConvertListToTokenString(List<int> tokenList, string separator)
{
string result = ""; string result = "";
if (tokenList.Count > 0) { if (tokenList.Count > 0)
for (int i = 0; i < tokenList.Count; i++) { {
for (int i = 0; i < tokenList.Count; i++)
{
result += tokenList[i].ToString() + separator; result += tokenList[i].ToString() + separator;
} }
@ -322,22 +400,27 @@ namespace Core.Helper {
return result; return result;
} }
public static List<object> ConvertToObjectList<T>(List<T> inputList) { public static List<object> ConvertToObjectList<T>(List<T> inputList)
{
List<object> result = new List<object>(); List<object> result = new List<object>();
foreach (T item in inputList) { foreach (T item in inputList)
{
result.Add(item); result.Add(item);
} }
return result; return result;
} }
public static Hashtable ConvertTokenStringToHashtable(string tokenizedString, string pairSeparator, string fieldSeperator) { public static Hashtable ConvertTokenStringToHashtable(string tokenizedString, string pairSeparator, string fieldSeperator)
{
Hashtable result = new Hashtable(); Hashtable result = new Hashtable();
if (!String.IsNullOrEmpty(tokenizedString) && !String.IsNullOrEmpty(pairSeparator) && !String.IsNullOrEmpty(fieldSeperator)) { if (!String.IsNullOrEmpty(tokenizedString) && !String.IsNullOrEmpty(pairSeparator) && !String.IsNullOrEmpty(fieldSeperator))
{
string[] arrTokens = tokenizedString.Split(pairSeparator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); string[] arrTokens = tokenizedString.Split(pairSeparator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < arrTokens.Length; i++) { for (int i = 0; i < arrTokens.Length; i++)
{
string[] arrKeyValuePair = arrTokens[i].Split(fieldSeperator.ToCharArray()); string[] arrKeyValuePair = arrTokens[i].Split(fieldSeperator.ToCharArray());
result.Add(arrKeyValuePair[0], arrKeyValuePair[1]); result.Add(arrKeyValuePair[0], arrKeyValuePair[1]);
@ -347,11 +430,14 @@ namespace Core.Helper {
return result; return result;
} }
public static string ConvertHashtableToTokenString(Hashtable tokenHashtable, string pairSeparator, string fieldSeperator) { public static string ConvertHashtableToTokenString(Hashtable tokenHashtable, string pairSeparator, string fieldSeperator)
{
string result = ""; string result = "";
if (tokenHashtable.Keys.Count > 0) { if (tokenHashtable.Keys.Count > 0)
foreach (string key in tokenHashtable.Keys) { {
foreach (string key in tokenHashtable.Keys)
{
result += key + fieldSeperator + tokenHashtable[key] + pairSeparator; result += key + fieldSeperator + tokenHashtable[key] + pairSeparator;
} }
@ -362,7 +448,8 @@ namespace Core.Helper {
return result; return result;
} }
public static string GetProperDurationTime(int durationSeconds, bool includeDays = true) { public static string GetProperDurationTime(int durationSeconds, bool includeDays = true)
{
string result = ""; string result = "";
int days = (int)Math.Floor((double)durationSeconds / (60.0 * 60.0 * 24.0)); int days = (int)Math.Floor((double)durationSeconds / (60.0 * 60.0 * 24.0));
@ -372,21 +459,25 @@ namespace Core.Helper {
int minutes = (int)Math.Floor((double)durationSeconds / 60.0) - (hours * 60) - (days * 24 * 60); int minutes = (int)Math.Floor((double)durationSeconds / 60.0) - (hours * 60) - (days * 24 * 60);
int seconds = durationSeconds - (minutes * 60) - (hours * 60 * 60) - (days * 24 * 60 * 60); int seconds = durationSeconds - (minutes * 60) - (hours * 60 * 60) - (days * 24 * 60 * 60);
if (days > 0) { if (days > 0)
{
result += days.ToString() + "d"; result += days.ToString() + "d";
} }
if (hours > 0) { if (hours > 0)
{
if (days > 0) result += " "; if (days > 0) result += " ";
result += hours.ToString() + "h"; result += hours.ToString() + "h";
} }
if (minutes > 0) { if (minutes > 0)
{
if (hours > 0 || days > 0) result += " "; if (hours > 0 || days > 0) result += " ";
result += minutes.ToString() + "m"; result += minutes.ToString() + "m";
} }
if (seconds > 0) { if (seconds > 0)
{
if (minutes > 0 || hours > 0 || days > 0) result += " "; if (minutes > 0 || hours > 0 || days > 0) result += " ";
result += seconds.ToString() + "s"; result += seconds.ToString() + "s";
} }
@ -394,24 +485,30 @@ namespace Core.Helper {
return result; return result;
} }
public static void AddValueToStringBuilder(StringBuilder sb, string value, int length, bool fillField, string delimiter) { public static void AddValueToStringBuilder(StringBuilder sb, string value, int length, bool fillField, string delimiter)
if (!string.IsNullOrEmpty(value)) { {
if (!string.IsNullOrEmpty(value))
{
if (value.Length > length) if (value.Length > length)
sb.Append(value.Substring(0, length)); // Beschneiden sb.Append(value.Substring(0, length)); // Beschneiden
else { else
{
if (fillField) if (fillField)
sb.Append(value.PadRight(length)); sb.Append(value.PadRight(length));
else else
sb.Append(value); sb.Append(value);
} }
} else { }
else
{
if (fillField) if (fillField)
sb.Append(string.Empty.PadRight(length)); sb.Append(string.Empty.PadRight(length));
} }
sb.Append(delimiter); sb.Append(delimiter);
} }
public static bool UrlIsReachable(string url) { public static bool UrlIsReachable(string url)
{
ServicePointManager.Expect100Continue = true; ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999; ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
@ -421,29 +518,39 @@ namespace Core.Helper {
request.Timeout = 10000; request.Timeout = 10000;
request.Method = "GET"; request.Method = "GET";
try { try
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { {
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
return response.StatusCode == HttpStatusCode.OK; return response.StatusCode == HttpStatusCode.OK;
} }
} catch (WebException) { }
catch (WebException)
{
return false; return false;
} }
} }
public static string GetMarketLink(string platform, string exchange, string market, string mainMarket) { public static string GetMarketLink(string platform, string exchange, string market, string mainMarket)
{
string result = "#"; string result = "#";
if (platform.Equals("TradingView")) { if (platform.Equals("TradingView"))
{
result = "https://www.tradingview.com/chart/?symbol=" + exchange.ToUpper() + ":"; result = "https://www.tradingview.com/chart/?symbol=" + exchange.ToUpper() + ":";
string pairName = SystemHelper.StripBadCode(market, Constants.WhiteListMinimal); string pairName = SystemHelper.StripBadCode(market, Constants.WhiteListMinimal);
if (pairName.StartsWith(mainMarket)) { if (pairName.StartsWith(mainMarket))
{
pairName = pairName.Replace(mainMarket, "") + mainMarket; pairName = pairName.Replace(mainMarket, "") + mainMarket;
} }
result += pairName; result += pairName;
} else { }
switch (exchange) { else
{
switch (exchange)
{
case "Bittrex": case "Bittrex":
result = "https://bittrex.com/Market/Index?MarketName=" + market; result = "https://bittrex.com/Market/Index?MarketName=" + market;
break; break;
@ -459,10 +566,12 @@ namespace Core.Helper {
return result; return result;
} }
public static string GetFullMarketName(string mainMarket, string market, string exchange) { public static string GetFullMarketName(string mainMarket, string market, string exchange)
{
string result = market; string result = market;
switch (exchange) { switch (exchange)
{
case "Bittrex": case "Bittrex":
result = mainMarket + "-" + market; result = mainMarket + "-" + market;
break; break;
@ -478,12 +587,14 @@ namespace Core.Helper {
return result; return result;
} }
public static string GetTradingViewSymbol(string exchange, string market, string mainMarket) { public static string GetTradingViewSymbol(string exchange, string market, string mainMarket)
{
string result = exchange.ToUpper() + ":"; string result = exchange.ToUpper() + ":";
string pairName = SystemHelper.StripBadCode(market, Constants.WhiteListMinimal); string pairName = SystemHelper.StripBadCode(market, Constants.WhiteListMinimal);
if (pairName.StartsWith(mainMarket)) { if (pairName.StartsWith(mainMarket))
{
pairName = pairName.Replace(mainMarket, "") + mainMarket; pairName = pairName.Replace(mainMarket, "") + mainMarket;
} }
@ -493,53 +604,68 @@ namespace Core.Helper {
return result; return result;
} }
public static string GetCurrencySymbol(string code) { public static string GetCurrencySymbol(string code)
{
string result = code; string result = code;
try { try
{
System.Globalization.RegionInfo regionInfo = (from culture in System.Globalization.CultureInfo.GetCultures(System.Globalization.CultureTypes.AllCultures) System.Globalization.RegionInfo regionInfo = (from culture in System.Globalization.CultureInfo.GetCultures(System.Globalization.CultureTypes.AllCultures)
where culture.Name.Length > 0 && !culture.IsNeutralCulture where culture.Name.Length > 0 && !culture.IsNeutralCulture
let region = new System.Globalization.RegionInfo(culture.LCID) let region = new System.Globalization.RegionInfo(culture.LCID)
where String.Equals(region.ISOCurrencySymbol, code, StringComparison.InvariantCultureIgnoreCase) where String.Equals(region.ISOCurrencySymbol, code, StringComparison.InvariantCultureIgnoreCase)
select region).First(); select region).First();
result = regionInfo.CurrencySymbol; result = regionInfo.CurrencySymbol;
} catch { }
catch
{
} }
return result; return result;
} }
public static string PropertyToString(object property) { public static string PropertyToString(object property)
{
string result = property.ToString(); string result = property.ToString();
if (!property.ToString().Equals("true", StringComparison.InvariantCultureIgnoreCase) && !property.ToString().Equals("false", StringComparison.InvariantCultureIgnoreCase)) { if (!property.ToString().Equals("true", StringComparison.InvariantCultureIgnoreCase) && !property.ToString().Equals("false", StringComparison.InvariantCultureIgnoreCase))
try { {
try
{
double resultDouble = Convert.ToDouble(property); double resultDouble = Convert.ToDouble(property);
result = resultDouble.ToString(new System.Globalization.CultureInfo("en-US")); result = resultDouble.ToString(new System.Globalization.CultureInfo("en-US"));
} catch {
} }
} else { catch
{
}
}
else
{
result = property.ToString().ToLower(); result = property.ToString().ToLower();
} }
return result; return result;
} }
public static bool IsRecentVersion(string currentVersion, string latestVersion) { public static bool IsRecentVersion(string currentVersion, string latestVersion)
{
bool result = true; bool result = true;
List<int> currentVersionInfo = SystemHelper.ConvertTokenStringToListInt(currentVersion, "."); List<int> currentVersionInfo = SystemHelper.ConvertTokenStringToListInt(currentVersion, ".");
List<int> latestVersionInfo = SystemHelper.ConvertTokenStringToListInt(latestVersion, "."); List<int> latestVersionInfo = SystemHelper.ConvertTokenStringToListInt(latestVersion, ".");
if (currentVersionInfo[0] < latestVersionInfo[0]) { if (currentVersionInfo[0] < latestVersionInfo[0])
{
result = false; result = false;
} }
if (currentVersionInfo[0] == latestVersionInfo[0] && currentVersionInfo[1] < latestVersionInfo[1]) { if (currentVersionInfo[0] == latestVersionInfo[0] && currentVersionInfo[1] < latestVersionInfo[1])
{
result = false; result = false;
} }
if (currentVersionInfo[0] == latestVersionInfo[0] && currentVersionInfo[1] == latestVersionInfo[1] && currentVersionInfo[2] < latestVersionInfo[2]) { if (currentVersionInfo[0] == latestVersionInfo[0] && currentVersionInfo[1] == latestVersionInfo[1] && currentVersionInfo[2] < latestVersionInfo[2])
{
result = false; result = false;
} }

View File

@ -4,18 +4,26 @@ using Telegram.Bot;
using Telegram.Bot.Types.Enums; using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types; using Telegram.Bot.Types;
namespace Core.Helper { namespace Core.Helper
public static class TelegramHelper { {
public static void SendMessage(string botToken, Int64 chatId, string message, bool useSilentMode, LogHelper log) { public static class TelegramHelper
if (!botToken.Equals("") && chatId != 0) { {
try { public static void SendMessage(string botToken, Int64 chatId, string message, bool useSilentMode, LogHelper log)
{
if (!botToken.Equals("") && chatId != 0)
{
try
{
TelegramBotClient botClient = new TelegramBotClient(botToken); TelegramBotClient botClient = new TelegramBotClient(botToken);
System.Threading.Tasks.Task<Message> sentMessage = botClient.SendTextMessageAsync(chatId, message, ParseMode.Markdown, false, useSilentMode); System.Threading.Tasks.Task<Message> sentMessage = botClient.SendTextMessageAsync(chatId, message, ParseMode.Markdown, false, useSilentMode);
if (sentMessage.IsCompleted) { if (sentMessage.IsCompleted)
{
log.DoLogDebug("Telegram message sent to ChatId " + chatId.ToString() + " on Bot Token '" + botToken + "'"); log.DoLogDebug("Telegram message sent to ChatId " + chatId.ToString() + " on Bot Token '" + botToken + "'");
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical("Exception sending telegram message to ChatId " + chatId.ToString() + " on Bot Token '" + botToken + "'", ex); log.DoLogCritical("Exception sending telegram message to ChatId " + chatId.ToString() + " on Bot Token '" + botToken + "'", ex);
} }
} }

View File

@ -6,20 +6,25 @@ using System.IO;
using System.Text; using System.Text;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
namespace Core.Helper { namespace Core.Helper
{
public class ZIPHelper { public class ZIPHelper
{
public static bool CreateZipFile(ArrayList filePaths, string outputPath) { public static bool CreateZipFile(ArrayList filePaths, string outputPath)
{
bool result = true; bool result = true;
ZipOutputStream pack = new ZipOutputStream(File.Create(outputPath)); ZipOutputStream pack = new ZipOutputStream(File.Create(outputPath));
try { try
{
// set compression level // set compression level
pack.SetLevel(5); pack.SetLevel(5);
foreach (string filePath in filePaths) { foreach (string filePath in filePaths)
{
FileStream fs = File.OpenRead(filePath); FileStream fs = File.OpenRead(filePath);
// allocate buffer // allocate buffer
@ -32,9 +37,13 @@ namespace Core.Helper {
pack.Write(buffer, 0, buffer.Length); pack.Write(buffer, 0, buffer.Length);
} }
} catch { }
catch
{
result = false; result = false;
} finally { }
finally
{
pack.Finish(); pack.Finish();
pack.Close(); pack.Close();
} }
@ -42,15 +51,20 @@ namespace Core.Helper {
return result; return result;
} }
public static ArrayList ExtractFileFromZipFile(string filePath, string destinationPath, bool isInvoicePackage) { public static ArrayList ExtractFileFromZipFile(string filePath, string destinationPath, bool isInvoicePackage)
{
ArrayList result = new ArrayList(); ArrayList result = new ArrayList();
ZipFile zip = new ZipFile(File.OpenRead(filePath)); ZipFile zip = new ZipFile(File.OpenRead(filePath));
try { try
foreach (ZipEntry entry in zip) { {
if (entry.IsFile) { foreach (ZipEntry entry in zip)
{
if (entry.IsFile)
{
string fileName = entry.Name; string fileName = entry.Name;
if (isInvoicePackage) { if (isInvoicePackage)
{
fileName = fileName.Replace("unsigned", "signed"); fileName = fileName.Replace("unsigned", "signed");
} }
@ -58,25 +72,32 @@ namespace Core.Helper {
Stream inputStream = zip.GetInputStream(entry); Stream inputStream = zip.GetInputStream(entry);
FileStream fileStream = new FileStream(destinationPath + fileName, FileMode.Create); FileStream fileStream = new FileStream(destinationPath + fileName, FileMode.Create);
try { try
{
CopyStream(inputStream, fileStream); CopyStream(inputStream, fileStream);
} finally { }
finally
{
fileStream.Close(); fileStream.Close();
inputStream.Close(); inputStream.Close();
} }
} }
} }
} finally { }
finally
{
zip.Close(); zip.Close();
} }
return result; return result;
} }
private static void CopyStream(Stream input, Stream output) { private static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[0x1000]; byte[] buffer = new byte[0x1000];
int read; int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, read); output.Write(buffer, 0, read);
} }
} }

View File

@ -2,8 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
namespace Core.Main { namespace Core.Main
public static class Constants { {
public static class Constants
{
// Minimales Datum (für NULL) // Minimales Datum (für NULL)
public static DateTime confMinDate = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue; public static DateTime confMinDate = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;
public static DateTime confMaxDate = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue; public static DateTime confMaxDate = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue;

File diff suppressed because it is too large Load Diff

View File

@ -7,23 +7,29 @@ using Newtonsoft.Json;
using Core.Helper; using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
namespace Core.Main { namespace Core.Main
{
public class PTMagicConfiguration { public class PTMagicConfiguration
{
private GeneralSettings _generalSettings = null; private GeneralSettings _generalSettings = null;
private AnalyzerSettings _analyzerSettings = null; private AnalyzerSettings _analyzerSettings = null;
private SecureSettings _secureSettings = null; private SecureSettings _secureSettings = null;
public PTMagicConfiguration() { public PTMagicConfiguration()
{
LoadSettings(Directory.GetCurrentDirectory()); LoadSettings(Directory.GetCurrentDirectory());
} }
public PTMagicConfiguration(string basePath) { public PTMagicConfiguration(string basePath)
{
LoadSettings(basePath); LoadSettings(basePath);
} }
private void LoadSettings(string basePath) { private void LoadSettings(string basePath)
if (!basePath.EndsWith(Path.DirectorySeparatorChar)) { {
if (!basePath.EndsWith(Path.DirectorySeparatorChar))
{
basePath += Path.DirectorySeparatorChar; basePath += Path.DirectorySeparatorChar;
} }
@ -33,27 +39,33 @@ namespace Core.Main {
AnalyzerSettingsWrapper asw = JsonConvert.DeserializeObject<AnalyzerSettingsWrapper>(File.ReadAllText(basePath + "settings.analyzer.json")); AnalyzerSettingsWrapper asw = JsonConvert.DeserializeObject<AnalyzerSettingsWrapper>(File.ReadAllText(basePath + "settings.analyzer.json"));
_analyzerSettings = asw.AnalyzerSettings; _analyzerSettings = asw.AnalyzerSettings;
if (!_generalSettings.Application.ProfitTrailerPath.EndsWith(Path.DirectorySeparatorChar)) { if (!_generalSettings.Application.ProfitTrailerPath.EndsWith(Path.DirectorySeparatorChar))
{
_generalSettings.Application.ProfitTrailerPath += Path.DirectorySeparatorChar; _generalSettings.Application.ProfitTrailerPath += Path.DirectorySeparatorChar;
} }
if (!_generalSettings.Application.ProfitTrailerMonitorURL.EndsWith("/")) { if (!_generalSettings.Application.ProfitTrailerMonitorURL.EndsWith("/"))
{
_generalSettings.Application.ProfitTrailerMonitorURL += "/"; _generalSettings.Application.ProfitTrailerMonitorURL += "/";
} }
if (File.Exists(basePath + "settings.secure.json")) { if (File.Exists(basePath + "settings.secure.json"))
{
SecureSettingsWrapper ssw = JsonConvert.DeserializeObject<SecureSettingsWrapper>(File.ReadAllText(basePath + "settings.secure.json")); SecureSettingsWrapper ssw = JsonConvert.DeserializeObject<SecureSettingsWrapper>(File.ReadAllText(basePath + "settings.secure.json"));
_secureSettings = ssw.SecureSettings; _secureSettings = ssw.SecureSettings;
} }
} }
public string GetProfitTrailerLicenseKeyMasked() { public string GetProfitTrailerLicenseKeyMasked()
{
string result = ""; string result = "";
if (!this.GeneralSettings.Application.ProfitTrailerLicense.Equals("")) { if (!this.GeneralSettings.Application.ProfitTrailerLicense.Equals(""))
{
result = this.GeneralSettings.Application.ProfitTrailerLicense.Substring(0, 4); result = this.GeneralSettings.Application.ProfitTrailerLicense.Substring(0, 4);
for (int i = 1; i < this.GeneralSettings.Application.ProfitTrailerLicense.Length - 8; i++) { for (int i = 1; i < this.GeneralSettings.Application.ProfitTrailerLicense.Length - 8; i++)
{
result += "*"; result += "*";
} }
@ -63,26 +75,33 @@ namespace Core.Main {
return result; return result;
} }
public GeneralSettings GeneralSettings { public GeneralSettings GeneralSettings
get { {
get
{
return _generalSettings; return _generalSettings;
} }
} }
public AnalyzerSettings AnalyzerSettings { public AnalyzerSettings AnalyzerSettings
get { {
get
{
return _analyzerSettings; return _analyzerSettings;
} }
} }
public SecureSettings SecureSettings { public SecureSettings SecureSettings
get { {
get
{
if (_secureSettings == null) _secureSettings = new SecureSettings(); if (_secureSettings == null) _secureSettings = new SecureSettings();
return _secureSettings; return _secureSettings;
} }
} }
public void WriteGeneralSettings(string basePath) { public void WriteGeneralSettings(string basePath)
{
GeneralSettingsWrapper gsWrapper = new GeneralSettingsWrapper(); GeneralSettingsWrapper gsWrapper = new GeneralSettingsWrapper();
gsWrapper.GeneralSettings = this.GeneralSettings; gsWrapper.GeneralSettings = this.GeneralSettings;
@ -91,7 +110,8 @@ namespace Core.Main {
FileHelper.WriteTextToFile(basePath, "settings.general.json", JsonConvert.SerializeObject(gsWrapper, Formatting.Indented)); FileHelper.WriteTextToFile(basePath, "settings.general.json", JsonConvert.SerializeObject(gsWrapper, Formatting.Indented));
} }
public void WriteAnalyzerSettings(string basePath) { public void WriteAnalyzerSettings(string basePath)
{
AnalyzerSettingsWrapper asWrapper = new AnalyzerSettingsWrapper(); AnalyzerSettingsWrapper asWrapper = new AnalyzerSettingsWrapper();
asWrapper.AnalyzerSettings = this.AnalyzerSettings; asWrapper.AnalyzerSettings = this.AnalyzerSettings;
@ -104,7 +124,8 @@ namespace Core.Main {
FileHelper.WriteTextToFile(basePath, "settings.analyzer.json", JsonConvert.SerializeObject(asWrapper, Formatting.Indented, settings)); FileHelper.WriteTextToFile(basePath, "settings.analyzer.json", JsonConvert.SerializeObject(asWrapper, Formatting.Indented, settings));
} }
public void WriteSecureSettings(string password, string basePath) { public void WriteSecureSettings(string password, string basePath)
{
string passwordEncrypted = EncryptionHelper.Encrypt(password); string passwordEncrypted = EncryptionHelper.Encrypt(password);
this.SecureSettings.MonitorPassword = passwordEncrypted; this.SecureSettings.MonitorPassword = passwordEncrypted;

View File

@ -9,13 +9,17 @@ using Core.Main;
using Core.Helper; using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
namespace Core.MarketAnalyzer { namespace Core.MarketAnalyzer
public class BaseAnalyzer { {
public static Dictionary<string, dynamic> GetJsonFromURL(string url, LogHelper log, string api) { public class BaseAnalyzer
{
public static Dictionary<string, dynamic> GetJsonFromURL(string url, LogHelper log, string api)
{
Dictionary<string, dynamic> jsonObject = null; Dictionary<string, dynamic> jsonObject = null;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
if (api != ""){ if (api != "")
{
request.Headers.Add("X-CMC_PRO_API_KEY", api); request.Headers.Add("X-CMC_PRO_API_KEY", api);
} }
@ -23,7 +27,8 @@ namespace Core.MarketAnalyzer {
request.UserAgent = "PTMagic.Import"; request.UserAgent = "PTMagic.Import";
request.KeepAlive = true; request.KeepAlive = true;
try { try
{
HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse(); HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse();
StreamReader jsonReader = new StreamReader(httpResponse.GetResponseStream()); StreamReader jsonReader = new StreamReader(httpResponse.GetResponseStream());
@ -33,17 +38,22 @@ namespace Core.MarketAnalyzer {
jsonObject = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(jsonString); jsonObject = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(jsonString);
return jsonObject; return jsonObject;
} catch (WebException ex) { }
catch (WebException ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
throw ex; throw ex;
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return jsonObject; return jsonObject;
} }
public static Newtonsoft.Json.Linq.JObject GetSimpleJsonObjectFromURL(string url, LogHelper log, bool swallowException) { public static Newtonsoft.Json.Linq.JObject GetSimpleJsonObjectFromURL(string url, LogHelper log, bool swallowException)
{
Newtonsoft.Json.Linq.JObject jsonObject = null; Newtonsoft.Json.Linq.JObject jsonObject = null;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
@ -51,7 +61,8 @@ namespace Core.MarketAnalyzer {
request.UserAgent = "PTMagic.Import"; request.UserAgent = "PTMagic.Import";
request.KeepAlive = true; request.KeepAlive = true;
try { try
{
HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse(); HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse();
StreamReader jsonReader = new StreamReader(httpResponse.GetResponseStream()); StreamReader jsonReader = new StreamReader(httpResponse.GetResponseStream());
@ -61,17 +72,27 @@ namespace Core.MarketAnalyzer {
jsonObject = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(jsonString); jsonObject = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(jsonString);
return jsonObject; return jsonObject;
} catch (WebException ex) { }
if (swallowException) { catch (WebException ex)
{
if (swallowException)
{
// Do nothing, as we do not want to get this logged. Only uncritical functions uses this // Do nothing, as we do not want to get this logged. Only uncritical functions uses this
} else { }
else
{
log.DoLogCritical("Url: " + url + " Message: " + ex.Message, ex); log.DoLogCritical("Url: " + url + " Message: " + ex.Message, ex);
throw ex; throw ex;
} }
} catch (Exception ex) { }
if (swallowException) { catch (Exception ex)
{
if (swallowException)
{
// Do nothing, as we do not want to get this logged. Only uncritical functions uses this // Do nothing, as we do not want to get this logged. Only uncritical functions uses this
} else { }
else
{
log.DoLogCritical("Url: " + url + " Message: " + ex.Message, ex); log.DoLogCritical("Url: " + url + " Message: " + ex.Message, ex);
throw ex; throw ex;
} }
@ -80,7 +101,8 @@ namespace Core.MarketAnalyzer {
return jsonObject; return jsonObject;
} }
public static List<dynamic> GetSimpleJsonListFromURL(string url, LogHelper log) { public static List<dynamic> GetSimpleJsonListFromURL(string url, LogHelper log)
{
List<dynamic> jsonObject = null; List<dynamic> jsonObject = null;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
@ -88,7 +110,8 @@ namespace Core.MarketAnalyzer {
request.UserAgent = "PTMagic.Import"; request.UserAgent = "PTMagic.Import";
request.KeepAlive = true; request.KeepAlive = true;
try { try
{
HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse(); HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse();
StreamReader jsonReader = new StreamReader(httpResponse.GetResponseStream()); StreamReader jsonReader = new StreamReader(httpResponse.GetResponseStream());
@ -98,17 +121,22 @@ namespace Core.MarketAnalyzer {
jsonObject = JsonConvert.DeserializeObject<List<dynamic>>(jsonString); jsonObject = JsonConvert.DeserializeObject<List<dynamic>>(jsonString);
return jsonObject; return jsonObject;
} catch (WebException ex) { }
catch (WebException ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
throw ex; throw ex;
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return jsonObject; return jsonObject;
} }
public static Newtonsoft.Json.Linq.JArray GetSimpleJsonArrayFromURL(string url, LogHelper log) { public static Newtonsoft.Json.Linq.JArray GetSimpleJsonArrayFromURL(string url, LogHelper log)
{
Newtonsoft.Json.Linq.JArray jsonObject = null; Newtonsoft.Json.Linq.JArray jsonObject = null;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
@ -116,7 +144,8 @@ namespace Core.MarketAnalyzer {
request.UserAgent = "PTMagic.Import"; request.UserAgent = "PTMagic.Import";
request.KeepAlive = true; request.KeepAlive = true;
try { try
{
HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse(); HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse();
StreamReader jsonReader = new StreamReader(httpResponse.GetResponseStream()); StreamReader jsonReader = new StreamReader(httpResponse.GetResponseStream());
@ -126,43 +155,56 @@ namespace Core.MarketAnalyzer {
jsonObject = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JArray>(jsonString); jsonObject = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JArray>(jsonString);
return jsonObject; return jsonObject;
} catch (WebException ex) { }
catch (WebException ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
throw ex; throw ex;
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return jsonObject; return jsonObject;
} }
public static string GetLatestGitHubRelease(LogHelper log, string defaultVersion) { public static string GetLatestGitHubRelease(LogHelper log, string defaultVersion)
{
string result = defaultVersion; string result = defaultVersion;
try { try
{
string baseUrl = "https://api.github.com/repos/legedric/ptmagic/releases/latest"; string baseUrl = "https://api.github.com/repos/legedric/ptmagic/releases/latest";
Newtonsoft.Json.Linq.JObject jsonObject = GetSimpleJsonObjectFromURL(baseUrl, log, true); Newtonsoft.Json.Linq.JObject jsonObject = GetSimpleJsonObjectFromURL(baseUrl, log, true);
if (jsonObject != null) { if (jsonObject != null)
{
result = jsonObject.GetValue("tag_name").ToString(); result = jsonObject.GetValue("tag_name").ToString();
} }
} catch (WebException ex) { }
catch (WebException ex)
{
log.DoLogDebug("GitHub version check error: " + ex.Message); log.DoLogDebug("GitHub version check error: " + ex.Message);
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogDebug("GitHub version check error: " + ex.Message); log.DoLogDebug("GitHub version check error: " + ex.Message);
} }
return result; return result;
} }
public static double GetMainFiatCurrencyRate(string currency, LogHelper log) { public static double GetMainFiatCurrencyRate(string currency, LogHelper log)
{
double result = 1; double result = 1;
string baseUrl = "http://free.currencyconverterapi.com/api/v5/convert?q=USD_" + currency + "&compact=y"; string baseUrl = "http://free.currencyconverterapi.com/api/v5/convert?q=USD_" + currency + "&compact=y";
log.DoLogDebug("http://free.currencyconverterapi.com - Getting latest exchange rates..."); log.DoLogDebug("http://free.currencyconverterapi.com - Getting latest exchange rates...");
Newtonsoft.Json.Linq.JObject jsonObject = GetSimpleJsonObjectFromURL(baseUrl, log, false); Newtonsoft.Json.Linq.JObject jsonObject = GetSimpleJsonObjectFromURL(baseUrl, log, false);
if (jsonObject != null) { if (jsonObject != null)
{
log.DoLogDebug("http://free.currencyconverterapi.com - Received latest exchange rates."); log.DoLogDebug("http://free.currencyconverterapi.com - Received latest exchange rates.");
result = (double)jsonObject["USD_" + currency]["val"]; result = (double)jsonObject["USD_" + currency]["val"];
@ -172,30 +214,38 @@ namespace Core.MarketAnalyzer {
return result; return result;
} }
public static Dictionary<string, MarketInfo> GetMarketInfosFromFile(PTMagicConfiguration systemConfiguration, LogHelper log) { public static Dictionary<string, MarketInfo> GetMarketInfosFromFile(PTMagicConfiguration systemConfiguration, LogHelper log)
{
Dictionary<string, MarketInfo> result = new Dictionary<string, MarketInfo>(); Dictionary<string, MarketInfo> result = new Dictionary<string, MarketInfo>();
string marketInfoFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar + "MarketInfo.json"; string marketInfoFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar + "MarketInfo.json";
if (File.Exists(marketInfoFilePath)) { if (File.Exists(marketInfoFilePath))
try { {
try
{
result = JsonConvert.DeserializeObject<Dictionary<string, MarketInfo>>(System.IO.File.ReadAllText(marketInfoFilePath)); result = JsonConvert.DeserializeObject<Dictionary<string, MarketInfo>>(System.IO.File.ReadAllText(marketInfoFilePath));
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogDebug(ex.Message); log.DoLogDebug(ex.Message);
} }
} }
if (result == null) { if (result == null)
{
result = new Dictionary<string, MarketInfo>(); result = new Dictionary<string, MarketInfo>();
} }
return result; return result;
} }
public static void SaveMarketInfosToFile(Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { public static void SaveMarketInfosToFile(Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log)
{
FileHelper.WriteTextToFile(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar, "MarketInfo.json", JsonConvert.SerializeObject(marketInfos)); FileHelper.WriteTextToFile(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar, "MarketInfo.json", JsonConvert.SerializeObject(marketInfos));
} }
public static Dictionary<string, Market> GetMarketDataFromFile(PTMagicConfiguration systemConfiguration, LogHelper log, string platform, DateTime maxDateTime, string marketCaption) { public static Dictionary<string, Market> GetMarketDataFromFile(PTMagicConfiguration systemConfiguration, LogHelper log, string platform, DateTime maxDateTime, string marketCaption)
{
Dictionary<string, Market> result = new Dictionary<string, Market>(); Dictionary<string, Market> result = new Dictionary<string, Market>();
DirectoryInfo dataDirectory = new DirectoryInfo(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + platform + Path.DirectorySeparatorChar); DirectoryInfo dataDirectory = new DirectoryInfo(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + platform + Path.DirectorySeparatorChar);
@ -207,11 +257,14 @@ namespace Core.MarketAnalyzer {
.ToArray().OrderByDescending(f => f.LastWriteTimeUtc).ToList(); .ToArray().OrderByDescending(f => f.LastWriteTimeUtc).ToList();
FileInfo marketFile = null; FileInfo marketFile = null;
if (marketFiles.Count > 0) { if (marketFiles.Count > 0)
{
marketFile = marketFiles.First(); marketFile = marketFiles.First();
log.DoLogDebug(platform + " - " + marketCaption + " market data loaded (" + marketFile.LastWriteTimeUtc.ToString() + ")"); log.DoLogDebug(platform + " - " + marketCaption + " market data loaded (" + marketFile.LastWriteTimeUtc.ToString() + ")");
} else { }
else
{
log.DoLogDebug(platform + " - Not able to load " + marketCaption + " market data. Loading next youngest market file instead."); log.DoLogDebug(platform + " - Not able to load " + marketCaption + " market data. Loading next youngest market file instead.");
// Get market files younger than max datetime in ascending order (oldest file up top) // Get market files younger than max datetime in ascending order (oldest file up top)
@ -219,33 +272,44 @@ namespace Core.MarketAnalyzer {
.Select(x => { x.Refresh(); return x; }) .Select(x => { x.Refresh(); return x; })
.Where(x => x.LastWriteTimeUtc >= maxDateTime) .Where(x => x.LastWriteTimeUtc >= maxDateTime)
.ToArray().OrderBy(f => f.LastWriteTimeUtc).ToList(); .ToArray().OrderBy(f => f.LastWriteTimeUtc).ToList();
if (marketFiles.Count > 0) { if (marketFiles.Count > 0)
{
marketFile = marketFiles.First(); marketFile = marketFiles.First();
log.DoLogDebug(platform + " - " + marketCaption + " market data loaded (" + marketFile.LastWriteTimeUtc.ToString() + ")"); log.DoLogDebug(platform + " - " + marketCaption + " market data loaded (" + marketFile.LastWriteTimeUtc.ToString() + ")");
} }
} }
try { try
{
// Get JSON object // Get JSON object
result = JsonConvert.DeserializeObject<Dictionary<string, Market>>(marketFile.OpenText().ReadToEnd()); result = JsonConvert.DeserializeObject<Dictionary<string, Market>>(marketFile.OpenText().ReadToEnd());
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return result; return result;
} }
public static Dictionary<string, List<MarketTrendChange>> BuildMarketTrends(string platform, string mainMarket, List<string> marketList, string sortBy, bool isGlobal, Dictionary<string, List<MarketTrendChange>> output, PTMagicConfiguration systemConfiguration, LogHelper log) { public static Dictionary<string, List<MarketTrendChange>> BuildMarketTrends(string platform, string mainMarket, List<string> marketList, string sortBy, bool isGlobal, Dictionary<string, List<MarketTrendChange>> output, PTMagicConfiguration systemConfiguration, LogHelper log)
{
try { try
{
List<MarketTrend> marketTrends = systemConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.FindAll(mt => mt.Platform.Equals(platform, StringComparison.InvariantCultureIgnoreCase)); List<MarketTrend> marketTrends = systemConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.FindAll(mt => mt.Platform.Equals(platform, StringComparison.InvariantCultureIgnoreCase));
if (marketTrends.Count > 0) { if (marketTrends.Count > 0)
{
Dictionary<string, Market> recentMarkets = BaseAnalyzer.GetMarketDataFromFile(systemConfiguration, log, platform, DateTime.Now.ToUniversalTime(), "Recent"); Dictionary<string, Market> recentMarkets = BaseAnalyzer.GetMarketDataFromFile(systemConfiguration, log, platform, DateTime.Now.ToUniversalTime(), "Recent");
foreach (MarketTrend marketTrend in marketTrends) { foreach (MarketTrend marketTrend in marketTrends)
if (platform.Equals("Exchange", StringComparison.InvariantCultureIgnoreCase)) { {
if (platform.Equals("Exchange", StringComparison.InvariantCultureIgnoreCase))
{
log.DoLogInfo(platform + " - Building market trend changes for '" + marketTrend.Name + "' on main market '" + mainMarket + "' with " + marketList.Count.ToString() + " markets..."); log.DoLogInfo(platform + " - Building market trend changes for '" + marketTrend.Name + "' on main market '" + mainMarket + "' with " + marketList.Count.ToString() + " markets...");
} else { }
else
{
log.DoLogInfo(platform + " - Building market trend changes for '" + marketTrend.Name + "'..."); log.DoLogInfo(platform + " - Building market trend changes for '" + marketTrend.Name + "'...");
} }
@ -259,33 +323,42 @@ namespace Core.MarketAnalyzer {
} }
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return output; return output;
} }
public static List<MarketTrendChange> GetMarketTrendChanges(string platform, string mainMarket, MarketTrend marketTrend, List<string> marketList, Dictionary<string, Market> recentMarkets, Dictionary<string, Market> trendMarkets, string sortBy, bool isGlobal, PTMagicConfiguration systemConfiguration, LogHelper log) { public static List<MarketTrendChange> GetMarketTrendChanges(string platform, string mainMarket, MarketTrend marketTrend, List<string> marketList, Dictionary<string, Market> recentMarkets, Dictionary<string, Market> trendMarkets, string sortBy, bool isGlobal, PTMagicConfiguration systemConfiguration, LogHelper log)
{
List<MarketTrendChange> result = new List<MarketTrendChange>(); List<MarketTrendChange> result = new List<MarketTrendChange>();
var sortedMarkets = new SortedDictionary<string, Market>(recentMarkets).OrderBy(m => m.Value.Position); var sortedMarkets = new SortedDictionary<string, Market>(recentMarkets).OrderBy(m => m.Value.Position);
if (sortBy.Equals("Volume")) { if (sortBy.Equals("Volume"))
{
sortedMarkets = new SortedDictionary<string, Market>(recentMarkets).OrderByDescending(m => m.Value.Volume24h); sortedMarkets = new SortedDictionary<string, Market>(recentMarkets).OrderByDescending(m => m.Value.Volume24h);
} }
int marketCount = 1; int marketCount = 1;
foreach (KeyValuePair<string, Market> recentMarketPair in sortedMarkets) { foreach (KeyValuePair<string, Market> recentMarketPair in sortedMarkets)
if (marketList.Count == 0 || marketList.Contains(recentMarketPair.Key)) { {
if (marketList.Count == 0 || marketList.Contains(recentMarketPair.Key))
{
bool excludeMainCurrency = systemConfiguration.AnalyzerSettings.MarketAnalyzer.ExcludeMainCurrency; bool excludeMainCurrency = systemConfiguration.AnalyzerSettings.MarketAnalyzer.ExcludeMainCurrency;
if (!marketTrend.ExcludeMainCurrency) { if (!marketTrend.ExcludeMainCurrency)
{
excludeMainCurrency = marketTrend.ExcludeMainCurrency; excludeMainCurrency = marketTrend.ExcludeMainCurrency;
} }
if (platform.Equals("CoinMarketCap", StringComparison.InvariantCulture) && excludeMainCurrency) { if (platform.Equals("CoinMarketCap", StringComparison.InvariantCulture) && excludeMainCurrency)
{
// Check if this is the main currency (only for CoinMarketCap) // Check if this is the main currency (only for CoinMarketCap)
if (recentMarketPair.Value.Symbol.Equals(mainMarket, StringComparison.InvariantCultureIgnoreCase)) { if (recentMarketPair.Value.Symbol.Equals(mainMarket, StringComparison.InvariantCultureIgnoreCase))
{
// If the current market is the main currency, skip it // If the current market is the main currency, skip it
continue; continue;
@ -293,27 +366,33 @@ namespace Core.MarketAnalyzer {
} }
Market recentMarket = recentMarkets[recentMarketPair.Key]; Market recentMarket = recentMarkets[recentMarketPair.Key];
if (trendMarkets.ContainsKey(recentMarketPair.Key)) { if (trendMarkets.ContainsKey(recentMarketPair.Key))
{
List<string> ignoredMarkets = SystemHelper.ConvertTokenStringToList(marketTrend.IgnoredMarkets, ","); List<string> ignoredMarkets = SystemHelper.ConvertTokenStringToList(marketTrend.IgnoredMarkets, ",");
if (ignoredMarkets.Contains(recentMarketPair.Value.Symbol)) { if (ignoredMarkets.Contains(recentMarketPair.Value.Symbol))
{
log.DoLogDebug(platform + " - Market trend '" + marketTrend.Name + "' for '" + recentMarketPair.Key + "' is ignored in this trend."); log.DoLogDebug(platform + " - Market trend '" + marketTrend.Name + "' for '" + recentMarketPair.Key + "' is ignored in this trend.");
continue; continue;
} }
List<string> allowedMarkets = SystemHelper.ConvertTokenStringToList(marketTrend.AllowedMarkets, ","); List<string> allowedMarkets = SystemHelper.ConvertTokenStringToList(marketTrend.AllowedMarkets, ",");
if (allowedMarkets.Count > 0 && !allowedMarkets.Contains(recentMarketPair.Value.Symbol)) { if (allowedMarkets.Count > 0 && !allowedMarkets.Contains(recentMarketPair.Value.Symbol))
{
log.DoLogDebug(platform + " - Market trend '" + marketTrend.Name + "' for '" + recentMarketPair.Key + "' is not allowed in this trend."); log.DoLogDebug(platform + " - Market trend '" + marketTrend.Name + "' for '" + recentMarketPair.Key + "' is not allowed in this trend.");
continue; continue;
} }
Market trendMarket = trendMarkets[recentMarketPair.Key]; Market trendMarket = trendMarkets[recentMarketPair.Key];
if (trendMarket != null) { if (trendMarket != null)
{
double recentMarketPrice = recentMarket.Price; double recentMarketPrice = recentMarket.Price;
double trendMarketPrice = trendMarket.Price; double trendMarketPrice = trendMarket.Price;
if (!platform.Equals("CoinMarketCap", StringComparison.InvariantCulture) && marketTrend.TrendCurrency.Equals("Fiat", StringComparison.InvariantCultureIgnoreCase)) { if (!platform.Equals("CoinMarketCap", StringComparison.InvariantCulture) && marketTrend.TrendCurrency.Equals("Fiat", StringComparison.InvariantCultureIgnoreCase))
if (recentMarket.MainCurrencyPriceUSD > 0 && trendMarket.MainCurrencyPriceUSD > 0) { {
if (recentMarket.MainCurrencyPriceUSD > 0 && trendMarket.MainCurrencyPriceUSD > 0)
{
recentMarketPrice = recentMarketPrice * recentMarket.MainCurrencyPriceUSD; recentMarketPrice = recentMarketPrice * recentMarket.MainCurrencyPriceUSD;
trendMarketPrice = trendMarketPrice * trendMarket.MainCurrencyPriceUSD; trendMarketPrice = trendMarketPrice * trendMarket.MainCurrencyPriceUSD;
} }
@ -340,7 +419,8 @@ namespace Core.MarketAnalyzer {
} }
} }
if (marketTrend.MaxMarkets > 0 && isGlobal) { if (marketTrend.MaxMarkets > 0 && isGlobal)
{
int maxMarkets = (marketTrend.MaxMarkets <= result.Count) ? marketTrend.MaxMarkets : result.Count; int maxMarkets = (marketTrend.MaxMarkets <= result.Count) ? marketTrend.MaxMarkets : result.Count;
result = result.GetRange(0, maxMarkets); result = result.GetRange(0, maxMarkets);
@ -349,29 +429,38 @@ namespace Core.MarketAnalyzer {
return result; return result;
} }
public static Dictionary<string, double> BuildGlobalMarketTrends(Dictionary<string, List<MarketTrendChange>> globalMarketTrendChanges, PTMagicConfiguration systemConfiguration, LogHelper log) { public static Dictionary<string, double> BuildGlobalMarketTrends(Dictionary<string, List<MarketTrendChange>> globalMarketTrendChanges, PTMagicConfiguration systemConfiguration, LogHelper log)
{
Dictionary<string, double> result = new Dictionary<string, double>(); Dictionary<string, double> result = new Dictionary<string, double>();
List<MarketTrend> marketTrends = systemConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends; List<MarketTrend> marketTrends = systemConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends;
if (marketTrends.Count > 0) { if (marketTrends.Count > 0)
foreach (MarketTrend marketTrend in marketTrends) { {
foreach (MarketTrend marketTrend in marketTrends)
{
log.DoLogInfo("Building market trend average for '" + marketTrend.Name + "'"); log.DoLogInfo("Building market trend average for '" + marketTrend.Name + "'");
if (globalMarketTrendChanges.ContainsKey(marketTrend.Name)) { if (globalMarketTrendChanges.ContainsKey(marketTrend.Name))
{
List<MarketTrendChange> marketTrendChanges = globalMarketTrendChanges[marketTrend.Name]; List<MarketTrendChange> marketTrendChanges = globalMarketTrendChanges[marketTrend.Name];
if (marketTrendChanges != null && marketTrendChanges.Count > 0) { if (marketTrendChanges != null && marketTrendChanges.Count > 0)
{
double averageTrendChange = marketTrendChanges.Average(mtc => mtc.TrendChange); double averageTrendChange = marketTrendChanges.Average(mtc => mtc.TrendChange);
result.Add(marketTrend.Name, averageTrendChange); result.Add(marketTrend.Name, averageTrendChange);
log.DoLogInfo("Built average market trend change '" + marketTrend.Name + "' (" + averageTrendChange.ToString("#,#0.00") + "% in " + marketTrend.TrendMinutes.ToString() + " minutes) for " + marketTrendChanges.Count.ToString() + " markets."); log.DoLogInfo("Built average market trend change '" + marketTrend.Name + "' (" + averageTrendChange.ToString("#,#0.00") + "% in " + marketTrend.TrendMinutes.ToString() + " minutes) for " + marketTrendChanges.Count.ToString() + " markets.");
} else { }
else
{
result.Add(marketTrend.Name, 0); result.Add(marketTrend.Name, 0);
log.DoLogWarn("No market trend changes found for '" + marketTrend.Name + "' - returning 0%"); log.DoLogWarn("No market trend changes found for '" + marketTrend.Name + "' - returning 0%");
} }
} else { }
else
{
result.Add(marketTrend.Name, 0); result.Add(marketTrend.Name, 0);
log.DoLogWarn("Market trend '" + marketTrend.Name + "' not found in globalMarketTrendChanges[] - returning 0%"); log.DoLogWarn("Market trend '" + marketTrend.Name + "' not found in globalMarketTrendChanges[] - returning 0%");

View File

@ -10,52 +10,71 @@ using Newtonsoft.Json;
using Core.ProfitTrailer; using Core.ProfitTrailer;
using System.Net; using System.Net;
namespace Core.MarketAnalyzer { namespace Core.MarketAnalyzer
public class Binance : BaseAnalyzer { {
public static double GetMainCurrencyPrice(string mainMarket, PTMagicConfiguration systemConfiguration, LogHelper log) { public class Binance : BaseAnalyzer
{
public static double GetMainCurrencyPrice(string mainMarket, PTMagicConfiguration systemConfiguration, LogHelper log)
{
double result = 0; double result = 0;
try { try
{
string baseUrl = "https://api.binance.com/api/v1/ticker/24hr?symbol=" + mainMarket + "USDT"; string baseUrl = "https://api.binance.com/api/v1/ticker/24hr?symbol=" + mainMarket + "USDT";
log.DoLogInfo("Binance - Getting main market price..."); log.DoLogInfo("Binance - Getting main market price...");
Newtonsoft.Json.Linq.JObject jsonObject = GetSimpleJsonObjectFromURL(baseUrl, log, false); Newtonsoft.Json.Linq.JObject jsonObject = GetSimpleJsonObjectFromURL(baseUrl, log, false);
if (jsonObject != null) { if (jsonObject != null)
{
log.DoLogInfo("Binance - Market data received for " + mainMarket + "USDT"); log.DoLogInfo("Binance - Market data received for " + mainMarket + "USDT");
result = (double)jsonObject.GetValue("lastPrice"); result = (double)jsonObject.GetValue("lastPrice");
log.DoLogInfo("Binance - Current price for " + mainMarket + "USDT: " + result.ToString("#,#0.00") + " USD"); log.DoLogInfo("Binance - Current price for " + mainMarket + "USDT: " + result.ToString("#,#0.00") + " USD");
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return result; return result;
} }
public static List<string> GetMarketData(string mainMarket, Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { public static List<string> GetMarketData(string mainMarket, Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log)
{
List<string> result = new List<string>(); List<string> result = new List<string>();
string lastMarket = ""; string lastMarket = "";
Newtonsoft.Json.Linq.JObject lastTicker = null; Newtonsoft.Json.Linq.JObject lastTicker = null;
try { try
{
string baseUrl = "https://api.binance.com/api/v1/ticker/24hr"; string baseUrl = "https://api.binance.com/api/v1/ticker/24hr";
log.DoLogInfo("Binance - Getting market data..."); log.DoLogInfo("Binance - Getting market data...");
Newtonsoft.Json.Linq.JArray jsonArray = GetSimpleJsonArrayFromURL(baseUrl, log); Newtonsoft.Json.Linq.JArray jsonArray = GetSimpleJsonArrayFromURL(baseUrl, log);
if (jsonArray.Count > 0) { if (jsonArray.Count > 0)
{
double mainCurrencyPrice = 1; double mainCurrencyPrice = 1;
if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase)) { if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase))
{
mainCurrencyPrice = Binance.GetMainCurrencyPrice(mainMarket, systemConfiguration, log); mainCurrencyPrice = Binance.GetMainCurrencyPrice(mainMarket, systemConfiguration, log);
} }
log.DoLogInfo("Binance - Market data received for " + jsonArray.Count.ToString() + " currencies"); log.DoLogInfo("Binance - Market data received for " + jsonArray.Count.ToString() + " currencies");
if (mainCurrencyPrice > 0) { if (mainCurrencyPrice > 0)
{
Dictionary<string, Market> markets = new Dictionary<string, Market>(); Dictionary<string, Market> markets = new Dictionary<string, Market>();
foreach (Newtonsoft.Json.Linq.JObject currencyTicker in jsonArray) { foreach (Newtonsoft.Json.Linq.JObject currencyTicker in jsonArray)
{
string marketName = currencyTicker["symbol"].ToString(); string marketName = currencyTicker["symbol"].ToString();
if (marketName.EndsWith(mainMarket, StringComparison.InvariantCultureIgnoreCase)) { //New variables for filtering out bad markets
float marketLastPrice = currencyTicker["lastPrice"].ToObject<float>();
float marketVolume = currencyTicker["volume"].ToObject<float>();
if (marketName.EndsWith(mainMarket, StringComparison.InvariantCultureIgnoreCase))
{
if(marketLastPrice > 0 && marketVolume > 0 )
{
// Set last values in case any error occurs // Set last values in case any error occurs
lastMarket = marketName; lastMarket = marketName;
@ -72,6 +91,12 @@ namespace Core.MarketAnalyzer {
markets.Add(market.Name, market); markets.Add(market.Name, market);
result.Add(market.Name); result.Add(market.Name);
}
else
{
//Let the user know that the problem market was ignored.
log.DoLogInfo("Binance - Ignoring bad market data for " + marketName);
}
} }
} }
@ -89,23 +114,33 @@ namespace Core.MarketAnalyzer {
FileHelper.CleanupFiles(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar, systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours); FileHelper.CleanupFiles(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar, systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours);
log.DoLogInfo("Binance - Market data cleaned."); log.DoLogInfo("Binance - Market data cleaned.");
} else { }
else
{
log.DoLogError("Binance - Failed to get main market price for " + mainMarket + "."); log.DoLogError("Binance - Failed to get main market price for " + mainMarket + ".");
result = null; result = null;
} }
} }
} catch (WebException ex) { }
if (ex.Response != null) { catch (WebException ex)
using (HttpWebResponse errorResponse = (HttpWebResponse)ex.Response) { {
using (StreamReader reader = new StreamReader(errorResponse.GetResponseStream())) { if (ex.Response != null)
{
using (HttpWebResponse errorResponse = (HttpWebResponse)ex.Response)
{
using (StreamReader reader = new StreamReader(errorResponse.GetResponseStream()))
{
Dictionary<string, string> errorData = JsonConvert.DeserializeObject<Dictionary<string, string>>(reader.ReadToEnd()); Dictionary<string, string> errorData = JsonConvert.DeserializeObject<Dictionary<string, string>>(reader.ReadToEnd());
if (errorData != null) { if (errorData != null)
{
string errorMessage = "Unable to get data from Binance with URL '" + errorResponse.ResponseUri + "'!"; string errorMessage = "Unable to get data from Binance with URL '" + errorResponse.ResponseUri + "'!";
if (errorData.ContainsKey("code")) { if (errorData.ContainsKey("code"))
{
errorMessage += " - Code: " + errorData["code"]; errorMessage += " - Code: " + errorData["code"];
} }
if (errorData.ContainsKey("msg")) { if (errorData.ContainsKey("msg"))
{
errorMessage += " - Message: " + errorData["msg"]; errorMessage += " - Message: " + errorData["msg"];
} }
@ -115,7 +150,9 @@ namespace Core.MarketAnalyzer {
} }
} }
result = null; result = null;
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical("Exception while getting data for '" + lastMarket + "': " + ex.Message, ex); log.DoLogCritical("Exception while getting data for '" + lastMarket + "': " + ex.Message, ex);
result = null; result = null;
} }
@ -123,24 +160,31 @@ namespace Core.MarketAnalyzer {
return result; return result;
} }
public static void CheckFirstSeenDates(Dictionary<string, Market> markets, ref Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { public static void CheckFirstSeenDates(Dictionary<string, Market> markets, ref Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log)
{
log.DoLogInfo("Binance - Checking first seen dates for " + markets.Count + " markets. This may take a while..."); log.DoLogInfo("Binance - Checking first seen dates for " + markets.Count + " markets. This may take a while...");
int marketsChecked = 0; int marketsChecked = 0;
foreach (string key in markets.Keys) { foreach (string key in markets.Keys)
{
// Save market info // Save market info
MarketInfo marketInfo = null; MarketInfo marketInfo = null;
if (marketInfos.ContainsKey(key)) { if (marketInfos.ContainsKey(key))
{
marketInfo = marketInfos[key]; marketInfo = marketInfos[key];
} }
if (marketInfo == null) { if (marketInfo == null)
{
marketInfo = new MarketInfo(); marketInfo = new MarketInfo();
marketInfo.Name = key; marketInfo.Name = key;
marketInfos.Add(key, marketInfo); marketInfos.Add(key, marketInfo);
marketInfo.FirstSeen = Binance.GetFirstSeenDate(key, systemConfiguration, log); marketInfo.FirstSeen = Binance.GetFirstSeenDate(key, systemConfiguration, log);
} else { }
if (marketInfo.FirstSeen == Constants.confMinDate) { else
{
if (marketInfo.FirstSeen == Constants.confMinDate)
{
marketInfo.FirstSeen = Binance.GetFirstSeenDate(key, systemConfiguration, log); marketInfo.FirstSeen = Binance.GetFirstSeenDate(key, systemConfiguration, log);
} }
} }
@ -148,13 +192,15 @@ namespace Core.MarketAnalyzer {
marketsChecked++; marketsChecked++;
if ((marketsChecked % 20) == 0) { if ((marketsChecked % 20) == 0)
{
log.DoLogInfo("Binance - Yes, I am still checking first seen dates... " + marketsChecked + "/" + markets.Count + " markets done..."); log.DoLogInfo("Binance - Yes, I am still checking first seen dates... " + marketsChecked + "/" + markets.Count + " markets done...");
} }
} }
} }
public static DateTime GetFirstSeenDate(string marketName, PTMagicConfiguration systemConfiguration, LogHelper log) { public static DateTime GetFirstSeenDate(string marketName, PTMagicConfiguration systemConfiguration, LogHelper log)
{
DateTime result = Constants.confMinDate; DateTime result = Constants.confMinDate;
string baseUrl = "https://api.binance.com/api/v1/klines?interval=1d&symbol=" + marketName + "&limit=100"; string baseUrl = "https://api.binance.com/api/v1/klines?interval=1d&symbol=" + marketName + "&limit=100";
@ -162,7 +208,8 @@ namespace Core.MarketAnalyzer {
log.DoLogDebug("Binance - Getting first seen date for '" + marketName + "'..."); log.DoLogDebug("Binance - Getting first seen date for '" + marketName + "'...");
Newtonsoft.Json.Linq.JArray jsonArray = GetSimpleJsonArrayFromURL(baseUrl, log); Newtonsoft.Json.Linq.JArray jsonArray = GetSimpleJsonArrayFromURL(baseUrl, log);
if (jsonArray.Count > 0) { if (jsonArray.Count > 0)
{
result = Constants.Epoch.AddMilliseconds((Int64)jsonArray[0][0]); result = Constants.Epoch.AddMilliseconds((Int64)jsonArray[0][0]);
log.DoLogDebug("Binance - First seen date for '" + marketName + "' set to " + result.ToString()); log.DoLogDebug("Binance - First seen date for '" + marketName + "' set to " + result.ToString());
} }
@ -170,29 +217,35 @@ namespace Core.MarketAnalyzer {
return result; return result;
} }
public static List<MarketTick> GetMarketTicks(string marketName, int ticksNeeded, PTMagicConfiguration systemConfiguration, LogHelper log) { public static List<MarketTick> GetMarketTicks(string marketName, int ticksNeeded, PTMagicConfiguration systemConfiguration, LogHelper log)
{
List<MarketTick> result = new List<MarketTick>(); List<MarketTick> result = new List<MarketTick>();
try { try
{
Int64 endTime = (Int64)Math.Ceiling(DateTime.Now.ToUniversalTime().Subtract(Constants.Epoch).TotalMilliseconds); Int64 endTime = (Int64)Math.Ceiling(DateTime.Now.ToUniversalTime().Subtract(Constants.Epoch).TotalMilliseconds);
int ticksLimit = 500; int ticksLimit = 500;
string baseUrl = ""; string baseUrl = "";
int ticksFetched = 0; int ticksFetched = 0;
if (ticksNeeded < ticksLimit) { if (ticksNeeded < ticksLimit)
{
ticksLimit = ticksNeeded; ticksLimit = ticksNeeded;
} }
bool go = true; bool go = true;
while (ticksFetched < ticksNeeded && go) { while (ticksFetched < ticksNeeded && go)
{
baseUrl = "https://api.binance.com/api/v1/klines?interval=1m&symbol=" + marketName + "&endTime=" + endTime.ToString() + "&limit=" + ticksLimit.ToString(); baseUrl = "https://api.binance.com/api/v1/klines?interval=1m&symbol=" + marketName + "&endTime=" + endTime.ToString() + "&limit=" + ticksLimit.ToString();
log.DoLogDebug("Binance - Getting " + ticksLimit.ToString() + " ticks for '" + marketName + "'..."); log.DoLogDebug("Binance - Getting " + ticksLimit.ToString() + " ticks for '" + marketName + "'...");
Newtonsoft.Json.Linq.JArray jsonArray = GetSimpleJsonArrayFromURL(baseUrl, log); Newtonsoft.Json.Linq.JArray jsonArray = GetSimpleJsonArrayFromURL(baseUrl, log);
if (jsonArray.Count > 0) { if (jsonArray.Count > 0)
{
log.DoLogDebug("Binance - " + jsonArray.Count.ToString() + " ticks received."); log.DoLogDebug("Binance - " + jsonArray.Count.ToString() + " ticks received.");
foreach (Newtonsoft.Json.Linq.JArray marketTick in jsonArray) { foreach (Newtonsoft.Json.Linq.JArray marketTick in jsonArray)
{
MarketTick tick = new MarketTick(); MarketTick tick = new MarketTick();
tick.Price = (double)marketTick[4]; tick.Price = (double)marketTick[4];
@ -204,26 +257,37 @@ namespace Core.MarketAnalyzer {
ticksFetched = ticksFetched + jsonArray.Count; ticksFetched = ticksFetched + jsonArray.Count;
endTime = endTime - ticksLimit * 60 * 1000; endTime = endTime - ticksLimit * 60 * 1000;
if (ticksNeeded - ticksFetched < ticksLimit) { if (ticksNeeded - ticksFetched < ticksLimit)
{
ticksLimit = ticksNeeded - ticksFetched; ticksLimit = ticksNeeded - ticksFetched;
} }
} else { }
else
{
log.DoLogDebug("Binance - No ticks received."); log.DoLogDebug("Binance - No ticks received.");
go = false; go = false;
} }
} }
} catch (WebException ex) { }
if (ex.Response != null) { catch (WebException ex)
using (HttpWebResponse errorResponse = (HttpWebResponse)ex.Response) { {
using (StreamReader reader = new StreamReader(errorResponse.GetResponseStream())) { if (ex.Response != null)
{
using (HttpWebResponse errorResponse = (HttpWebResponse)ex.Response)
{
using (StreamReader reader = new StreamReader(errorResponse.GetResponseStream()))
{
Dictionary<string, string> errorData = JsonConvert.DeserializeObject<Dictionary<string, string>>(reader.ReadToEnd()); Dictionary<string, string> errorData = JsonConvert.DeserializeObject<Dictionary<string, string>>(reader.ReadToEnd());
if (errorData != null) { if (errorData != null)
{
string errorMessage = "Unable to get data from Binance with URL '" + errorResponse.ResponseUri + "'!"; string errorMessage = "Unable to get data from Binance with URL '" + errorResponse.ResponseUri + "'!";
if (errorData.ContainsKey("code")) { if (errorData.ContainsKey("code"))
{
errorMessage += " - Code: " + errorData["code"]; errorMessage += " - Code: " + errorData["code"];
} }
if (errorData.ContainsKey("msg")) { if (errorData.ContainsKey("msg"))
{
errorMessage += " - Message: " + errorData["msg"]; errorMessage += " - Message: " + errorData["msg"];
} }
@ -233,17 +297,21 @@ namespace Core.MarketAnalyzer {
} }
} }
result = null; result = null;
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return result; return result;
} }
public static void CheckForMarketDataRecreation(string mainMarket, Dictionary<string, Market> markets, PTMagicConfiguration systemConfiguration, LogHelper log) { public static void CheckForMarketDataRecreation(string mainMarket, Dictionary<string, Market> markets, PTMagicConfiguration systemConfiguration, LogHelper log)
{
string binanceDataDirectoryPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar; string binanceDataDirectoryPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar;
if (!Directory.Exists(binanceDataDirectoryPath)) { if (!Directory.Exists(binanceDataDirectoryPath))
{
Directory.CreateDirectory(binanceDataDirectoryPath); Directory.CreateDirectory(binanceDataDirectoryPath);
} }
@ -253,22 +321,27 @@ namespace Core.MarketAnalyzer {
DateTime latestMarketDataFileDateTime = Constants.confMinDate; DateTime latestMarketDataFileDateTime = Constants.confMinDate;
List<FileInfo> marketFiles = dataDirectory.EnumerateFiles("MarketData*").ToList(); List<FileInfo> marketFiles = dataDirectory.EnumerateFiles("MarketData*").ToList();
FileInfo latestMarketDataFile = null; FileInfo latestMarketDataFile = null;
if (marketFiles.Count > 0) { if (marketFiles.Count > 0)
{
latestMarketDataFile = marketFiles.OrderByDescending(mdf => mdf.LastWriteTimeUtc).First(); latestMarketDataFile = marketFiles.OrderByDescending(mdf => mdf.LastWriteTimeUtc).First();
latestMarketDataFileDateTime = latestMarketDataFile.LastWriteTimeUtc; latestMarketDataFileDateTime = latestMarketDataFile.LastWriteTimeUtc;
} }
if (latestMarketDataFileDateTime < DateTime.Now.ToUniversalTime().AddMinutes(-20)) { if (latestMarketDataFileDateTime < DateTime.Now.ToUniversalTime().AddMinutes(-20))
{
int lastMarketDataAgeInSeconds = (int)Math.Ceiling(DateTime.Now.ToUniversalTime().Subtract(latestMarketDataFileDateTime).TotalSeconds); int lastMarketDataAgeInSeconds = (int)Math.Ceiling(DateTime.Now.ToUniversalTime().Subtract(latestMarketDataFileDateTime).TotalSeconds);
// Go back in time and create market data // Go back in time and create market data
DateTime startDateTime = DateTime.Now.ToUniversalTime(); DateTime startDateTime = DateTime.Now.ToUniversalTime();
DateTime endDateTime = DateTime.Now.ToUniversalTime().AddHours(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours); DateTime endDateTime = DateTime.Now.ToUniversalTime().AddHours(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours);
if (latestMarketDataFileDateTime != Constants.confMinDate && latestMarketDataFileDateTime > endDateTime) { if (latestMarketDataFileDateTime != Constants.confMinDate && latestMarketDataFileDateTime > endDateTime)
{
// Existing market files too old => Recreate market data for configured timeframe // Existing market files too old => Recreate market data for configured timeframe
log.DoLogInfo("Binance - Recreating market data for " + markets.Count + " markets over " + SystemHelper.GetProperDurationTime(lastMarketDataAgeInSeconds) + ". This may take a while..."); log.DoLogInfo("Binance - Recreating market data for " + markets.Count + " markets over " + SystemHelper.GetProperDurationTime(lastMarketDataAgeInSeconds) + ". This may take a while...");
endDateTime = latestMarketDataFileDateTime; endDateTime = latestMarketDataFileDateTime;
} else { }
else
{
// No existing market files found => Recreate market data for configured timeframe // No existing market files found => Recreate market data for configured timeframe
log.DoLogInfo("Binance - Recreating market data for " + markets.Count + " markets over " + systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours + " hours. This may take a while..."); log.DoLogInfo("Binance - Recreating market data for " + markets.Count + " markets over " + systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours + " hours. This may take a while...");
} }
@ -277,17 +350,20 @@ namespace Core.MarketAnalyzer {
// Get Ticks for main market // Get Ticks for main market
List<MarketTick> mainMarketTicks = new List<MarketTick>(); List<MarketTick> mainMarketTicks = new List<MarketTick>();
if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase)) { if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase))
{
mainMarketTicks = Binance.GetMarketTicks(mainMarket + "USDT", totalTicks, systemConfiguration, log); mainMarketTicks = Binance.GetMarketTicks(mainMarket + "USDT", totalTicks, systemConfiguration, log);
} }
// Get Ticks for all markets // Get Ticks for all markets
log.DoLogDebug("Binance - Getting ticks for '" + markets.Count + "' markets"); log.DoLogDebug("Binance - Getting ticks for '" + markets.Count + "' markets");
Dictionary<string, List<MarketTick>> marketTicks = new Dictionary<string, List<MarketTick>>(); Dictionary<string, List<MarketTick>> marketTicks = new Dictionary<string, List<MarketTick>>();
foreach (string key in markets.Keys) { foreach (string key in markets.Keys)
{
marketTicks.Add(key, Binance.GetMarketTicks(key, totalTicks, systemConfiguration, log)); marketTicks.Add(key, Binance.GetMarketTicks(key, totalTicks, systemConfiguration, log));
if ((marketTicks.Count % 10) == 0) { if ((marketTicks.Count % 10) == 0)
{
log.DoLogInfo("Binance - No worries, I am still alive... " + marketTicks.Count + "/" + markets.Count + " markets done..."); log.DoLogInfo("Binance - No worries, I am still alive... " + marketTicks.Count + "/" + markets.Count + " markets done...");
} }
} }
@ -298,24 +374,30 @@ namespace Core.MarketAnalyzer {
// Go back in time and create market data // Go back in time and create market data
int completedTicks = 0; int completedTicks = 0;
if (marketTicks.Count > 0) { if (marketTicks.Count > 0)
for (DateTime tickTime = startDateTime; tickTime >= endDateTime; tickTime = tickTime.AddMinutes(-1)) { {
for (DateTime tickTime = startDateTime; tickTime >= endDateTime; tickTime = tickTime.AddMinutes(-1))
{
completedTicks++; completedTicks++;
double mainCurrencyPrice = 1; double mainCurrencyPrice = 1;
if (mainMarketTicks.Count > 0) { if (mainMarketTicks.Count > 0)
{
List<MarketTick> mainCurrencyTickRange = mainMarketTicks.FindAll(t => t.Time <= tickTime); List<MarketTick> mainCurrencyTickRange = mainMarketTicks.FindAll(t => t.Time <= tickTime);
if (mainCurrencyTickRange.Count > 0) { if (mainCurrencyTickRange.Count > 0)
{
MarketTick mainCurrencyTick = mainCurrencyTickRange.OrderByDescending(t => t.Time).First(); MarketTick mainCurrencyTick = mainCurrencyTickRange.OrderByDescending(t => t.Time).First();
mainCurrencyPrice = mainCurrencyTick.Price; mainCurrencyPrice = mainCurrencyTick.Price;
} }
} }
Dictionary<string, Market> tickMarkets = new Dictionary<string, Market>(); Dictionary<string, Market> tickMarkets = new Dictionary<string, Market>();
foreach (string key in markets.Keys) { foreach (string key in markets.Keys)
{
List<MarketTick> tickRange = marketTicks[key].FindAll(t => t.Time <= tickTime); List<MarketTick> tickRange = marketTicks[key].FindAll(t => t.Time <= tickTime);
if (tickRange.Count > 0) { if (tickRange.Count > 0)
{
MarketTick marketTick = tickRange.OrderByDescending(t => t.Time).First(); MarketTick marketTick = tickRange.OrderByDescending(t => t.Time).First();
Market market = new Market(); Market market = new Market();
@ -336,7 +418,8 @@ namespace Core.MarketAnalyzer {
log.DoLogDebug("Binance - Market data saved for tick " + fileDateTime.ToString() + " - MainCurrencyPrice=" + mainCurrencyPrice.ToString("#,#0.00") + " USD."); log.DoLogDebug("Binance - Market data saved for tick " + fileDateTime.ToString() + " - MainCurrencyPrice=" + mainCurrencyPrice.ToString("#,#0.00") + " USD.");
if ((completedTicks % 100) == 0) { if ((completedTicks % 100) == 0)
{
log.DoLogInfo("Binance - Our magicbots are still at work, hang on... " + completedTicks + "/" + totalTicks + " ticks done..."); log.DoLogInfo("Binance - Our magicbots are still at work, hang on... " + completedTicks + "/" + totalTicks + " ticks done...");
} }
} }

View File

@ -9,55 +9,71 @@ using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json; using Newtonsoft.Json;
using Core.ProfitTrailer; using Core.ProfitTrailer;
namespace Core.MarketAnalyzer { namespace Core.MarketAnalyzer
public class Bittrex : BaseAnalyzer { {
public static double GetMainCurrencyPrice(string mainMarket, PTMagicConfiguration systemConfiguration, LogHelper log) { public class Bittrex : BaseAnalyzer
{
public static double GetMainCurrencyPrice(string mainMarket, PTMagicConfiguration systemConfiguration, LogHelper log)
{
double result = 0; double result = 0;
try { try
{
string baseUrl = "https://bittrex.com/api/v1.1/public/getmarketsummary?market=USDT-" + mainMarket; string baseUrl = "https://bittrex.com/api/v1.1/public/getmarketsummary?market=USDT-" + mainMarket;
log.DoLogInfo("Bittrex - Getting main market price..."); log.DoLogInfo("Bittrex - Getting main market price...");
Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, ""); Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, "");
if (jsonObject.Count > 0) { if (jsonObject.Count > 0)
if (jsonObject["success"]) { {
if (jsonObject["success"])
{
log.DoLogInfo("Bittrex - Market data received for USDT-" + mainMarket); log.DoLogInfo("Bittrex - Market data received for USDT-" + mainMarket);
result = jsonObject["result"][0]["Last"]; result = jsonObject["result"][0]["Last"];
log.DoLogInfo("Bittrex - Current price for USDT-" + mainMarket + ": " + result.ToString("#,#0.00") + " USD"); log.DoLogInfo("Bittrex - Current price for USDT-" + mainMarket + ": " + result.ToString("#,#0.00") + " USD");
} }
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return result; return result;
} }
public static List<string> GetMarketData(string mainMarket, Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { public static List<string> GetMarketData(string mainMarket, Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log)
{
List<string> result = new List<string>(); List<string> result = new List<string>();
string lastMarket = ""; string lastMarket = "";
Newtonsoft.Json.Linq.JObject lastTicker = null; Newtonsoft.Json.Linq.JObject lastTicker = null;
try { try
{
string baseUrl = "https://bittrex.com/api/v2.0/pub/markets/GetMarketSummaries"; string baseUrl = "https://bittrex.com/api/v2.0/pub/markets/GetMarketSummaries";
log.DoLogInfo("Bittrex - Getting market data..."); log.DoLogInfo("Bittrex - Getting market data...");
Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, ""); Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, "");
if (jsonObject.Count > 0) { if (jsonObject.Count > 0)
if (jsonObject["success"]) { {
if (jsonObject["success"])
{
log.DoLogInfo("Bittrex - Market data received for " + jsonObject["result"].Count.ToString() + " currencies"); log.DoLogInfo("Bittrex - Market data received for " + jsonObject["result"].Count.ToString() + " currencies");
double mainCurrencyPrice = 1; double mainCurrencyPrice = 1;
if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase)) { if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase))
{
mainCurrencyPrice = Bittrex.GetMainCurrencyPrice(mainMarket, systemConfiguration, log); mainCurrencyPrice = Bittrex.GetMainCurrencyPrice(mainMarket, systemConfiguration, log);
} }
if (mainCurrencyPrice > 0) { if (mainCurrencyPrice > 0)
{
Dictionary<string, Market> markets = new Dictionary<string, Market>(); Dictionary<string, Market> markets = new Dictionary<string, Market>();
foreach (Newtonsoft.Json.Linq.JObject currencyTicker in jsonObject["result"]) { foreach (Newtonsoft.Json.Linq.JObject currencyTicker in jsonObject["result"])
{
string marketName = currencyTicker["Summary"]["MarketName"].ToString(); string marketName = currencyTicker["Summary"]["MarketName"].ToString();
if (marketName.StartsWith(mainMarket, StringComparison.InvariantCultureIgnoreCase)) { if (marketName.StartsWith(mainMarket, StringComparison.InvariantCultureIgnoreCase))
{
// Set last values in case any error occurs // Set last values in case any error occurs
lastMarket = marketName; lastMarket = marketName;
@ -77,11 +93,13 @@ namespace Core.MarketAnalyzer {
// Save market info // Save market info
MarketInfo marketInfo = null; MarketInfo marketInfo = null;
if (marketInfos.ContainsKey(marketName)) { if (marketInfos.ContainsKey(marketName))
{
marketInfo = marketInfos[marketName]; marketInfo = marketInfos[marketName];
} }
if (marketInfo == null) { if (marketInfo == null)
{
marketInfo = new MarketInfo(); marketInfo = new MarketInfo();
marketInfo.Name = marketName; marketInfo.Name = marketName;
marketInfos.Add(marketName, marketInfo); marketInfos.Add(marketName, marketInfo);
@ -103,13 +121,17 @@ namespace Core.MarketAnalyzer {
FileHelper.CleanupFiles(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar, systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours); FileHelper.CleanupFiles(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar, systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours);
log.DoLogInfo("Bittrex - Market data cleaned."); log.DoLogInfo("Bittrex - Market data cleaned.");
} else { }
else
{
log.DoLogError("Bittrex - Failed to get main market price for " + mainMarket + "."); log.DoLogError("Bittrex - Failed to get main market price for " + mainMarket + ".");
result = null; result = null;
} }
} }
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical("Exception while getting data for '" + lastMarket + "': " + ex.Message, ex); log.DoLogCritical("Exception while getting data for '" + lastMarket + "': " + ex.Message, ex);
result = null; result = null;
} }
@ -117,20 +139,26 @@ namespace Core.MarketAnalyzer {
return result; return result;
} }
public static List<MarketTick> GetMarketTicks(string marketName, PTMagicConfiguration systemConfiguration, LogHelper log) { public static List<MarketTick> GetMarketTicks(string marketName, PTMagicConfiguration systemConfiguration, LogHelper log)
{
List<MarketTick> result = new List<MarketTick>(); List<MarketTick> result = new List<MarketTick>();
try { try
{
string baseUrl = "https://bittrex.com/Api/v2.0/pub/market/GetTicks?tickInterval=oneMin&marketName=" + marketName; string baseUrl = "https://bittrex.com/Api/v2.0/pub/market/GetTicks?tickInterval=oneMin&marketName=" + marketName;
log.DoLogDebug("Bittrex - Getting ticks for '" + marketName + "'..."); log.DoLogDebug("Bittrex - Getting ticks for '" + marketName + "'...");
Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, ""); Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, "");
if (jsonObject.Count > 0) { if (jsonObject.Count > 0)
if (jsonObject["success"]) { {
if (jsonObject["result"] != null) { if (jsonObject["success"])
{
if (jsonObject["result"] != null)
{
log.DoLogDebug("Bittrex - " + jsonObject["result"].Count.ToString() + " ticks received."); log.DoLogDebug("Bittrex - " + jsonObject["result"].Count.ToString() + " ticks received.");
foreach (var marketTick in jsonObject["result"]) { foreach (var marketTick in jsonObject["result"])
{
MarketTick tick = new MarketTick(); MarketTick tick = new MarketTick();
tick.Price = (double)marketTick["C"]; tick.Price = (double)marketTick["C"];
@ -138,22 +166,28 @@ namespace Core.MarketAnalyzer {
result.Add(tick); result.Add(tick);
} }
} else { }
else
{
log.DoLogDebug("Bittrex - No ticks received."); log.DoLogDebug("Bittrex - No ticks received.");
} }
} }
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return result; return result;
} }
public static void CheckForMarketDataRecreation(string mainMarket, Dictionary<string, Market> markets, PTMagicConfiguration systemConfiguration, LogHelper log) { public static void CheckForMarketDataRecreation(string mainMarket, Dictionary<string, Market> markets, PTMagicConfiguration systemConfiguration, LogHelper log)
{
string bittrexDataDirectoryPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar; string bittrexDataDirectoryPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar;
if (!Directory.Exists(bittrexDataDirectoryPath)) { if (!Directory.Exists(bittrexDataDirectoryPath))
{
Directory.CreateDirectory(bittrexDataDirectoryPath); Directory.CreateDirectory(bittrexDataDirectoryPath);
} }
@ -163,39 +197,47 @@ namespace Core.MarketAnalyzer {
DateTime latestMarketDataFileDateTime = Constants.confMinDate; DateTime latestMarketDataFileDateTime = Constants.confMinDate;
List<FileInfo> marketFiles = dataDirectory.EnumerateFiles("MarketData*").ToList(); List<FileInfo> marketFiles = dataDirectory.EnumerateFiles("MarketData*").ToList();
FileInfo latestMarketDataFile = null; FileInfo latestMarketDataFile = null;
if (marketFiles.Count > 0) { if (marketFiles.Count > 0)
{
latestMarketDataFile = marketFiles.OrderByDescending(mdf => mdf.LastWriteTimeUtc).First(); latestMarketDataFile = marketFiles.OrderByDescending(mdf => mdf.LastWriteTimeUtc).First();
latestMarketDataFileDateTime = latestMarketDataFile.LastWriteTimeUtc; latestMarketDataFileDateTime = latestMarketDataFile.LastWriteTimeUtc;
} }
if (latestMarketDataFileDateTime < DateTime.Now.ToUniversalTime().AddMinutes(-20)) { if (latestMarketDataFileDateTime < DateTime.Now.ToUniversalTime().AddMinutes(-20))
{
int lastMarketDataAgeInSeconds = (int)Math.Ceiling(DateTime.Now.ToUniversalTime().Subtract(latestMarketDataFileDateTime).TotalSeconds); int lastMarketDataAgeInSeconds = (int)Math.Ceiling(DateTime.Now.ToUniversalTime().Subtract(latestMarketDataFileDateTime).TotalSeconds);
// Go back in time and create market data // Go back in time and create market data
DateTime startDateTime = DateTime.Now.ToUniversalTime(); DateTime startDateTime = DateTime.Now.ToUniversalTime();
DateTime endDateTime = DateTime.Now.ToUniversalTime().AddHours(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours); DateTime endDateTime = DateTime.Now.ToUniversalTime().AddHours(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours);
if (latestMarketDataFileDateTime != Constants.confMinDate && latestMarketDataFileDateTime > endDateTime) { if (latestMarketDataFileDateTime != Constants.confMinDate && latestMarketDataFileDateTime > endDateTime)
{
// Existing market files too old => Recreate market data for configured timeframe // Existing market files too old => Recreate market data for configured timeframe
log.DoLogInfo("Bittrex - Recreating market data for " + markets.Count + " markets over " + SystemHelper.GetProperDurationTime(lastMarketDataAgeInSeconds) + ". This may take a while..."); log.DoLogInfo("Bittrex - Recreating market data for " + markets.Count + " markets over " + SystemHelper.GetProperDurationTime(lastMarketDataAgeInSeconds) + ". This may take a while...");
endDateTime = latestMarketDataFileDateTime; endDateTime = latestMarketDataFileDateTime;
} else { }
else
{
// No existing market files found => Recreate market data for configured timeframe // No existing market files found => Recreate market data for configured timeframe
log.DoLogInfo("Bittrex - Recreating market data for " + markets.Count + " markets over " + systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours + " hours. This may take a while..."); log.DoLogInfo("Bittrex - Recreating market data for " + markets.Count + " markets over " + systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours + " hours. This may take a while...");
} }
// Get Ticks for main market // Get Ticks for main market
List<MarketTick> mainMarketTicks = new List<MarketTick>(); List<MarketTick> mainMarketTicks = new List<MarketTick>();
if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase)) { if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase))
{
mainMarketTicks = Bittrex.GetMarketTicks("USDT-" + mainMarket, systemConfiguration, log); mainMarketTicks = Bittrex.GetMarketTicks("USDT-" + mainMarket, systemConfiguration, log);
} }
// Get Ticks for all markets // Get Ticks for all markets
log.DoLogDebug("Bittrex - Getting ticks for '" + markets.Count + "' markets"); log.DoLogDebug("Bittrex - Getting ticks for '" + markets.Count + "' markets");
Dictionary<string, List<MarketTick>> marketTicks = new Dictionary<string, List<MarketTick>>(); Dictionary<string, List<MarketTick>> marketTicks = new Dictionary<string, List<MarketTick>>();
foreach (string key in markets.Keys) { foreach (string key in markets.Keys)
{
marketTicks.Add(key, Bittrex.GetMarketTicks(key, systemConfiguration, log)); marketTicks.Add(key, Bittrex.GetMarketTicks(key, systemConfiguration, log));
if ((marketTicks.Count % 10) == 0) { if ((marketTicks.Count % 10) == 0)
{
log.DoLogInfo("Bittrex - No worries, I am still alive... " + marketTicks.Count + "/" + markets.Count + " markets done..."); log.DoLogInfo("Bittrex - No worries, I am still alive... " + marketTicks.Count + "/" + markets.Count + " markets done...");
} }
} }
@ -206,24 +248,30 @@ namespace Core.MarketAnalyzer {
int totalTicks = (int)Math.Ceiling(startDateTime.Subtract(endDateTime).TotalMinutes); int totalTicks = (int)Math.Ceiling(startDateTime.Subtract(endDateTime).TotalMinutes);
int completedTicks = 0; int completedTicks = 0;
if (marketTicks.Count > 0) { if (marketTicks.Count > 0)
for (DateTime tickTime = startDateTime.ToUniversalTime(); tickTime >= endDateTime.ToUniversalTime(); tickTime = tickTime.AddMinutes(-1)) { {
for (DateTime tickTime = startDateTime.ToUniversalTime(); tickTime >= endDateTime.ToUniversalTime(); tickTime = tickTime.AddMinutes(-1))
{
completedTicks++; completedTicks++;
double mainCurrencyPrice = 1; double mainCurrencyPrice = 1;
if (mainMarketTicks.Count > 0) { if (mainMarketTicks.Count > 0)
{
List<MarketTick> mainCurrencyTickRange = mainMarketTicks.FindAll(t => t.Time <= tickTime); List<MarketTick> mainCurrencyTickRange = mainMarketTicks.FindAll(t => t.Time <= tickTime);
if (mainCurrencyTickRange.Count > 0) { if (mainCurrencyTickRange.Count > 0)
{
MarketTick mainCurrencyTick = mainCurrencyTickRange.OrderByDescending(t => t.Time).First(); MarketTick mainCurrencyTick = mainCurrencyTickRange.OrderByDescending(t => t.Time).First();
mainCurrencyPrice = mainCurrencyTick.Price; mainCurrencyPrice = mainCurrencyTick.Price;
} }
} }
Dictionary<string, Market> tickMarkets = new Dictionary<string, Market>(); Dictionary<string, Market> tickMarkets = new Dictionary<string, Market>();
foreach (string key in markets.Keys) { foreach (string key in markets.Keys)
{
List<MarketTick> tickRange = marketTicks[key].FindAll(t => t.Time <= tickTime); List<MarketTick> tickRange = marketTicks[key].FindAll(t => t.Time <= tickTime);
if (tickRange.Count > 0) { if (tickRange.Count > 0)
{
MarketTick marketTick = tickRange.OrderByDescending(t => t.Time).First(); MarketTick marketTick = tickRange.OrderByDescending(t => t.Time).First();
Market market = new Market(); Market market = new Market();
@ -244,7 +292,8 @@ namespace Core.MarketAnalyzer {
log.DoLogDebug("Bittrex - Market data saved for tick " + fileDateTime.ToString() + " - MainCurrencyPrice=" + mainCurrencyPrice.ToString("#,#0.00") + " USD."); log.DoLogDebug("Bittrex - Market data saved for tick " + fileDateTime.ToString() + " - MainCurrencyPrice=" + mainCurrencyPrice.ToString("#,#0.00") + " USD.");
if ((completedTicks % 100) == 0) { if ((completedTicks % 100) == 0)
{
log.DoLogInfo("Bittrex - Our magicbots are still at work, hang on... " + completedTicks + "/" + totalTicks + " ticks done..."); log.DoLogInfo("Bittrex - Our magicbots are still at work, hang on... " + completedTicks + "/" + totalTicks + " ticks done...");
} }
} }

View File

@ -8,11 +8,15 @@ using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Core.MarketAnalyzer { namespace Core.MarketAnalyzer
public class CoinMarketCap : BaseAnalyzer { {
public static string GetMarketData(PTMagicConfiguration systemConfiguration, LogHelper log) { public class CoinMarketCap : BaseAnalyzer
{
public static string GetMarketData(PTMagicConfiguration systemConfiguration, LogHelper log)
{
string result = ""; string result = "";
try { try
{
string baseUrl = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?limit=200"; string baseUrl = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?limit=200";
string cmcAPI = systemConfiguration.GeneralSettings.Application.CoinMarketCapAPIKey; string cmcAPI = systemConfiguration.GeneralSettings.Application.CoinMarketCapAPIKey;
@ -20,26 +24,31 @@ namespace Core.MarketAnalyzer {
Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, cmcAPI); Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, cmcAPI);
if (jsonObject.Count > 0) { if (jsonObject.Count > 0)
if (jsonObject["data"] != null) { {
if (jsonObject["data"] != null)
{
log.DoLogInfo("CoinMarketCap - Market data received for " + jsonObject["data"].Count + " currencies"); log.DoLogInfo("CoinMarketCap - Market data received for " + jsonObject["data"].Count + " currencies");
Dictionary<string, Market> markets = new Dictionary<string, Market>(); Dictionary<string, Market> markets = new Dictionary<string, Market>();
for (int i = 0; i < jsonObject["data"].Count; i++){ for (int i = 0; i < jsonObject["data"].Count; i++)
{
if (jsonObject["data"][i]["quote"]["USD"] != null){ if (jsonObject["data"][i]["quote"]["USD"] != null)
Market market = new Market(); {
market.Position = markets.Count + 1; Market market = new Market();
market.Name = jsonObject["data"][i]["name"].ToString(); market.Position = markets.Count + 1;
market.Symbol = jsonObject["data"][i]["symbol"].ToString(); market.Name = jsonObject["data"][i]["name"].ToString();
market.Price = (double)jsonObject["data"][i]["quote"]["USD"]["price"]; market.Symbol = jsonObject["data"][i]["symbol"].ToString();
market.Volume24h = (double)jsonObject["data"][i]["quote"]["USD"]["volume_24h"]; market.Price = (double)jsonObject["data"][i]["quote"]["USD"]["price"];
if (!String.IsNullOrEmpty(jsonObject["data"][i]["quote"]["USD"]["percent_change_24h"].ToString())) { market.Volume24h = (double)jsonObject["data"][i]["quote"]["USD"]["volume_24h"];
market.TrendChange24h = (double)jsonObject["data"][i]["quote"]["USD"]["percent_change_24h"]; if (!String.IsNullOrEmpty(jsonObject["data"][i]["quote"]["USD"]["percent_change_24h"].ToString()))
} {
market.TrendChange24h = (double)jsonObject["data"][i]["quote"]["USD"]["percent_change_24h"];
}
markets.Add(market.Name, market); markets.Add(market.Name, market);
} }
} }
@ -56,7 +65,9 @@ namespace Core.MarketAnalyzer {
log.DoLogInfo("CoinMarketCap - Market data cleaned."); log.DoLogInfo("CoinMarketCap - Market data cleaned.");
} }
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
result = ex.Message; result = ex.Message;
} }
@ -64,10 +75,12 @@ namespace Core.MarketAnalyzer {
return result; return result;
} }
public static void CheckForMarketDataRecreation(Dictionary<string, Market> markets, PTMagicConfiguration systemConfiguration, LogHelper log) { public static void CheckForMarketDataRecreation(Dictionary<string, Market> markets, PTMagicConfiguration systemConfiguration, LogHelper log)
{
string coinMarketCapDataDirectoryPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathCoinMarketCap + Path.DirectorySeparatorChar; string coinMarketCapDataDirectoryPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathCoinMarketCap + Path.DirectorySeparatorChar;
if (!Directory.Exists(coinMarketCapDataDirectoryPath)) { if (!Directory.Exists(coinMarketCapDataDirectoryPath))
{
Directory.CreateDirectory(coinMarketCapDataDirectoryPath); Directory.CreateDirectory(coinMarketCapDataDirectoryPath);
} }
@ -80,33 +93,43 @@ namespace Core.MarketAnalyzer {
bool build24hMarketDataFile = false; bool build24hMarketDataFile = false;
FileInfo marketFile = null; FileInfo marketFile = null;
if (marketFiles.Count > 0) { if (marketFiles.Count > 0)
{
marketFile = marketFiles.First(); marketFile = marketFiles.First();
if (marketFile.LastWriteTimeUtc <= DateTime.Now.AddHours(-24).AddMinutes(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes).AddSeconds(-10)) { if (marketFile.LastWriteTimeUtc <= DateTime.Now.AddHours(-24).AddMinutes(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes).AddSeconds(-10))
{
log.DoLogDebug("CoinMarketCap - 24h market data file too old (" + marketFile.LastWriteTimeUtc.ToString() + "). Rebuilding data..."); log.DoLogDebug("CoinMarketCap - 24h market data file too old (" + marketFile.LastWriteTimeUtc.ToString() + "). Rebuilding data...");
build24hMarketDataFile = true; build24hMarketDataFile = true;
} }
} else { }
else
{
marketFiles = dataDirectory.EnumerateFiles("MarketData*") marketFiles = dataDirectory.EnumerateFiles("MarketData*")
.Select(x => { x.Refresh(); return x; }) .Select(x => { x.Refresh(); return x; })
.Where(x => x.LastWriteTimeUtc >= DateTime.Now.AddHours(-24)) .Where(x => x.LastWriteTimeUtc >= DateTime.Now.AddHours(-24))
.ToArray().OrderBy(f => f.LastWriteTimeUtc).ToList(); .ToArray().OrderBy(f => f.LastWriteTimeUtc).ToList();
if (marketFiles.Count > 0) { if (marketFiles.Count > 0)
{
marketFile = marketFiles.First(); marketFile = marketFiles.First();
if (marketFile.LastWriteTimeUtc >= DateTime.Now.AddHours(-24).AddMinutes(systemConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes).AddSeconds(10)) { if (marketFile.LastWriteTimeUtc >= DateTime.Now.AddHours(-24).AddMinutes(systemConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes).AddSeconds(10))
{
log.DoLogDebug("CoinMarketCap - 24h market data file too young (" + marketFile.LastWriteTimeUtc.ToString() + "). Rebuilding data..."); log.DoLogDebug("CoinMarketCap - 24h market data file too young (" + marketFile.LastWriteTimeUtc.ToString() + "). Rebuilding data...");
build24hMarketDataFile = true; build24hMarketDataFile = true;
} }
} else { }
else
{
log.DoLogDebug("CoinMarketCap - 24h market data not found. Rebuilding data..."); log.DoLogDebug("CoinMarketCap - 24h market data not found. Rebuilding data...");
build24hMarketDataFile = true; build24hMarketDataFile = true;
} }
} }
if (build24hMarketDataFile) { if (build24hMarketDataFile)
{
Dictionary<string, Market> markets24h = new Dictionary<string, Market>(); Dictionary<string, Market> markets24h = new Dictionary<string, Market>();
foreach (string key in markets.Keys) { foreach (string key in markets.Keys)
{
Market market24h = new Market(); Market market24h = new Market();
market24h.Position = markets.Count + 1; market24h.Position = markets.Count + 1;
market24h.Name = markets[key].Name; market24h.Name = markets[key].Name;

View File

@ -9,54 +9,69 @@ using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json; using Newtonsoft.Json;
using Core.ProfitTrailer; using Core.ProfitTrailer;
namespace Core.MarketAnalyzer { namespace Core.MarketAnalyzer
public class Poloniex : BaseAnalyzer { {
public static double GetMainCurrencyPrice(string mainMarket, PTMagicConfiguration systemConfiguration, LogHelper log) { public class Poloniex : BaseAnalyzer
{
public static double GetMainCurrencyPrice(string mainMarket, PTMagicConfiguration systemConfiguration, LogHelper log)
{
double result = 0; double result = 0;
try { try
{
string baseUrl = "https://bittrex.com/api/v1.1/public/getmarketsummary?market=USDT-" + mainMarket; string baseUrl = "https://bittrex.com/api/v1.1/public/getmarketsummary?market=USDT-" + mainMarket;
log.DoLogInfo("Poloniex - Getting main market price..."); log.DoLogInfo("Poloniex - Getting main market price...");
Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, ""); Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, "");
if (jsonObject.Count > 0) { if (jsonObject.Count > 0)
if (jsonObject["success"]) { {
if (jsonObject["success"])
{
log.DoLogInfo("Poloniex - Market data received for USDT_" + mainMarket); log.DoLogInfo("Poloniex - Market data received for USDT_" + mainMarket);
result = jsonObject["result"][0]["Last"]; result = jsonObject["result"][0]["Last"];
log.DoLogInfo("Poloniex - Current price for USDT_" + mainMarket + ": " + result.ToString("#,#0.00") + " USD"); log.DoLogInfo("Poloniex - Current price for USDT_" + mainMarket + ": " + result.ToString("#,#0.00") + " USD");
} }
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return result; return result;
} }
public static List<string> GetMarketData(string mainMarket, Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { public static List<string> GetMarketData(string mainMarket, Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log)
{
List<string> result = new List<string>(); List<string> result = new List<string>();
string lastMarket = ""; string lastMarket = "";
KeyValuePair<string, dynamic> lastTicker = new KeyValuePair<string, dynamic>(); KeyValuePair<string, dynamic> lastTicker = new KeyValuePair<string, dynamic>();
try { try
{
string baseUrl = "https://poloniex.com/public?command=returnTicker"; string baseUrl = "https://poloniex.com/public?command=returnTicker";
log.DoLogInfo("Poloniex - Getting market data..."); log.DoLogInfo("Poloniex - Getting market data...");
Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, ""); Dictionary<string, dynamic> jsonObject = GetJsonFromURL(baseUrl, log, "");
if (jsonObject.Count > 0) { if (jsonObject.Count > 0)
{
log.DoLogInfo("Poloniex - Market data received for " + jsonObject.Count.ToString() + " currencies"); log.DoLogInfo("Poloniex - Market data received for " + jsonObject.Count.ToString() + " currencies");
double mainCurrencyPrice = 1; double mainCurrencyPrice = 1;
if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase)) { if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase))
{
mainCurrencyPrice = Poloniex.GetMainCurrencyPrice(mainMarket, systemConfiguration, log); mainCurrencyPrice = Poloniex.GetMainCurrencyPrice(mainMarket, systemConfiguration, log);
} }
if (mainCurrencyPrice > 0) { if (mainCurrencyPrice > 0)
{
Dictionary<string, Market> markets = new Dictionary<string, Market>(); Dictionary<string, Market> markets = new Dictionary<string, Market>();
foreach (KeyValuePair<string, dynamic> currencyTicker in jsonObject) { foreach (KeyValuePair<string, dynamic> currencyTicker in jsonObject)
{
string marketName = currencyTicker.Key.ToString(); string marketName = currencyTicker.Key.ToString();
if (marketName.StartsWith(mainMarket, StringComparison.InvariantCultureIgnoreCase)) { if (marketName.StartsWith(mainMarket, StringComparison.InvariantCultureIgnoreCase))
{
// Set last values in case any error occurs // Set last values in case any error occurs
lastMarket = marketName; lastMarket = marketName;
@ -91,12 +106,16 @@ namespace Core.MarketAnalyzer {
FileHelper.CleanupFiles(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar, systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours); FileHelper.CleanupFiles(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar, systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours);
log.DoLogInfo("Poloniex - Market data cleaned."); log.DoLogInfo("Poloniex - Market data cleaned.");
} else { }
else
{
log.DoLogError("Poloniex - Failed to get main market price for " + mainMarket + "."); log.DoLogError("Poloniex - Failed to get main market price for " + mainMarket + ".");
result = null; result = null;
} }
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical("Exception while getting data for '" + lastMarket + "': " + ex.Message, ex); log.DoLogCritical("Exception while getting data for '" + lastMarket + "': " + ex.Message, ex);
result = null; result = null;
} }
@ -104,23 +123,30 @@ namespace Core.MarketAnalyzer {
return result; return result;
} }
public static void CheckFirstSeenDates(Dictionary<string, Market> markets, ref Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) { public static void CheckFirstSeenDates(Dictionary<string, Market> markets, ref Dictionary<string, MarketInfo> marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log)
{
log.DoLogInfo("Poloniex - Checking first seen dates for " + markets.Count + " markets. This may take a while..."); log.DoLogInfo("Poloniex - Checking first seen dates for " + markets.Count + " markets. This may take a while...");
int marketsChecked = 0; int marketsChecked = 0;
foreach (string key in markets.Keys) { foreach (string key in markets.Keys)
{
// Save market info // Save market info
MarketInfo marketInfo = null; MarketInfo marketInfo = null;
if (marketInfos.ContainsKey(key)) { if (marketInfos.ContainsKey(key))
{
marketInfo = marketInfos[key]; marketInfo = marketInfos[key];
} }
if (marketInfo == null) { if (marketInfo == null)
{
marketInfo = new MarketInfo(); marketInfo = new MarketInfo();
marketInfo.Name = key; marketInfo.Name = key;
marketInfos.Add(key, marketInfo); marketInfos.Add(key, marketInfo);
marketInfo.FirstSeen = Poloniex.GetFirstSeenDate(key, systemConfiguration, log); marketInfo.FirstSeen = Poloniex.GetFirstSeenDate(key, systemConfiguration, log);
} else { }
if (marketInfo.FirstSeen == Constants.confMinDate) { else
{
if (marketInfo.FirstSeen == Constants.confMinDate)
{
marketInfo.FirstSeen = Poloniex.GetFirstSeenDate(key, systemConfiguration, log); marketInfo.FirstSeen = Poloniex.GetFirstSeenDate(key, systemConfiguration, log);
} }
} }
@ -128,13 +154,15 @@ namespace Core.MarketAnalyzer {
marketsChecked++; marketsChecked++;
if ((marketsChecked % 20) == 0) { if ((marketsChecked % 20) == 0)
{
log.DoLogInfo("Poloniex - Yes, I am still checking first seen dates... " + marketsChecked + "/" + markets.Count + " markets done..."); log.DoLogInfo("Poloniex - Yes, I am still checking first seen dates... " + marketsChecked + "/" + markets.Count + " markets done...");
} }
} }
} }
public static DateTime GetFirstSeenDate(string marketName, PTMagicConfiguration systemConfiguration, LogHelper log) { public static DateTime GetFirstSeenDate(string marketName, PTMagicConfiguration systemConfiguration, LogHelper log)
{
DateTime result = Constants.confMinDate; DateTime result = Constants.confMinDate;
Int64 startTime = (Int64)Math.Ceiling(DateTime.Now.ToUniversalTime().AddDays(-100).Subtract(Constants.Epoch).TotalSeconds); Int64 startTime = (Int64)Math.Ceiling(DateTime.Now.ToUniversalTime().AddDays(-100).Subtract(Constants.Epoch).TotalSeconds);
@ -143,7 +171,8 @@ namespace Core.MarketAnalyzer {
log.DoLogDebug("Poloniex - Getting first seen date for '" + marketName + "'..."); log.DoLogDebug("Poloniex - Getting first seen date for '" + marketName + "'...");
List<dynamic> jsonObject = GetSimpleJsonListFromURL(baseUrl, log); List<dynamic> jsonObject = GetSimpleJsonListFromURL(baseUrl, log);
if (jsonObject.Count > 0) { if (jsonObject.Count > 0)
{
var marketTick = jsonObject[0]; var marketTick = jsonObject[0];
result = Constants.Epoch.AddSeconds((int)marketTick["date"]); result = Constants.Epoch.AddSeconds((int)marketTick["date"]);
@ -153,19 +182,23 @@ namespace Core.MarketAnalyzer {
return result; return result;
} }
public static List<MarketTick> GetMarketTicks(string marketName, PTMagicConfiguration systemConfiguration, LogHelper log) { public static List<MarketTick> GetMarketTicks(string marketName, PTMagicConfiguration systemConfiguration, LogHelper log)
{
List<MarketTick> result = new List<MarketTick>(); List<MarketTick> result = new List<MarketTick>();
try { try
{
Int64 startTime = (Int64)Math.Ceiling(DateTime.Now.ToUniversalTime().AddHours(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours).Subtract(Constants.Epoch).TotalSeconds); Int64 startTime = (Int64)Math.Ceiling(DateTime.Now.ToUniversalTime().AddHours(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours).Subtract(Constants.Epoch).TotalSeconds);
string baseUrl = "https://poloniex.com/public?command=returnChartData&period=300&start=" + startTime.ToString() + "&end=9999999999&currencyPair=" + marketName; string baseUrl = "https://poloniex.com/public?command=returnChartData&period=300&start=" + startTime.ToString() + "&end=9999999999&currencyPair=" + marketName;
log.DoLogDebug("Poloniex - Getting ticks for '" + marketName + "'..."); log.DoLogDebug("Poloniex - Getting ticks for '" + marketName + "'...");
List<dynamic> jsonObject = GetSimpleJsonListFromURL(baseUrl, log); List<dynamic> jsonObject = GetSimpleJsonListFromURL(baseUrl, log);
if (jsonObject.Count > 0) { if (jsonObject.Count > 0)
{
log.DoLogDebug("Poloniex - " + jsonObject.Count.ToString() + " ticks received."); log.DoLogDebug("Poloniex - " + jsonObject.Count.ToString() + " ticks received.");
foreach (var marketTick in jsonObject) { foreach (var marketTick in jsonObject)
{
MarketTick tick = new MarketTick(); MarketTick tick = new MarketTick();
tick.Price = (double)marketTick["close"]; tick.Price = (double)marketTick["close"];
@ -174,17 +207,21 @@ namespace Core.MarketAnalyzer {
result.Add(tick); result.Add(tick);
} }
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical(ex.Message, ex); log.DoLogCritical(ex.Message, ex);
} }
return result; return result;
} }
public static void CheckForMarketDataRecreation(string mainMarket, Dictionary<string, Market> markets, PTMagicConfiguration systemConfiguration, LogHelper log) { public static void CheckForMarketDataRecreation(string mainMarket, Dictionary<string, Market> markets, PTMagicConfiguration systemConfiguration, LogHelper log)
{
string poloniexDataDirectoryPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar; string poloniexDataDirectoryPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathData + Path.DirectorySeparatorChar + Constants.PTMagicPathExchange + Path.DirectorySeparatorChar;
if (!Directory.Exists(poloniexDataDirectoryPath)) { if (!Directory.Exists(poloniexDataDirectoryPath))
{
Directory.CreateDirectory(poloniexDataDirectoryPath); Directory.CreateDirectory(poloniexDataDirectoryPath);
} }
@ -194,39 +231,47 @@ namespace Core.MarketAnalyzer {
DateTime latestMarketDataFileDateTime = Constants.confMinDate; DateTime latestMarketDataFileDateTime = Constants.confMinDate;
List<FileInfo> marketFiles = dataDirectory.EnumerateFiles("MarketData*").ToList(); List<FileInfo> marketFiles = dataDirectory.EnumerateFiles("MarketData*").ToList();
FileInfo latestMarketDataFile = null; FileInfo latestMarketDataFile = null;
if (marketFiles.Count > 0) { if (marketFiles.Count > 0)
{
latestMarketDataFile = marketFiles.OrderByDescending(mdf => mdf.LastWriteTimeUtc).First(); latestMarketDataFile = marketFiles.OrderByDescending(mdf => mdf.LastWriteTimeUtc).First();
latestMarketDataFileDateTime = latestMarketDataFile.LastWriteTimeUtc; latestMarketDataFileDateTime = latestMarketDataFile.LastWriteTimeUtc;
} }
if (latestMarketDataFileDateTime < DateTime.Now.ToUniversalTime().AddMinutes(-(systemConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes * 3))) { if (latestMarketDataFileDateTime < DateTime.Now.ToUniversalTime().AddMinutes(-(systemConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes * 3)))
{
int lastMarketDataAgeInSeconds = (int)Math.Ceiling(DateTime.Now.ToUniversalTime().Subtract(latestMarketDataFileDateTime).TotalSeconds); int lastMarketDataAgeInSeconds = (int)Math.Ceiling(DateTime.Now.ToUniversalTime().Subtract(latestMarketDataFileDateTime).TotalSeconds);
// Go back in time and create market data // Go back in time and create market data
DateTime startDateTime = DateTime.Now.ToUniversalTime(); DateTime startDateTime = DateTime.Now.ToUniversalTime();
DateTime endDateTime = DateTime.Now.ToUniversalTime().AddHours(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours); DateTime endDateTime = DateTime.Now.ToUniversalTime().AddHours(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours);
if (latestMarketDataFileDateTime != Constants.confMinDate && latestMarketDataFileDateTime > endDateTime) { if (latestMarketDataFileDateTime != Constants.confMinDate && latestMarketDataFileDateTime > endDateTime)
{
// Existing market files too old => Recreate market data for configured timeframe // Existing market files too old => Recreate market data for configured timeframe
log.DoLogInfo("Poloniex - Recreating market data for " + markets.Count + " markets over " + SystemHelper.GetProperDurationTime(lastMarketDataAgeInSeconds) + ". This may take a while..."); log.DoLogInfo("Poloniex - Recreating market data for " + markets.Count + " markets over " + SystemHelper.GetProperDurationTime(lastMarketDataAgeInSeconds) + ". This may take a while...");
endDateTime = latestMarketDataFileDateTime; endDateTime = latestMarketDataFileDateTime;
} else { }
else
{
// No existing market files found => Recreate market data for configured timeframe // No existing market files found => Recreate market data for configured timeframe
log.DoLogInfo("Poloniex - Recreating market data for " + markets.Count + " markets over " + systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours + " hours. This may take a while..."); log.DoLogInfo("Poloniex - Recreating market data for " + markets.Count + " markets over " + systemConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours + " hours. This may take a while...");
} }
// Get Ticks for main market // Get Ticks for main market
List<MarketTick> mainMarketTicks = new List<MarketTick>(); List<MarketTick> mainMarketTicks = new List<MarketTick>();
if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase)) { if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase))
{
mainMarketTicks = Poloniex.GetMarketTicks("USDT_" + mainMarket, systemConfiguration, log); mainMarketTicks = Poloniex.GetMarketTicks("USDT_" + mainMarket, systemConfiguration, log);
} }
// Get Ticks for all markets // Get Ticks for all markets
log.DoLogDebug("Poloniex - Getting ticks for '" + markets.Count + "' markets"); log.DoLogDebug("Poloniex - Getting ticks for '" + markets.Count + "' markets");
Dictionary<string, List<MarketTick>> marketTicks = new Dictionary<string, List<MarketTick>>(); Dictionary<string, List<MarketTick>> marketTicks = new Dictionary<string, List<MarketTick>>();
foreach (string key in markets.Keys) { foreach (string key in markets.Keys)
{
marketTicks.Add(key, Poloniex.GetMarketTicks(key, systemConfiguration, log)); marketTicks.Add(key, Poloniex.GetMarketTicks(key, systemConfiguration, log));
if ((marketTicks.Count % 10) == 0) { if ((marketTicks.Count % 10) == 0)
{
log.DoLogInfo("Poloniex - No worries, I am still alive... " + marketTicks.Count + "/" + markets.Count + " markets done..."); log.DoLogInfo("Poloniex - No worries, I am still alive... " + marketTicks.Count + "/" + markets.Count + " markets done...");
} }
} }
@ -238,24 +283,30 @@ namespace Core.MarketAnalyzer {
// Go back in time and create market data // Go back in time and create market data
int totalTicks = (int)Math.Ceiling(startDateTime.Subtract(endDateTime).TotalMinutes); int totalTicks = (int)Math.Ceiling(startDateTime.Subtract(endDateTime).TotalMinutes);
int completedTicks = 0; int completedTicks = 0;
if (marketTicks.Count > 0) { if (marketTicks.Count > 0)
for (DateTime tickTime = startDateTime; tickTime >= endDateTime; tickTime = tickTime.AddMinutes(-5)) { {
for (DateTime tickTime = startDateTime; tickTime >= endDateTime; tickTime = tickTime.AddMinutes(-5))
{
completedTicks++; completedTicks++;
double mainCurrencyPrice = 1; double mainCurrencyPrice = 1;
if (mainMarketTicks.Count > 0) { if (mainMarketTicks.Count > 0)
{
List<MarketTick> mainCurrencyTickRange = mainMarketTicks.FindAll(t => t.Time <= tickTime); List<MarketTick> mainCurrencyTickRange = mainMarketTicks.FindAll(t => t.Time <= tickTime);
if (mainCurrencyTickRange.Count > 0) { if (mainCurrencyTickRange.Count > 0)
{
MarketTick mainCurrencyTick = mainCurrencyTickRange.OrderByDescending(t => t.Time).First(); MarketTick mainCurrencyTick = mainCurrencyTickRange.OrderByDescending(t => t.Time).First();
mainCurrencyPrice = mainCurrencyTick.Price; mainCurrencyPrice = mainCurrencyTick.Price;
} }
} }
Dictionary<string, Market> tickMarkets = new Dictionary<string, Market>(); Dictionary<string, Market> tickMarkets = new Dictionary<string, Market>();
foreach (string key in markets.Keys) { foreach (string key in markets.Keys)
{
List<MarketTick> tickRange = marketTicks[key].FindAll(t => t.Time <= tickTime); List<MarketTick> tickRange = marketTicks[key].FindAll(t => t.Time <= tickTime);
if (tickRange.Count > 0) { if (tickRange.Count > 0)
{
MarketTick marketTick = tickRange.OrderByDescending(t => t.Time).First(); MarketTick marketTick = tickRange.OrderByDescending(t => t.Time).First();
Market market = new Market(); Market market = new Market();
@ -277,7 +328,8 @@ namespace Core.MarketAnalyzer {
log.DoLogDebug("Poloniex - Market data saved for tick " + tickTime.ToLocalTime().ToString() + " - MainCurrencyPrice=" + mainCurrencyPrice.ToString("#,#0.00") + " USD."); log.DoLogDebug("Poloniex - Market data saved for tick " + tickTime.ToLocalTime().ToString() + " - MainCurrencyPrice=" + mainCurrencyPrice.ToString("#,#0.00") + " USD.");
if ((completedTicks % 100) == 0) { if ((completedTicks % 100) == 0)
{
log.DoLogInfo("Poloniex - Our magicbots are still at work, hang on... " + completedTicks + "/" + totalTicks + " ticks done..."); log.DoLogInfo("Poloniex - Our magicbots are still at work, hang on... " + completedTicks + "/" + totalTicks + " ticks done...");
} }
} }

View File

@ -13,12 +13,16 @@ using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Core.ProfitTrailer { namespace Core.ProfitTrailer
public static class SettingsAPI { {
public static List<string> GetPropertyLinesFromAPI(string ptFileName, PTMagicConfiguration systemConfiguration, LogHelper log) { public static class SettingsAPI
{
public static List<string> GetPropertyLinesFromAPI(string ptFileName, PTMagicConfiguration systemConfiguration, LogHelper log)
{
List<string> result = null; List<string> result = null;
try { try
{
ServicePointManager.Expect100Continue = true; ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999; ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
@ -33,7 +37,8 @@ namespace Core.ProfitTrailer {
byte[] formData = Encoding.ASCII.GetBytes(query); byte[] formData = Encoding.ASCII.GetBytes(query);
httpWebRequest.ContentLength = formData.Length; httpWebRequest.ContentLength = formData.Length;
using (Stream stream = httpWebRequest.GetRequestStream()) { using (Stream stream = httpWebRequest.GetRequestStream())
{
stream.Write(formData, 0, formData.Length); stream.Write(formData, 0, formData.Length);
} }
@ -48,33 +53,44 @@ namespace Core.ProfitTrailer {
//} //}
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse(); HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream())) { using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string jsonResult = streamReader.ReadToEnd(); string jsonResult = streamReader.ReadToEnd();
result = JsonConvert.DeserializeObject<List<string>>(jsonResult); result = JsonConvert.DeserializeObject<List<string>>(jsonResult);
} }
} catch (WebException ex) { }
catch (WebException ex)
{
// Manual error handling as PT doesn't seem to provide a proper error response... // Manual error handling as PT doesn't seem to provide a proper error response...
if (ex.Message.IndexOf("401") > -1) { if (ex.Message.IndexOf("401") > -1)
{
log.DoLogError("Loading " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Unauthorized! The specified Profit Trailer license key '" + systemConfiguration.GetProfitTrailerLicenseKeyMasked() + "' is invalid!"); log.DoLogError("Loading " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Unauthorized! The specified Profit Trailer license key '" + systemConfiguration.GetProfitTrailerLicenseKeyMasked() + "' is invalid!");
} else { }
else
{
log.DoLogCritical("Loading " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex); log.DoLogCritical("Loading " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex);
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical("Loading " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex); log.DoLogCritical("Loading " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex);
} }
return result; return result;
} }
public static void SendPropertyLinesToAPI(string ptFileName, List<string> lines, PTMagicConfiguration systemConfiguration, LogHelper log) { public static void SendPropertyLinesToAPI(string ptFileName, List<string> lines, PTMagicConfiguration systemConfiguration, LogHelper log)
{
int retryCount = 0; int retryCount = 0;
int maxRetries = 3; int maxRetries = 3;
bool transferCompleted = false; bool transferCompleted = false;
bool transferCanceled = false; bool transferCanceled = false;
while (!transferCompleted && !transferCanceled) { while (!transferCompleted && !transferCanceled)
try { {
try
{
ServicePointManager.Expect100Continue = true; ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999; ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
@ -94,7 +110,8 @@ namespace Core.ProfitTrailer {
byte[] formData = Encoding.ASCII.GetBytes(query); byte[] formData = Encoding.ASCII.GetBytes(query);
httpWebRequest.ContentLength = formData.Length; httpWebRequest.ContentLength = formData.Length;
using (Stream stream = httpWebRequest.GetRequestStream()) { using (Stream stream = httpWebRequest.GetRequestStream())
{
stream.Write(formData, 0, formData.Length); stream.Write(formData, 0, formData.Length);
} }
log.DoLogDebug("Built POST request for " + ptFileName + ".properties."); log.DoLogDebug("Built POST request for " + ptFileName + ".properties.");
@ -117,34 +134,51 @@ namespace Core.ProfitTrailer {
log.DoLogDebug(ptFileName + ".properties response object closed."); log.DoLogDebug(ptFileName + ".properties response object closed.");
transferCompleted = true; transferCompleted = true;
} catch (WebException ex) { }
catch (WebException ex)
{
// Manual error handling as PT doesn't seem to provide a proper error response... // Manual error handling as PT doesn't seem to provide a proper error response...
if (ex.Message.IndexOf("401") > -1) { if (ex.Message.IndexOf("401") > -1)
{
log.DoLogError("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Unauthorized! The specified Profit Trailer license key '" + systemConfiguration.GetProfitTrailerLicenseKeyMasked() + "' is invalid!"); log.DoLogError("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Unauthorized! The specified Profit Trailer license key '" + systemConfiguration.GetProfitTrailerLicenseKeyMasked() + "' is invalid!");
transferCanceled = true; transferCanceled = true;
} else if (ex.Message.IndexOf("timed out") > -1) { }
else if (ex.Message.IndexOf("timed out") > -1)
{
// Handle timeout seperately // Handle timeout seperately
retryCount++; retryCount++;
if (retryCount <= maxRetries) { if (retryCount <= maxRetries)
{
log.DoLogError("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!"); log.DoLogError("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!");
} else { }
else
{
transferCanceled = true; transferCanceled = true;
log.DoLogError("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Canceling transfer after " + maxRetries.ToString() + " failed retries."); log.DoLogError("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout! Canceling transfer after " + maxRetries.ToString() + " failed retries.");
} }
} else { }
else
{
log.DoLogCritical("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex); log.DoLogCritical("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex);
transferCanceled = true; transferCanceled = true;
} }
} catch (TimeoutException ex) { }
catch (TimeoutException ex)
{
retryCount++; retryCount++;
if (retryCount <= maxRetries) { if (retryCount <= maxRetries)
{
log.DoLogError("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Starting retry number " + retryCount + "/" + maxRetries.ToString() + "!"); log.DoLogError("Saving " + ptFileName + ".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 " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Canceling transfer after " + maxRetries.ToString() + " failed retries."); log.DoLogError("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Timeout (" + ex.Message + ")! Canceling transfer after " + maxRetries.ToString() + " failed retries.");
} }
} catch (Exception ex) { }
catch (Exception ex)
{
log.DoLogCritical("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex); log.DoLogCritical("Saving " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex);
transferCanceled = true; transferCanceled = true;
} }

View File

@ -13,14 +13,18 @@ using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Core.ProfitTrailer { namespace Core.ProfitTrailer
public static class SettingsFiles { {
public static string GetActiveSetting(PTMagicConfiguration systemConfiguration, string pairsFileName, string dcaFileName, string indicatorsFileName, LogHelper log) { public static class SettingsFiles
{
public static string GetActiveSetting(PTMagicConfiguration systemConfiguration, string pairsFileName, string dcaFileName, string indicatorsFileName, LogHelper log)
{
string pairsPropertiesPath = systemConfiguration.GeneralSettings.Application.ProfitTrailerPath + Constants.PTPathTrading + Path.DirectorySeparatorChar + pairsFileName; string pairsPropertiesPath = systemConfiguration.GeneralSettings.Application.ProfitTrailerPath + Constants.PTPathTrading + Path.DirectorySeparatorChar + pairsFileName;
string result = SettingsFiles.GetActiveSettingFromFile(pairsPropertiesPath, systemConfiguration, log); string result = SettingsFiles.GetActiveSettingFromFile(pairsPropertiesPath, systemConfiguration, log);
if (result.Equals("")) { if (result.Equals(""))
{
SettingsFiles.WriteHeaderLines(pairsPropertiesPath, "Default", systemConfiguration); SettingsFiles.WriteHeaderLines(pairsPropertiesPath, "Default", systemConfiguration);
string dcaPropertiesPath = systemConfiguration.GeneralSettings.Application.ProfitTrailerPath + Constants.PTPathTrading + Path.DirectorySeparatorChar + dcaFileName; string dcaPropertiesPath = systemConfiguration.GeneralSettings.Application.ProfitTrailerPath + Constants.PTPathTrading + Path.DirectorySeparatorChar + dcaFileName;
@ -34,7 +38,8 @@ namespace Core.ProfitTrailer {
return result; return result;
} }
public static void WriteHeaderLines(string filePath, string settingName, PTMagicConfiguration systemConfiguration) { public static void WriteHeaderLines(string filePath, string settingName, PTMagicConfiguration systemConfiguration)
{
// Writing Header lines // Writing Header lines
List<string> lines = File.ReadAllLines(filePath).ToList(); List<string> lines = File.ReadAllLines(filePath).ToList();
lines.Insert(0, ""); lines.Insert(0, "");
@ -47,15 +52,20 @@ namespace Core.ProfitTrailer {
if (!systemConfiguration.GeneralSettings.Application.TestMode) File.WriteAllLines(filePath, lines); if (!systemConfiguration.GeneralSettings.Application.TestMode) File.WriteAllLines(filePath, lines);
} }
public static string GetActiveSettingFromFile(string filePath, PTMagicConfiguration systemConfiguration, LogHelper log) { public static string GetActiveSettingFromFile(string filePath, PTMagicConfiguration systemConfiguration, LogHelper log)
{
string result = ""; string result = "";
if (File.Exists(filePath)) { if (File.Exists(filePath))
{
StreamReader sr = new StreamReader(filePath); StreamReader sr = new StreamReader(filePath);
try { try
{
string line = sr.ReadLine(); string line = sr.ReadLine();
while (line != null) { while (line != null)
if (line.IndexOf("PTMagic_ActiveSetting", StringComparison.InvariantCultureIgnoreCase) > -1) { {
if (line.IndexOf("PTMagic_ActiveSetting", StringComparison.InvariantCultureIgnoreCase) > -1)
{
result = line.Replace("PTMagic_ActiveSetting", "", StringComparison.InvariantCultureIgnoreCase); result = line.Replace("PTMagic_ActiveSetting", "", StringComparison.InvariantCultureIgnoreCase);
result = result.Replace("#", ""); result = result.Replace("#", "");
result = result.Replace("=", "").Trim(); result = result.Replace("=", "").Trim();
@ -64,7 +74,10 @@ namespace Core.ProfitTrailer {
} }
line = sr.ReadLine(); line = sr.ReadLine();
} }
} catch { } finally { }
catch { }
finally
{
sr.Close(); sr.Close();
} }
} }
@ -73,31 +86,39 @@ namespace Core.ProfitTrailer {
} }
public static List<string> GetPresetFileLinesAsList(string settingName, string fileName, PTMagicConfiguration systemConfiguration) { public static List<string> GetPresetFileLinesAsList(string settingName, string fileName, PTMagicConfiguration systemConfiguration)
{
return SettingsFiles.GetPresetFileLinesAsList(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar, settingName, fileName, systemConfiguration); return SettingsFiles.GetPresetFileLinesAsList(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar, settingName, fileName, systemConfiguration);
} }
public static List<string> GetPresetFileLinesAsList(string baseFolderPath, string settingName, string fileName, PTMagicConfiguration systemConfiguration) { public static List<string> GetPresetFileLinesAsList(string baseFolderPath, string settingName, string fileName, PTMagicConfiguration systemConfiguration)
{
fileName = fileName.Replace(".PROPERTIES", ".properties"); fileName = fileName.Replace(".PROPERTIES", ".properties");
string settingPropertiesPath = baseFolderPath + Constants.PTMagicPathPresets + Path.DirectorySeparatorChar + settingName + Path.DirectorySeparatorChar + fileName; string settingPropertiesPath = baseFolderPath + Constants.PTMagicPathPresets + Path.DirectorySeparatorChar + settingName + Path.DirectorySeparatorChar + fileName;
List<string> result = new List<string>(); List<string> result = new List<string>();
if (File.Exists(settingPropertiesPath)) { if (File.Exists(settingPropertiesPath))
{
result = File.ReadAllLines(settingPropertiesPath).ToList(); result = File.ReadAllLines(settingPropertiesPath).ToList();
} }
return result; return result;
} }
public static bool CheckPresets(PTMagicConfiguration systemConfiguration, LogHelper log, bool forceCheck) { public static bool CheckPresets(PTMagicConfiguration systemConfiguration, LogHelper log, bool forceCheck)
if (!forceCheck) { {
if (!forceCheck)
{
// If the check is not enforced, check for file changes // If the check is not enforced, check for file changes
string[] presetFilePaths = Directory.GetFiles(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathPresets, "*.*", SearchOption.AllDirectories); string[] presetFilePaths = Directory.GetFiles(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathPresets, "*.*", SearchOption.AllDirectories);
foreach (string presetFilePath in presetFilePaths) { foreach (string presetFilePath in presetFilePaths)
if (presetFilePath.IndexOf(".properties", StringComparison.InvariantCultureIgnoreCase) > -1) { {
if (presetFilePath.IndexOf(".properties", StringComparison.InvariantCultureIgnoreCase) > -1)
{
FileInfo presetFile = new FileInfo(presetFilePath); FileInfo presetFile = new FileInfo(presetFilePath);
if (presetFile.LastWriteTime > DateTime.Now.AddMinutes(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes).AddSeconds(2)) { if (presetFile.LastWriteTime > DateTime.Now.AddMinutes(-systemConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes).AddSeconds(2))
{
// File has changed recently, force preparation check // File has changed recently, force preparation check
log.DoLogInfo("Preset files changed, enforcing preparation check..."); log.DoLogInfo("Preset files changed, enforcing preparation check...");
@ -109,20 +130,28 @@ namespace Core.ProfitTrailer {
} }
if (forceCheck) { if (forceCheck)
{
log.DoLogInfo("Checking automated settings for presets..."); log.DoLogInfo("Checking automated settings for presets...");
foreach (GlobalSetting setting in systemConfiguration.AnalyzerSettings.GlobalSettings) { foreach (GlobalSetting setting in systemConfiguration.AnalyzerSettings.GlobalSettings)
if (setting.PairsProperties != null) { {
if (setting.PairsProperties.ContainsKey("File")) { if (setting.PairsProperties != null)
{
if (setting.PairsProperties.ContainsKey("File"))
{
setting.PairsProperties["File"] = SystemHelper.PropertyToString(setting.PairsProperties["File"]).Replace(".PROPERTIES", ".properties"); setting.PairsProperties["File"] = SystemHelper.PropertyToString(setting.PairsProperties["File"]).Replace(".PROPERTIES", ".properties");
// Check preset PAIRS.PROPERTIES for header lines // Check preset PAIRS.PROPERTIES for header lines
string settingPairsPropertiesPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathPresets + Path.DirectorySeparatorChar + setting.SettingName + Path.DirectorySeparatorChar + setting.PairsProperties["File"]; string settingPairsPropertiesPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathPresets + Path.DirectorySeparatorChar + setting.SettingName + Path.DirectorySeparatorChar + setting.PairsProperties["File"];
string headerPairsSetting = SettingsFiles.GetActiveSettingFromFile(settingPairsPropertiesPath, systemConfiguration, log); string headerPairsSetting = SettingsFiles.GetActiveSettingFromFile(settingPairsPropertiesPath, systemConfiguration, log);
if (headerPairsSetting.Equals("")) { if (headerPairsSetting.Equals(""))
if (File.Exists(settingPairsPropertiesPath)) { {
if (File.Exists(settingPairsPropertiesPath))
{
SettingsFiles.WriteHeaderLines(settingPairsPropertiesPath, setting.SettingName, systemConfiguration); SettingsFiles.WriteHeaderLines(settingPairsPropertiesPath, setting.SettingName, systemConfiguration);
} else { }
else
{
Exception ex = new Exception("Not able to find preset file " + SystemHelper.PropertyToString(setting.PairsProperties["File"]) + " for '" + setting.SettingName + "'"); Exception ex = new Exception("Not able to find preset file " + SystemHelper.PropertyToString(setting.PairsProperties["File"]) + " for '" + setting.SettingName + "'");
log.DoLogCritical("Not able to find preset file " + SystemHelper.PropertyToString(setting.PairsProperties["File"]) + " for '" + setting.SettingName + "'", ex); log.DoLogCritical("Not able to find preset file " + SystemHelper.PropertyToString(setting.PairsProperties["File"]) + " for '" + setting.SettingName + "'", ex);
throw ex; throw ex;
@ -134,17 +163,23 @@ namespace Core.ProfitTrailer {
} }
} }
if (setting.DCAProperties != null) { if (setting.DCAProperties != null)
if (setting.DCAProperties.ContainsKey("File")) { {
if (setting.DCAProperties.ContainsKey("File"))
{
setting.DCAProperties["File"] = SystemHelper.PropertyToString(setting.DCAProperties["File"]).Replace(".PROPERTIES", ".properties"); setting.DCAProperties["File"] = SystemHelper.PropertyToString(setting.DCAProperties["File"]).Replace(".PROPERTIES", ".properties");
// Check preset DCA.PROPERTIES for header lines // Check preset DCA.PROPERTIES for header lines
string settingDCAPropertiesPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathPresets + Path.DirectorySeparatorChar + setting.SettingName + Path.DirectorySeparatorChar + setting.DCAProperties["File"]; string settingDCAPropertiesPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathPresets + Path.DirectorySeparatorChar + setting.SettingName + Path.DirectorySeparatorChar + setting.DCAProperties["File"];
string headerDCASetting = SettingsFiles.GetActiveSettingFromFile(settingDCAPropertiesPath, systemConfiguration, log); string headerDCASetting = SettingsFiles.GetActiveSettingFromFile(settingDCAPropertiesPath, systemConfiguration, log);
if (headerDCASetting.Equals("")) { if (headerDCASetting.Equals(""))
if (File.Exists(settingDCAPropertiesPath)) { {
if (File.Exists(settingDCAPropertiesPath))
{
SettingsFiles.WriteHeaderLines(settingDCAPropertiesPath, setting.SettingName, systemConfiguration); SettingsFiles.WriteHeaderLines(settingDCAPropertiesPath, setting.SettingName, systemConfiguration);
} else { }
else
{
Exception ex = new Exception("Not able to find preset file " + SystemHelper.PropertyToString(setting.DCAProperties["File"]) + " for '" + setting.SettingName + "'"); Exception ex = new Exception("Not able to find preset file " + SystemHelper.PropertyToString(setting.DCAProperties["File"]) + " for '" + setting.SettingName + "'");
log.DoLogCritical("Not able to find preset file " + SystemHelper.PropertyToString(setting.DCAProperties["File"]) + " for '" + setting.SettingName + "'", ex); log.DoLogCritical("Not able to find preset file " + SystemHelper.PropertyToString(setting.DCAProperties["File"]) + " for '" + setting.SettingName + "'", ex);
throw ex; throw ex;
@ -155,17 +190,23 @@ namespace Core.ProfitTrailer {
} }
} }
if (setting.IndicatorsProperties != null) { if (setting.IndicatorsProperties != null)
if (setting.IndicatorsProperties.ContainsKey("File")) { {
if (setting.IndicatorsProperties.ContainsKey("File"))
{
setting.IndicatorsProperties["File"] = SystemHelper.PropertyToString(setting.IndicatorsProperties["File"]).Replace(".PROPERTIES", ".properties"); setting.IndicatorsProperties["File"] = SystemHelper.PropertyToString(setting.IndicatorsProperties["File"]).Replace(".PROPERTIES", ".properties");
// Check preset INDICATORS.PROPERTIES for header lines // Check preset INDICATORS.PROPERTIES for header lines
string settingIndicatorsPropertiesPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathPresets + Path.DirectorySeparatorChar + setting.SettingName + Path.DirectorySeparatorChar + setting.IndicatorsProperties["File"]; string settingIndicatorsPropertiesPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Constants.PTMagicPathPresets + Path.DirectorySeparatorChar + setting.SettingName + Path.DirectorySeparatorChar + setting.IndicatorsProperties["File"];
string headerIndicatorsSetting = SettingsFiles.GetActiveSettingFromFile(settingIndicatorsPropertiesPath, systemConfiguration, log); string headerIndicatorsSetting = SettingsFiles.GetActiveSettingFromFile(settingIndicatorsPropertiesPath, systemConfiguration, log);
if (headerIndicatorsSetting.Equals("")) { if (headerIndicatorsSetting.Equals(""))
if (File.Exists(settingIndicatorsPropertiesPath)) { {
if (File.Exists(settingIndicatorsPropertiesPath))
{
SettingsFiles.WriteHeaderLines(settingIndicatorsPropertiesPath, setting.SettingName, systemConfiguration); SettingsFiles.WriteHeaderLines(settingIndicatorsPropertiesPath, setting.SettingName, systemConfiguration);
} else { }
else
{
Exception ex = new Exception("Not able to find preset file " + SystemHelper.PropertyToString(setting.IndicatorsProperties["File"]) + " for '" + setting.SettingName + "'"); Exception ex = new Exception("Not able to find preset file " + SystemHelper.PropertyToString(setting.IndicatorsProperties["File"]) + " for '" + setting.SettingName + "'");
log.DoLogCritical("Not able to find preset file " + SystemHelper.PropertyToString(setting.IndicatorsProperties["File"]) + " for '" + setting.SettingName + "'", ex); log.DoLogCritical("Not able to find preset file " + SystemHelper.PropertyToString(setting.IndicatorsProperties["File"]) + " for '" + setting.SettingName + "'", ex);
throw ex; throw ex;

View File

@ -13,13 +13,18 @@ using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Core.ProfitTrailer { namespace Core.ProfitTrailer
public static class SettingsHandler { {
public static string GetMainMarket(PTMagicConfiguration systemConfiguration, List<string> pairsLines, LogHelper log) { public static class SettingsHandler
{
public static string GetMainMarket(PTMagicConfiguration systemConfiguration, List<string> pairsLines, LogHelper log)
{
string result = ""; string result = "";
foreach (string line in pairsLines) { foreach (string line in pairsLines)
if (line.Replace(" ", "").StartsWith("MARKET", StringComparison.InvariantCultureIgnoreCase)) { {
if (line.Replace(" ", "").StartsWith("MARKET", StringComparison.InvariantCultureIgnoreCase))
{
result = line.Replace("MARKET", "", StringComparison.InvariantCultureIgnoreCase); result = line.Replace("MARKET", "", StringComparison.InvariantCultureIgnoreCase);
result = result.Replace("#", ""); result = result.Replace("#", "");
result = result.Replace("=", "").Trim(); result = result.Replace("=", "").Trim();
@ -30,11 +35,14 @@ namespace Core.ProfitTrailer {
return result; return result;
} }
public static string GetMarketPairs(PTMagicConfiguration systemConfiguration, List<string> pairsLines, LogHelper log) { public static string GetMarketPairs(PTMagicConfiguration systemConfiguration, List<string> pairsLines, LogHelper log)
{
string result = ""; string result = "";
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("ALL_enabled_pairs", StringComparison.InvariantCultureIgnoreCase) || line.Replace(" ", "").StartsWith("enabled_pairs", StringComparison.InvariantCultureIgnoreCase))
{
result = line.Replace("ALL_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("#", "");
@ -46,11 +54,14 @@ namespace Core.ProfitTrailer {
return result; return result;
} }
public static string GetActiveSetting(PTMagic ptmagicInstance, ref bool headerLinesAdded) { public static string GetActiveSetting(PTMagic ptmagicInstance, ref bool headerLinesAdded)
{
string result = ""; string result = "";
foreach (string line in ptmagicInstance.PairsLines) { foreach (string line in ptmagicInstance.PairsLines)
if (line.IndexOf("PTMagic_ActiveSetting", StringComparison.InvariantCultureIgnoreCase) > -1) { {
if (line.IndexOf("PTMagic_ActiveSetting", StringComparison.InvariantCultureIgnoreCase) > -1)
{
result = line.Replace("PTMagic_ActiveSetting", "", StringComparison.InvariantCultureIgnoreCase); result = line.Replace("PTMagic_ActiveSetting", "", StringComparison.InvariantCultureIgnoreCase);
result = result.Replace("#", ""); result = result.Replace("#", "");
result = result.Replace("=", "").Trim(); result = result.Replace("=", "").Trim();
@ -59,7 +70,8 @@ namespace Core.ProfitTrailer {
} }
} }
if (result.Equals("")) { if (result.Equals(""))
{
SettingsHandler.WriteHeaderLines("Pairs", ptmagicInstance); SettingsHandler.WriteHeaderLines("Pairs", ptmagicInstance);
SettingsHandler.WriteHeaderLines("DCA", ptmagicInstance); SettingsHandler.WriteHeaderLines("DCA", ptmagicInstance);
SettingsHandler.WriteHeaderLines("Indicators", ptmagicInstance); SettingsHandler.WriteHeaderLines("Indicators", ptmagicInstance);
@ -69,7 +81,8 @@ namespace Core.ProfitTrailer {
return result; return result;
} }
public static void WriteHeaderLines(string fileType, PTMagic ptmagicInstance) { public static void WriteHeaderLines(string fileType, PTMagic ptmagicInstance)
{
List<string> fileLines = (List<string>)ptmagicInstance.GetType().GetProperty(fileType + "Lines").GetValue(ptmagicInstance, null); List<string> fileLines = (List<string>)ptmagicInstance.GetType().GetProperty(fileType + "Lines").GetValue(ptmagicInstance, null);
// Writing Header lines // Writing Header lines
@ -83,16 +96,23 @@ namespace Core.ProfitTrailer {
ptmagicInstance.GetType().GetProperty(fileType + "Lines").SetValue(ptmagicInstance, fileLines); ptmagicInstance.GetType().GetProperty(fileType + "Lines").SetValue(ptmagicInstance, fileLines);
} }
public static Dictionary<string, string> GetPropertiesAsDictionary(List<string> propertyLines) { public static Dictionary<string, string> GetPropertiesAsDictionary(List<string> propertyLines)
{
Dictionary<string, string> result = new Dictionary<string, string>(); Dictionary<string, string> result = new Dictionary<string, string>();
foreach (string line in propertyLines) { foreach (string line in propertyLines)
if (!line.StartsWith("#", StringComparison.InvariantCultureIgnoreCase)) { {
if (!line.StartsWith("#", StringComparison.InvariantCultureIgnoreCase))
{
string[] lineContentArray = line.Split("="); string[] lineContentArray = line.Split("=");
if (lineContentArray.Length == 2) { if (lineContentArray.Length == 2)
if (!result.ContainsKey(lineContentArray[0].Trim())) { {
if (!result.ContainsKey(lineContentArray[0].Trim()))
{
result.Add(lineContentArray[0].Trim(), lineContentArray[1].Trim()); result.Add(lineContentArray[0].Trim(), lineContentArray[1].Trim());
} else { }
else
{
result[lineContentArray[0].Trim()] = lineContentArray[1].Trim(); result[lineContentArray[0].Trim()] = lineContentArray[1].Trim();
} }
} }
@ -102,41 +122,51 @@ namespace Core.ProfitTrailer {
return result; return result;
} }
public static string GetCurrentPropertyValue(Dictionary<string, string> properties, string propertyKey, string fallbackPropertyKey) { public static string GetCurrentPropertyValue(Dictionary<string, string> properties, string propertyKey, string fallbackPropertyKey)
{
string result = ""; string result = "";
if (properties.ContainsKey(propertyKey)) { if (properties.ContainsKey(propertyKey))
{
result = properties[propertyKey]; result = properties[propertyKey];
} else if (!fallbackPropertyKey.Equals("") && properties.ContainsKey(fallbackPropertyKey)) { }
else if (!fallbackPropertyKey.Equals("") && properties.ContainsKey(fallbackPropertyKey))
{
result = properties[fallbackPropertyKey]; result = properties[fallbackPropertyKey];
} }
return result; return result;
} }
public static void CompileProperties(PTMagic ptmagicInstance, GlobalSetting setting) { public static void CompileProperties(PTMagic ptmagicInstance, GlobalSetting setting)
{
SettingsHandler.BuildPropertyLines("Pairs", ptmagicInstance, setting); SettingsHandler.BuildPropertyLines("Pairs", ptmagicInstance, setting);
SettingsHandler.BuildPropertyLines("DCA", ptmagicInstance, setting); SettingsHandler.BuildPropertyLines("DCA", ptmagicInstance, setting);
SettingsHandler.BuildPropertyLines("Indicators", ptmagicInstance, setting); SettingsHandler.BuildPropertyLines("Indicators", ptmagicInstance, setting);
} }
public static void BuildPropertyLines(string fileType, PTMagic ptmagicInstance, GlobalSetting setting) { public static void BuildPropertyLines(string fileType, PTMagic ptmagicInstance, GlobalSetting setting)
{
List<string> result = new List<string>(); List<string> result = new List<string>();
List<string> fileLines = (List<string>)ptmagicInstance.GetType().GetProperty(fileType + "Lines").GetValue(ptmagicInstance, null); List<string> fileLines = (List<string>)ptmagicInstance.GetType().GetProperty(fileType + "Lines").GetValue(ptmagicInstance, null);
Dictionary<string, object> properties = (Dictionary<string, object>)setting.GetType().GetProperty(fileType + "Properties").GetValue(setting, null); Dictionary<string, object> properties = (Dictionary<string, object>)setting.GetType().GetProperty(fileType + "Properties").GetValue(setting, null);
if (properties != null) { if (properties != null)
{
// Building Properties // Building Properties
if (!setting.SettingName.Equals(ptmagicInstance.DefaultSettingName, StringComparison.InvariantCultureIgnoreCase) && ptmagicInstance.PTMagicConfiguration.GeneralSettings.Application.AlwaysLoadDefaultBeforeSwitch && !properties.ContainsKey("File")) { if (!setting.SettingName.Equals(ptmagicInstance.DefaultSettingName, StringComparison.InvariantCultureIgnoreCase) && ptmagicInstance.PTMagicConfiguration.GeneralSettings.Application.AlwaysLoadDefaultBeforeSwitch && !properties.ContainsKey("File"))
{
// Load default settings as basis for the switch // Load default settings as basis for the switch
GlobalSetting defaultSetting = ptmagicInstance.PTMagicConfiguration.AnalyzerSettings.GlobalSettings.Find(a => a.SettingName.Equals(ptmagicInstance.DefaultSettingName, StringComparison.InvariantCultureIgnoreCase)); GlobalSetting defaultSetting = ptmagicInstance.PTMagicConfiguration.AnalyzerSettings.GlobalSettings.Find(a => a.SettingName.Equals(ptmagicInstance.DefaultSettingName, StringComparison.InvariantCultureIgnoreCase));
if (defaultSetting != null) { if (defaultSetting != null)
{
Dictionary<string, object> defaultProperties = new Dictionary<string, object>(); Dictionary<string, object> defaultProperties = new Dictionary<string, object>();
switch (fileType.ToLower()) { switch (fileType.ToLower())
{
case "pairs": case "pairs":
defaultProperties = defaultSetting.PairsProperties; defaultProperties = defaultSetting.PairsProperties;
break; break;
@ -148,39 +178,53 @@ namespace Core.ProfitTrailer {
break; break;
} }
if (defaultProperties.ContainsKey("File")) { if (defaultProperties.ContainsKey("File"))
{
fileLines = SettingsFiles.GetPresetFileLinesAsList(defaultSetting.SettingName, defaultProperties["File"].ToString(), ptmagicInstance.PTMagicConfiguration); fileLines = SettingsFiles.GetPresetFileLinesAsList(defaultSetting.SettingName, defaultProperties["File"].ToString(), ptmagicInstance.PTMagicConfiguration);
} }
} }
} else { }
else
{
// Check if settings are configured in a seperate file // Check if settings are configured in a seperate file
if (properties.ContainsKey("File")) { if (properties.ContainsKey("File"))
{
fileLines = SettingsFiles.GetPresetFileLinesAsList(setting.SettingName, properties["File"].ToString(), ptmagicInstance.PTMagicConfiguration); fileLines = SettingsFiles.GetPresetFileLinesAsList(setting.SettingName, properties["File"].ToString(), ptmagicInstance.PTMagicConfiguration);
} }
} }
foreach (string line in fileLines) { foreach (string line in fileLines)
if (line.IndexOf("PTMagic_ActiveSetting", StringComparison.InvariantCultureIgnoreCase) > -1) { {
if (line.IndexOf("PTMagic_ActiveSetting", StringComparison.InvariantCultureIgnoreCase) > -1)
{
// Setting current active setting // Setting current active setting
result.Add("# PTMagic_ActiveSetting = " + setting.SettingName); result.Add("# PTMagic_ActiveSetting = " + setting.SettingName);
} else if (line.IndexOf("PTMagic_LastChanged", StringComparison.InvariantCultureIgnoreCase) > -1) { }
else if (line.IndexOf("PTMagic_LastChanged", StringComparison.InvariantCultureIgnoreCase) > -1)
{
// Setting last change datetime // Setting last change datetime
result.Add("# PTMagic_LastChanged = " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString()); result.Add("# PTMagic_LastChanged = " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString());
} else if (line.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1) { }
else if (line.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1)
{
// Single Market Settings will get overwritten every single run => crop the lines // Single Market Settings will get overwritten every single run => crop the lines
break; break;
} else { }
else
{
// Writing property items // Writing property items
int oldResultCount = result.Count; int oldResultCount = result.Count;
if (properties != null) { if (properties != null)
foreach (string settingProperty in properties.Keys) { {
foreach (string settingProperty in properties.Keys)
{
result = SettingsHandler.BuildPropertyLine(result, setting.SettingName, line, properties, settingProperty); result = SettingsHandler.BuildPropertyLine(result, setting.SettingName, line, properties, settingProperty);
} }
} }
@ -192,32 +236,40 @@ namespace Core.ProfitTrailer {
ptmagicInstance.GetType().GetProperty(fileType + "Lines").SetValue(ptmagicInstance, result); ptmagicInstance.GetType().GetProperty(fileType + "Lines").SetValue(ptmagicInstance, result);
} }
public static List<string> BuildPropertyLine(List<string> result, string settingName, string line, Dictionary<string, object> properties, string settingProperty) { public static List<string> BuildPropertyLine(List<string> result, string settingName, string line, Dictionary<string, object> properties, string settingProperty)
{
int valueMode = Constants.ValueModeDefault; int valueMode = Constants.ValueModeDefault;
string propertyKey = settingProperty; string propertyKey = settingProperty;
// Check for offset values // Check for offset values
if (propertyKey.IndexOf("_OFFSETPERCENT") > -1) { if (propertyKey.IndexOf("_OFFSETPERCENT") > -1)
{
valueMode = Constants.ValueModeOffsetPercent; valueMode = Constants.ValueModeOffsetPercent;
propertyKey = propertyKey.Replace("_OFFSETPERCENT", ""); propertyKey = propertyKey.Replace("_OFFSETPERCENT", "");
} else if (propertyKey.IndexOf("_OFFSET") > -1) { }
else if (propertyKey.IndexOf("_OFFSET") > -1)
{
valueMode = Constants.ValueModeOffset; valueMode = Constants.ValueModeOffset;
propertyKey = propertyKey.Replace("_OFFSET", ""); propertyKey = propertyKey.Replace("_OFFSET", "");
} }
if (line.StartsWith(propertyKey + " ", StringComparison.InvariantCultureIgnoreCase) || line.StartsWith(propertyKey + "=", StringComparison.InvariantCultureIgnoreCase)) { if (line.StartsWith(propertyKey + " ", StringComparison.InvariantCultureIgnoreCase) || line.StartsWith(propertyKey + "=", StringComparison.InvariantCultureIgnoreCase))
{
string newValueString = SystemHelper.PropertyToString(properties[settingProperty]); string newValueString = SystemHelper.PropertyToString(properties[settingProperty]);
if (newValueString.ToLower().Equals("true") || newValueString.ToLower().Equals("false")) { if (newValueString.ToLower().Equals("true") || newValueString.ToLower().Equals("false"))
{
newValueString = newValueString.ToLower(); newValueString = newValueString.ToLower();
} }
string oldValueString = line.Replace(propertyKey, "").Replace("=", "").Trim(); string oldValueString = line.Replace(propertyKey, "").Replace("=", "").Trim();
switch (valueMode) { switch (valueMode)
{
case Constants.ValueModeOffset: case Constants.ValueModeOffset:
// Offset value by a fixed amount // Offset value by a fixed amount
double offsetValue = SystemHelper.TextToDouble(newValueString, 0, "en-US"); double offsetValue = SystemHelper.TextToDouble(newValueString, 0, "en-US");
if (offsetValue != 0) { if (offsetValue != 0)
{
double oldValue = SystemHelper.TextToDouble(oldValueString, 0, "en-US"); double oldValue = SystemHelper.TextToDouble(oldValueString, 0, "en-US");
newValueString = Math.Round((oldValue + offsetValue), 8).ToString(new System.Globalization.CultureInfo("en-US")); newValueString = Math.Round((oldValue + offsetValue), 8).ToString(new System.Globalization.CultureInfo("en-US"));
} }
@ -225,7 +277,8 @@ namespace Core.ProfitTrailer {
case Constants.ValueModeOffsetPercent: case Constants.ValueModeOffsetPercent:
// Offset value by percentage // Offset value by percentage
double offsetValuePercent = SystemHelper.TextToDouble(newValueString, 0, "en-US"); double offsetValuePercent = SystemHelper.TextToDouble(newValueString, 0, "en-US");
if (offsetValuePercent != 0) { if (offsetValuePercent != 0)
{
double oldValue = SystemHelper.TextToDouble(oldValueString, 0, "en-US"); double oldValue = SystemHelper.TextToDouble(oldValueString, 0, "en-US");
if (oldValue < 0) offsetValuePercent = offsetValuePercent * -1; if (oldValue < 0) offsetValuePercent = offsetValuePercent * -1;
double oldValueOffset = (oldValue * (offsetValuePercent / 100)); double oldValueOffset = (oldValue * (offsetValuePercent / 100));
@ -239,12 +292,15 @@ namespace Core.ProfitTrailer {
line = propertyKey + " = " + newValueString; line = propertyKey + " = " + newValueString;
string previousLine = result.Last(); string previousLine = result.Last();
if (previousLine.IndexOf("PTMagic Changed Line", StringComparison.InvariantCultureIgnoreCase) > -1) { if (previousLine.IndexOf("PTMagic Changed Line", StringComparison.InvariantCultureIgnoreCase) > -1)
{
previousLine = "# PTMagic changed line for setting '" + settingName + "' on " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString(); previousLine = "# PTMagic changed line for setting '" + settingName + "' on " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString();
result.RemoveAt(result.Count - 1); result.RemoveAt(result.Count - 1);
result.Add(previousLine); result.Add(previousLine);
} else { }
else
{
string editLine = "# PTMagic changed line for setting '" + settingName + "' on " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString(); string editLine = "# PTMagic changed line for setting '" + settingName + "' on " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString();
result.Add(editLine); result.Add(editLine);
} }
@ -254,8 +310,10 @@ namespace Core.ProfitTrailer {
return result; return result;
} }
public static void CompileSingleMarketProperties(PTMagic ptmagicInstance, Dictionary<string, List<string>> matchedTriggers) { public static void CompileSingleMarketProperties(PTMagic ptmagicInstance, Dictionary<string, List<string>> matchedTriggers)
try { {
try
{
List<string> globalPairsLines = new List<string>(); List<string> globalPairsLines = new List<string>();
List<string> globalDCALines = new List<string>(); List<string> globalDCALines = new List<string>();
List<string> globalIndicatorsLines = new List<string>(); List<string> globalIndicatorsLines = new List<string>();
@ -264,12 +322,16 @@ namespace Core.ProfitTrailer {
List<string> newDCALines = new List<string>(); List<string> newDCALines = new List<string>();
List<string> newIndicatorsLines = new List<string>(); List<string> newIndicatorsLines = new List<string>();
foreach (string pairsLine in ptmagicInstance.PairsLines) { foreach (string pairsLine in ptmagicInstance.PairsLines)
if (pairsLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1) { {
if (pairsLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1)
{
// Single Market Settings will get overwritten every single run => crop the lines // Single Market Settings will get overwritten every single run => crop the lines
break; break;
} else { }
else
{
string globalPairsLine = pairsLine; string globalPairsLine = pairsLine;
globalPairsLines.Add(globalPairsLine); globalPairsLines.Add(globalPairsLine);
@ -280,12 +342,16 @@ namespace Core.ProfitTrailer {
newPairsLines.Add("# ########################################################################"); newPairsLines.Add("# ########################################################################");
newPairsLines.Add(""); newPairsLines.Add("");
foreach (string dcaLine in ptmagicInstance.DCALines) { foreach (string dcaLine in ptmagicInstance.DCALines)
if (dcaLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1) { {
if (dcaLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1)
{
// Single Market Settings will get overwritten every single run => crop the lines // Single Market Settings will get overwritten every single run => crop the lines
break; break;
} else { }
else
{
string globalDCALine = dcaLine; string globalDCALine = dcaLine;
globalDCALines.Add(globalDCALine); globalDCALines.Add(globalDCALine);
@ -296,12 +362,16 @@ namespace Core.ProfitTrailer {
newDCALines.Add("# ########################################################################"); newDCALines.Add("# ########################################################################");
newDCALines.Add(""); newDCALines.Add("");
foreach (string indicatorsLine in ptmagicInstance.IndicatorsLines) { foreach (string indicatorsLine in ptmagicInstance.IndicatorsLines)
if (indicatorsLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1) { {
if (indicatorsLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1)
{
// Single Market Settings will get overwritten every single run => crop the lines // Single Market Settings will get overwritten every single run => crop the lines
break; break;
} else { }
else
{
string globalIndicatorsLine = indicatorsLine; string globalIndicatorsLine = indicatorsLine;
globalIndicatorsLines.Add(globalIndicatorsLine); globalIndicatorsLines.Add(globalIndicatorsLine);
@ -316,35 +386,49 @@ namespace Core.ProfitTrailer {
newIndicatorsLines.Add("# ########################################################################"); newIndicatorsLines.Add("# ########################################################################");
newIndicatorsLines.Add(""); newIndicatorsLines.Add("");
foreach (string marketPair in ptmagicInstance.TriggeredSingleMarketSettings.Keys.OrderBy(k => k)) { foreach (string marketPair in ptmagicInstance.TriggeredSingleMarketSettings.Keys.OrderBy(k => k))
{
Dictionary<string, object> pairsPropertiesToApply = new Dictionary<string, object>(); Dictionary<string, object> pairsPropertiesToApply = new Dictionary<string, object>();
Dictionary<string, object> dcaPropertiesToApply = new Dictionary<string, object>(); Dictionary<string, object> dcaPropertiesToApply = new Dictionary<string, object>();
Dictionary<string, object> indicatorsPropertiesToApply = new Dictionary<string, object>(); Dictionary<string, object> indicatorsPropertiesToApply = new Dictionary<string, object>();
// Build Properties as a whole list so that a single coin also has only one block with single market settings applied to it // Build Properties as a whole list so that a single coin also has only one block with single market settings applied to it
foreach (SingleMarketSetting setting in ptmagicInstance.TriggeredSingleMarketSettings[marketPair]) { foreach (SingleMarketSetting setting in ptmagicInstance.TriggeredSingleMarketSettings[marketPair])
{
ptmagicInstance.Log.DoLogInfo("Building single market settings '" + setting.SettingName + "' for '" + marketPair + "'..."); ptmagicInstance.Log.DoLogInfo("Building single market settings '" + setting.SettingName + "' for '" + marketPair + "'...");
foreach (string settingPairsProperty in setting.PairsProperties.Keys) { foreach (string settingPairsProperty in setting.PairsProperties.Keys)
if (!pairsPropertiesToApply.ContainsKey(settingPairsProperty)) { {
if (!pairsPropertiesToApply.ContainsKey(settingPairsProperty))
{
pairsPropertiesToApply.Add(settingPairsProperty, setting.PairsProperties[settingPairsProperty]); pairsPropertiesToApply.Add(settingPairsProperty, setting.PairsProperties[settingPairsProperty]);
} else { }
else
{
pairsPropertiesToApply[settingPairsProperty] = setting.PairsProperties[settingPairsProperty]; pairsPropertiesToApply[settingPairsProperty] = setting.PairsProperties[settingPairsProperty];
} }
} }
foreach (string settingDCAProperty in setting.DCAProperties.Keys) { foreach (string settingDCAProperty in setting.DCAProperties.Keys)
if (!dcaPropertiesToApply.ContainsKey(settingDCAProperty)) { {
if (!dcaPropertiesToApply.ContainsKey(settingDCAProperty))
{
dcaPropertiesToApply.Add(settingDCAProperty, setting.DCAProperties[settingDCAProperty]); dcaPropertiesToApply.Add(settingDCAProperty, setting.DCAProperties[settingDCAProperty]);
} else { }
else
{
dcaPropertiesToApply[settingDCAProperty] = setting.DCAProperties[settingDCAProperty]; dcaPropertiesToApply[settingDCAProperty] = setting.DCAProperties[settingDCAProperty];
} }
} }
foreach (string settingIndicatorsProperty in setting.IndicatorsProperties.Keys) { foreach (string settingIndicatorsProperty in setting.IndicatorsProperties.Keys)
if (!indicatorsPropertiesToApply.ContainsKey(settingIndicatorsProperty)) { {
if (!indicatorsPropertiesToApply.ContainsKey(settingIndicatorsProperty))
{
indicatorsPropertiesToApply.Add(settingIndicatorsProperty, setting.IndicatorsProperties[settingIndicatorsProperty]); indicatorsPropertiesToApply.Add(settingIndicatorsProperty, setting.IndicatorsProperties[settingIndicatorsProperty]);
} else { }
else
{
indicatorsPropertiesToApply[settingIndicatorsProperty] = setting.IndicatorsProperties[settingIndicatorsProperty]; indicatorsPropertiesToApply[settingIndicatorsProperty] = setting.IndicatorsProperties[settingIndicatorsProperty];
} }
} }
@ -365,68 +449,90 @@ namespace Core.ProfitTrailer {
ptmagicInstance.PairsLines = globalPairsLines; ptmagicInstance.PairsLines = globalPairsLines;
ptmagicInstance.DCALines = globalDCALines; ptmagicInstance.DCALines = globalDCALines;
ptmagicInstance.IndicatorsLines = globalIndicatorsLines; ptmagicInstance.IndicatorsLines = globalIndicatorsLines;
} catch (Exception ex) { }
catch (Exception ex)
{
ptmagicInstance.Log.DoLogCritical("Critical error while writing settings!", ex); ptmagicInstance.Log.DoLogCritical("Critical error while writing settings!", ex);
throw (ex); throw (ex);
} }
} }
public static List<string> BuildPropertyLinesForSingleMarketSetting(int ptMajorVersion, string mainMarket, string marketPair, List<SingleMarketSetting> appliedSettings, Dictionary<string, object> properties, Dictionary<string, List<string>> matchedTriggers, Dictionary<string, string> fullProperties, List<string> newPropertyLines, PTMagicConfiguration systemConfiguration, LogHelper log) { public static List<string> BuildPropertyLinesForSingleMarketSetting(int ptMajorVersion, string mainMarket, string marketPair, List<SingleMarketSetting> appliedSettings, Dictionary<string, object> properties, Dictionary<string, List<string>> matchedTriggers, Dictionary<string, string> fullProperties, List<string> newPropertyLines, PTMagicConfiguration systemConfiguration, LogHelper log)
if (properties.Keys.Count > 0) { {
if (properties.Keys.Count > 0)
{
string appliedSettingsStringList = ""; string appliedSettingsStringList = "";
foreach (SingleMarketSetting sms in appliedSettings) { foreach (SingleMarketSetting sms in appliedSettings)
{
if (!appliedSettingsStringList.Equals("")) appliedSettingsStringList += ", "; if (!appliedSettingsStringList.Equals("")) appliedSettingsStringList += ", ";
appliedSettingsStringList += sms.SettingName; appliedSettingsStringList += sms.SettingName;
} }
newPropertyLines.Add("# " + marketPair + " - Current active settings: " + appliedSettingsStringList); newPropertyLines.Add("# " + marketPair + " - Current active settings: " + appliedSettingsStringList);
newPropertyLines.Add("# Matching triggers:"); newPropertyLines.Add("# Matching triggers:");
foreach (string matchingTrigger in matchedTriggers[marketPair]) { foreach (string matchingTrigger in matchedTriggers[marketPair])
{
newPropertyLines.Add("# " + matchingTrigger); newPropertyLines.Add("# " + matchingTrigger);
} }
foreach (string settingProperty in properties.Keys) { foreach (string settingProperty in properties.Keys)
{
int valueMode = Constants.ValueModeDefault; int valueMode = Constants.ValueModeDefault;
string propertyKey = settingProperty; string propertyKey = settingProperty;
// Check for offset values // Check for offset values
if (propertyKey.IndexOf("_OFFSETPERCENT") > -1) { if (propertyKey.IndexOf("_OFFSETPERCENT") > -1)
{
valueMode = Constants.ValueModeOffsetPercent; valueMode = Constants.ValueModeOffsetPercent;
propertyKey = propertyKey.Replace("_OFFSETPERCENT", ""); propertyKey = propertyKey.Replace("_OFFSETPERCENT", "");
} else if (propertyKey.IndexOf("_OFFSET") > -1) { }
else if (propertyKey.IndexOf("_OFFSET") > -1)
{
valueMode = Constants.ValueModeOffset; valueMode = Constants.ValueModeOffset;
propertyKey = propertyKey.Replace("_OFFSET", ""); propertyKey = propertyKey.Replace("_OFFSET", "");
} }
string newValueString = SystemHelper.PropertyToString(properties[settingProperty]); string newValueString = SystemHelper.PropertyToString(properties[settingProperty]);
if (newValueString.ToLower().Equals("true") || newValueString.ToLower().Equals("false")) { if (newValueString.ToLower().Equals("true") || newValueString.ToLower().Equals("false"))
{
newValueString = newValueString.ToLower(); newValueString = newValueString.ToLower();
} }
string propertyMarketName = marketPair; string propertyMarketName = marketPair;
if (ptMajorVersion > 1) { if (ptMajorVersion > 1)
{
// Adjust market pair name for PT 2.0 and above // Adjust market pair name for PT 2.0 and above
propertyMarketName = propertyMarketName.Replace(mainMarket, "").Replace("_", "").Replace("-", ""); propertyMarketName = propertyMarketName.Replace(mainMarket, "").Replace("_", "").Replace("-", "");
} }
string propertyKeyString = ""; string propertyKeyString = "";
if (propertyKey.StartsWith("ALL", StringComparison.InvariantCultureIgnoreCase)) { if (propertyKey.StartsWith("ALL", StringComparison.InvariantCultureIgnoreCase))
{
propertyKeyString = propertyKey.Replace("ALL", propertyMarketName, StringComparison.InvariantCultureIgnoreCase); propertyKeyString = propertyKey.Replace("ALL", propertyMarketName, StringComparison.InvariantCultureIgnoreCase);
} else if (propertyKey.StartsWith("DEFAULT", StringComparison.InvariantCultureIgnoreCase)) { }
else if (propertyKey.StartsWith("DEFAULT", StringComparison.InvariantCultureIgnoreCase))
{
propertyKeyString = propertyKey.Replace("DEFAULT", propertyMarketName, StringComparison.InvariantCultureIgnoreCase); propertyKeyString = propertyKey.Replace("DEFAULT", propertyMarketName, StringComparison.InvariantCultureIgnoreCase);
} else { }
if (propertyKey.StartsWith("_", StringComparison.InvariantCultureIgnoreCase)) { else
{
if (propertyKey.StartsWith("_", StringComparison.InvariantCultureIgnoreCase))
{
propertyKeyString = propertyMarketName + propertyKey; propertyKeyString = propertyMarketName + propertyKey;
} else { }
else
{
propertyKeyString = propertyMarketName + "_" + propertyKey; propertyKeyString = propertyMarketName + "_" + propertyKey;
} }
} }
switch (valueMode) { switch (valueMode)
{
case Constants.ValueModeOffset: case Constants.ValueModeOffset:
// Offset value by a fixed amount // Offset value by a fixed amount
double offsetValue = SystemHelper.TextToDouble(newValueString, 0, "en-US"); double offsetValue = SystemHelper.TextToDouble(newValueString, 0, "en-US");
if (offsetValue != 0) { if (offsetValue != 0)
{
double oldValue = SystemHelper.TextToDouble(SettingsHandler.GetCurrentPropertyValue(fullProperties, propertyKey, propertyKey.Replace("ALL_", "DEFAULT_")), 0, "en-US"); double oldValue = SystemHelper.TextToDouble(SettingsHandler.GetCurrentPropertyValue(fullProperties, propertyKey, propertyKey.Replace("ALL_", "DEFAULT_")), 0, "en-US");
newValueString = Math.Round((oldValue + offsetValue), 8).ToString(new System.Globalization.CultureInfo("en-US")); newValueString = Math.Round((oldValue + offsetValue), 8).ToString(new System.Globalization.CultureInfo("en-US"));
} }
@ -434,7 +540,8 @@ namespace Core.ProfitTrailer {
case Constants.ValueModeOffsetPercent: case Constants.ValueModeOffsetPercent:
// Offset value by percentage // Offset value by percentage
double offsetValuePercent = SystemHelper.TextToDouble(newValueString, 0, "en-US"); double offsetValuePercent = SystemHelper.TextToDouble(newValueString, 0, "en-US");
if (offsetValuePercent != 0) { if (offsetValuePercent != 0)
{
double oldValue = SystemHelper.TextToDouble(SettingsHandler.GetCurrentPropertyValue(fullProperties, propertyKey, propertyKey.Replace("ALL_", "DEFAULT_")), 0, "en-US"); double oldValue = SystemHelper.TextToDouble(SettingsHandler.GetCurrentPropertyValue(fullProperties, propertyKey, propertyKey.Replace("ALL_", "DEFAULT_")), 0, "en-US");
if (oldValue < 0) offsetValuePercent = offsetValuePercent * -1; if (oldValue < 0) offsetValuePercent = offsetValuePercent * -1;
double oldValueOffset = (oldValue * (offsetValuePercent / 100)); double oldValueOffset = (oldValue * (offsetValuePercent / 100));
@ -453,21 +560,27 @@ namespace Core.ProfitTrailer {
return newPropertyLines; return newPropertyLines;
} }
public static bool RemoveSingleMarketSettings(PTMagic ptmagicInstance) { public static bool RemoveSingleMarketSettings(PTMagic ptmagicInstance)
{
bool result = false; bool result = false;
try { try
{
List<string> cleanedUpPairsLines = new List<string>(); List<string> cleanedUpPairsLines = new List<string>();
List<string> cleanedUpDCALines = new List<string>(); List<string> cleanedUpDCALines = new List<string>();
List<string> cleanedUpIndicatorsLines = new List<string>(); List<string> cleanedUpIndicatorsLines = new List<string>();
bool removedPairsSingleMarketSettings = false; bool removedPairsSingleMarketSettings = false;
foreach (string pairsLine in ptmagicInstance.PairsLines) { foreach (string pairsLine in ptmagicInstance.PairsLines)
if (pairsLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1) { {
if (pairsLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1)
{
// Single Market Settings will get overwritten every single run => crop the lines // Single Market Settings will get overwritten every single run => crop the lines
removedPairsSingleMarketSettings = true; removedPairsSingleMarketSettings = true;
break; break;
} else { }
else
{
string newPairsLine = pairsLine; string newPairsLine = pairsLine;
cleanedUpPairsLines.Add(newPairsLine); cleanedUpPairsLines.Add(newPairsLine);
@ -475,13 +588,17 @@ namespace Core.ProfitTrailer {
} }
bool removedDCASingleMarketSettings = false; bool removedDCASingleMarketSettings = false;
foreach (string dcaLine in ptmagicInstance.DCALines) { foreach (string dcaLine in ptmagicInstance.DCALines)
if (dcaLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1) { {
if (dcaLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1)
{
// Single Market Settings will get overwritten every single run => crop the lines // Single Market Settings will get overwritten every single run => crop the lines
removedDCASingleMarketSettings = true; removedDCASingleMarketSettings = true;
break; break;
} else { }
else
{
string newDCALine = dcaLine; string newDCALine = dcaLine;
cleanedUpDCALines.Add(newDCALine); cleanedUpDCALines.Add(newDCALine);
@ -489,13 +606,17 @@ namespace Core.ProfitTrailer {
} }
bool removedIndicatorsSingleMarketSettings = false; bool removedIndicatorsSingleMarketSettings = false;
foreach (string indicatorsLine in ptmagicInstance.IndicatorsLines) { foreach (string indicatorsLine in ptmagicInstance.IndicatorsLines)
if (indicatorsLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1) { {
if (indicatorsLine.IndexOf("PTMagic_SingleMarketSettings", StringComparison.InvariantCultureIgnoreCase) > -1)
{
// Single Market Settings will get overwritten every single run => crop the lines // Single Market Settings will get overwritten every single run => crop the lines
removedIndicatorsSingleMarketSettings = true; removedIndicatorsSingleMarketSettings = true;
break; break;
} else { }
else
{
string newIndicatorsLine = indicatorsLine; string newIndicatorsLine = indicatorsLine;
cleanedUpIndicatorsLines.Add(newIndicatorsLine); cleanedUpIndicatorsLines.Add(newIndicatorsLine);
@ -507,7 +628,9 @@ namespace Core.ProfitTrailer {
ptmagicInstance.IndicatorsLines = cleanedUpIndicatorsLines; ptmagicInstance.IndicatorsLines = cleanedUpIndicatorsLines;
result = removedPairsSingleMarketSettings && removedDCASingleMarketSettings && removedIndicatorsSingleMarketSettings; result = removedPairsSingleMarketSettings && removedDCASingleMarketSettings && removedIndicatorsSingleMarketSettings;
} catch (Exception ex) { }
catch (Exception ex)
{
ptmagicInstance.Log.DoLogCritical("Critical error while writing settings!", ex); ptmagicInstance.Log.DoLogCritical("Critical error while writing settings!", ex);
} }

View File

@ -13,12 +13,16 @@ using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Core.ProfitTrailer { namespace Core.ProfitTrailer
public static class StrategyHelper { {
public static string GetStrategyShortcut(string strategyName, bool onlyValidStrategies) { public static class StrategyHelper
{
public static string GetStrategyShortcut(string strategyName, bool onlyValidStrategies)
{
string result = strategyName; string result = strategyName;
switch (strategyName.ToLower()) { switch (strategyName.ToLower())
{
case "lowbb": case "lowbb":
result = "LBB"; result = "LBB";
break; break;
@ -122,8 +126,10 @@ namespace Core.ProfitTrailer {
break; break;
} }
if (onlyValidStrategies) { if (onlyValidStrategies)
if (strategyName.IndexOf("SOM") > -1 || strategyName.IndexOf("MAX") > -1 || strategyName.IndexOf("MIN") > -1 || strategyName.IndexOf("PRICE") > -1 || strategyName.IndexOf("BLACK") > -1 || strategyName.IndexOf("INSUFFICIENT") > -1 || strategyName.IndexOf("COST") > -1 || strategyName.IndexOf("TIMEOUT") > -1) { {
if (strategyName.IndexOf("SOM") > -1 || strategyName.IndexOf("MAX") > -1 || strategyName.IndexOf("MIN") > -1 || strategyName.IndexOf("PRICE") > -1 || strategyName.IndexOf("BLACK") > -1 || strategyName.IndexOf("INSUFFICIENT") > -1 || strategyName.IndexOf("COST") > -1 || strategyName.IndexOf("TIMEOUT") > -1)
{
result = ""; result = "";
} }
} }
@ -131,15 +137,19 @@ namespace Core.ProfitTrailer {
return result; return result;
} }
public static bool IsValidStrategy(string strategyName) { public static bool IsValidStrategy(string strategyName)
{
return StrategyHelper.IsValidStrategy(strategyName, false); return StrategyHelper.IsValidStrategy(strategyName, false);
} }
public static bool IsValidStrategy(string strategyName, bool checkForAnyInvalid) { public static bool IsValidStrategy(string strategyName, bool checkForAnyInvalid)
{
bool result = false; bool result = false;
if (!checkForAnyInvalid) { if (!checkForAnyInvalid)
switch (strategyName.ToLower()) { {
switch (strategyName.ToLower())
{
case "lowbb": case "lowbb":
case "highbb": case "highbb":
case "gain": case "gain":
@ -165,7 +175,9 @@ namespace Core.ProfitTrailer {
default: default:
break; break;
} }
} else { }
else
{
if (strategyName.IndexOf("max", StringComparison.InvariantCultureIgnoreCase) == -1 if (strategyName.IndexOf("max", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("min", StringComparison.InvariantCultureIgnoreCase) == -1 && strategyName.IndexOf("min", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("som", StringComparison.InvariantCultureIgnoreCase) == -1 && strategyName.IndexOf("som", StringComparison.InvariantCultureIgnoreCase) == -1
@ -175,7 +187,8 @@ namespace Core.ProfitTrailer {
&& strategyName.IndexOf("insufficient", StringComparison.InvariantCultureIgnoreCase) == -1 && strategyName.IndexOf("insufficient", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("timeout", StringComparison.InvariantCultureIgnoreCase) == -1 && strategyName.IndexOf("timeout", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("spread", StringComparison.InvariantCultureIgnoreCase) == -1 && strategyName.IndexOf("spread", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("pairs", StringComparison.InvariantCultureIgnoreCase) == -1) { && strategyName.IndexOf("pairs", StringComparison.InvariantCultureIgnoreCase) == -1)
{
result = true; result = true;
} }
} }
@ -183,10 +196,12 @@ namespace Core.ProfitTrailer {
return result; return result;
} }
public static int GetStrategyValueDecimals(string strategyName) { public static int GetStrategyValueDecimals(string strategyName)
{
int result = 0; int result = 0;
switch (strategyName.ToLower()) { switch (strategyName.ToLower())
{
case "lowbb": case "lowbb":
case "highbb": case "highbb":
result = 8; result = 8;
@ -220,34 +235,52 @@ namespace Core.ProfitTrailer {
return result; return result;
} }
public static string GetStrategyText(Summary summary, List<Strategy> strategies, string strategyText, bool isTrue, bool isTrailingBuyActive) { public static string GetStrategyText(Summary summary, List<Strategy> strategies, string strategyText, bool isTrue, bool isTrailingBuyActive)
if (strategies.Count > 0) { {
foreach (Strategy strategy in strategies) { if (strategies.Count > 0)
{
foreach (Strategy strategy in strategies)
{
string textClass = (strategy.IsTrue) ? "label-success" : "label-danger"; string textClass = (strategy.IsTrue) ? "label-success" : "label-danger";
if (!StrategyHelper.IsValidStrategy(strategy.Name)) { if (!StrategyHelper.IsValidStrategy(strategy.Name))
{
strategyText += "<span class=\"label label-warning\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategy.Name + "\">" + StrategyHelper.GetStrategyShortcut(strategy.Name, false) + "</span> "; strategyText += "<span class=\"label label-warning\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategy.Name + "\">" + StrategyHelper.GetStrategyShortcut(strategy.Name, false) + "</span> ";
} else { }
else
{
strategyText += "<span class=\"label " + textClass + "\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategy.Name + "\">" + StrategyHelper.GetStrategyShortcut(strategy.Name, false) + "</span> "; strategyText += "<span class=\"label " + textClass + "\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategy.Name + "\">" + StrategyHelper.GetStrategyShortcut(strategy.Name, false) + "</span> ";
} }
} }
if (isTrailingBuyActive) { if (isTrailingBuyActive)
{
strategyText += " <i class=\"fa fa-flag text-success\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Trailing active!\"></i>"; strategyText += " <i class=\"fa fa-flag text-success\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Trailing active!\"></i>";
} }
} else { }
if (isTrue) { else
{
if (isTrue)
{
strategyText = "<span class=\"label label-success\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, true) + "</span>"; strategyText = "<span class=\"label label-success\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, true) + "</span>";
if (isTrailingBuyActive) { if (isTrailingBuyActive)
{
strategyText += " <i class=\"fa fa-flag text-success\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Trailing active!\"></i>"; strategyText += " <i class=\"fa fa-flag text-success\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Trailing active!\"></i>";
} }
} else { }
if (StrategyHelper.IsValidStrategy(strategyText)) { else
{
if (StrategyHelper.IsValidStrategy(strategyText))
{
strategyText = "<span class=\"label label-danger\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, true) + "</span>"; strategyText = "<span class=\"label label-danger\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, true) + "</span>";
} else if (strategyText.Equals("")) { }
else if (strategyText.Equals(""))
{
strategyText = summary.DCABuyStrategy; strategyText = summary.DCABuyStrategy;
strategyText = "<span class=\"label label-danger\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, true) + "</span>"; strategyText = "<span class=\"label label-danger\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, true) + "</span>";
} else { }
else
{
strategyText = "<span class=\"label label-warning\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, false) + "</span> "; strategyText = "<span class=\"label label-warning\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, false) + "</span> ";
} }
} }
@ -256,43 +289,63 @@ namespace Core.ProfitTrailer {
return strategyText; return strategyText;
} }
public static string GetCurrentValueText(List<Strategy> strategies, string strategyText, double bbValue, double simpleValue, bool includeShortcut) { public static string GetCurrentValueText(List<Strategy> strategies, string strategyText, double bbValue, double simpleValue, bool includeShortcut)
{
string result = ""; string result = "";
if (strategies.Count > 0) { if (strategies.Count > 0)
foreach (Strategy strategy in strategies) { {
if (StrategyHelper.IsValidStrategy(strategy.Name)) { foreach (Strategy strategy in strategies)
{
if (StrategyHelper.IsValidStrategy(strategy.Name))
{
if (!result.Equals("")) result += "<br />"; if (!result.Equals("")) result += "<br />";
string decimalFormat = ""; string decimalFormat = "";
int decimals = StrategyHelper.GetStrategyValueDecimals(strategy.Name); int decimals = StrategyHelper.GetStrategyValueDecimals(strategy.Name);
for (int d = 1; d <= decimals; d++) { for (int d = 1; d <= decimals; d++)
{
decimalFormat += "0"; decimalFormat += "0";
} }
if (includeShortcut) { if (includeShortcut)
{
result += "<span class=\"text-muted\">" + StrategyHelper.GetStrategyShortcut(strategy.Name, true) + "</span> "; result += "<span class=\"text-muted\">" + StrategyHelper.GetStrategyShortcut(strategy.Name, true) + "</span> ";
} }
if (StrategyHelper.GetStrategyShortcut(strategy.Name, true).IndexOf("and", StringComparison.InvariantCultureIgnoreCase) > -1) { if (StrategyHelper.GetStrategyShortcut(strategy.Name, true).IndexOf("and", StringComparison.InvariantCultureIgnoreCase) > -1)
{
result += simpleValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")); result += simpleValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"));
} else { }
if (decimals == 0) { else
if (!SystemHelper.IsInteger(strategy.CurrentValue)) { {
if (decimals == 0)
{
if (!SystemHelper.IsInteger(strategy.CurrentValue))
{
result += strategy.CurrentValue.ToString("#,#", new System.Globalization.CultureInfo("en-US")); result += strategy.CurrentValue.ToString("#,#", new System.Globalization.CultureInfo("en-US"));
} else { }
else
{
result += strategy.CurrentValue.ToString("#,#0", new System.Globalization.CultureInfo("en-US")); result += strategy.CurrentValue.ToString("#,#0", new System.Globalization.CultureInfo("en-US"));
} }
} else { }
else
{
result += strategy.CurrentValue.ToString("#,#0." + decimalFormat, new System.Globalization.CultureInfo("en-US")); result += strategy.CurrentValue.ToString("#,#0." + decimalFormat, new System.Globalization.CultureInfo("en-US"));
} }
} }
} }
} }
} else { }
if (StrategyHelper.GetStrategyShortcut(strategyText, true).IndexOf("bb", StringComparison.InvariantCultureIgnoreCase) > -1) { else
{
if (StrategyHelper.GetStrategyShortcut(strategyText, true).IndexOf("bb", StringComparison.InvariantCultureIgnoreCase) > -1)
{
result = bbValue.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US")); result = bbValue.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"));
} else { }
else
{
result = simpleValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%"; result = simpleValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%";
} }
} }
@ -300,45 +353,67 @@ namespace Core.ProfitTrailer {
return result; return result;
} }
public static string GetTriggerValueText(Summary summary, List<Strategy> strategies, string strategyText, double bbValue, double simpleValue, int buyLevel, bool includeShortcut) { public static string GetTriggerValueText(Summary summary, List<Strategy> strategies, string strategyText, double bbValue, double simpleValue, int buyLevel, bool includeShortcut)
{
string result = ""; string result = "";
if (strategies.Count > 0) { if (strategies.Count > 0)
foreach (Strategy strategy in strategies) { {
if (StrategyHelper.IsValidStrategy(strategy.Name)) { foreach (Strategy strategy in strategies)
{
if (StrategyHelper.IsValidStrategy(strategy.Name))
{
if (!result.Equals("")) result += "<br />"; if (!result.Equals("")) result += "<br />";
string decimalFormat = ""; string decimalFormat = "";
int decimals = StrategyHelper.GetStrategyValueDecimals(strategy.Name); int decimals = StrategyHelper.GetStrategyValueDecimals(strategy.Name);
for (int d = 1; d <= decimals; d++) { for (int d = 1; d <= decimals; d++)
{
decimalFormat += "0"; decimalFormat += "0";
} }
if (includeShortcut) { if (includeShortcut)
{
result += "<span class=\"text-muted\">" + StrategyHelper.GetStrategyShortcut(strategy.Name, true) + "</span> "; result += "<span class=\"text-muted\">" + StrategyHelper.GetStrategyShortcut(strategy.Name, true) + "</span> ";
} }
if (StrategyHelper.GetStrategyShortcut(strategy.Name, true).IndexOf("and", StringComparison.InvariantCultureIgnoreCase) > -1) { if (StrategyHelper.GetStrategyShortcut(strategy.Name, true).IndexOf("and", StringComparison.InvariantCultureIgnoreCase) > -1)
{
result += strategy.TriggerValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")); result += strategy.TriggerValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"));
} else { }
if (decimals == 0) { else
if (!SystemHelper.IsInteger(strategy.EntryValue)) { {
if (decimals == 0)
{
if (!SystemHelper.IsInteger(strategy.EntryValue))
{
result += strategy.EntryValue.ToString(new System.Globalization.CultureInfo("en-US")); result += strategy.EntryValue.ToString(new System.Globalization.CultureInfo("en-US"));
} else { }
else
{
result += strategy.EntryValue.ToString("#,#0", new System.Globalization.CultureInfo("en-US")); result += strategy.EntryValue.ToString("#,#0", new System.Globalization.CultureInfo("en-US"));
} }
} else { }
else
{
result += strategy.EntryValue.ToString("#,#0." + decimalFormat, new System.Globalization.CultureInfo("en-US")); result += strategy.EntryValue.ToString("#,#0." + decimalFormat, new System.Globalization.CultureInfo("en-US"));
} }
} }
} }
} }
} else { }
if (StrategyHelper.GetStrategyShortcut(strategyText, true).IndexOf("bb", StringComparison.InvariantCultureIgnoreCase) > -1) { else
{
if (StrategyHelper.GetStrategyShortcut(strategyText, true).IndexOf("bb", StringComparison.InvariantCultureIgnoreCase) > -1)
{
result = bbValue.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US")); result = bbValue.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"));
} else { }
if (simpleValue == Constants.MinTrendChange) { else
if (summary.DCATriggers.ContainsKey(buyLevel + 1)) { {
if (simpleValue == Constants.MinTrendChange)
{
if (summary.DCATriggers.ContainsKey(buyLevel + 1))
{
simpleValue = summary.DCATriggers[buyLevel + 1]; simpleValue = summary.DCATriggers[buyLevel + 1];
} }
} }

View File

@ -6,17 +6,21 @@ using Core.Main;
using Core.Main.DataObjects; using Core.Main.DataObjects;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
namespace Monitor.Pages { namespace Monitor.Pages
public class BagAnalyzerModel : _Internal.BasePageModelSecure { {
public class BagAnalyzerModel : _Internal.BasePageModelSecure
{
public ProfitTrailerData PTData = null; public ProfitTrailerData PTData = null;
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
BindData(); BindData();
} }
private void BindData() { private void BindData()
{
PTData = new ProfitTrailerData(PTMagicBasePath, PTMagicConfiguration); PTData = new ProfitTrailerData(PTMagicBasePath, PTMagicConfiguration);
} }
} }

View File

@ -6,17 +6,21 @@ using Core.Main;
using Core.Main.DataObjects; using Core.Main.DataObjects;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
namespace Monitor.Pages { namespace Monitor.Pages
public class BuyAnalyzerModel : _Internal.BasePageModelSecure { {
public class BuyAnalyzerModel : _Internal.BasePageModelSecure
{
public ProfitTrailerData PTData = null; public ProfitTrailerData PTData = null;
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
BindData(); BindData();
} }
private void BindData() { private void BindData()
{
PTData = new ProfitTrailerData(PTMagicBasePath, PTMagicConfiguration); PTData = new ProfitTrailerData(PTMagicBasePath, PTMagicConfiguration);
} }
} }

View File

@ -4,17 +4,21 @@ using Core.Main;
using Core.Main.DataObjects; using Core.Main.DataObjects;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
namespace Monitor.Pages { namespace Monitor.Pages
public class DCACalculatorModel : _Internal.BasePageModelSecure { {
public class DCACalculatorModel : _Internal.BasePageModelSecure
{
public ProfitTrailerData PTData = null; public ProfitTrailerData PTData = null;
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
BindData(); BindData();
} }
private void BindData() { private void BindData()
{
PTData = new ProfitTrailerData(PTMagicBasePath, PTMagicConfiguration); PTData = new ProfitTrailerData(PTMagicBasePath, PTMagicConfiguration);
} }
} }

View File

@ -6,14 +6,17 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Monitor.Pages { namespace Monitor.Pages
public class ErrorModel : PageModel { {
public class ErrorModel : PageModel
{
public string RequestId { get; set; } public string RequestId { get; set; }
public IExceptionHandlerFeature Exception = null; public IExceptionHandlerFeature Exception = null;
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public void OnGet() { public void OnGet()
{
Exception = HttpContext.Features.Get<IExceptionHandlerFeature>(); Exception = HttpContext.Features.Get<IExceptionHandlerFeature>();
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;

View File

@ -1,7 +1,10 @@
namespace Monitor.Pages { namespace Monitor.Pages
public class IndexModel : _Internal.BasePageModelSecure { {
public class IndexModel : _Internal.BasePageModelSecure
{
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
} }
} }

View File

@ -4,29 +4,37 @@ using Microsoft.AspNetCore.Mvc;
using Core.Main; using Core.Main;
using Core.Helper; using Core.Helper;
namespace Monitor.Pages { namespace Monitor.Pages
public class LoginModel : _Internal.BasePageModel { {
public class LoginModel : _Internal.BasePageModel
{
public string CurrentPassword = ""; public string CurrentPassword = "";
public void OnGet() { public void OnGet()
{
base.PreInit(); base.PreInit();
CurrentPassword = PTMagicConfiguration.SecureSettings.MonitorPassword; CurrentPassword = PTMagicConfiguration.SecureSettings.MonitorPassword;
if (CurrentPassword.Equals("")) { if (CurrentPassword.Equals(""))
{
Response.Redirect(PTMagicConfiguration.GeneralSettings.Monitor.RootUrl + "SetupPassword"); Response.Redirect(PTMagicConfiguration.GeneralSettings.Monitor.RootUrl + "SetupPassword");
} }
} }
public void OnPost(string password, string cbRememberMe) { public void OnPost(string password, string cbRememberMe)
{
base.PreInit(); base.PreInit();
string encryptedPassword = EncryptionHelper.Encrypt(password); string encryptedPassword = EncryptionHelper.Encrypt(password);
if (encryptedPassword.Equals(PTMagicConfiguration.SecureSettings.MonitorPassword)) { if (encryptedPassword.Equals(PTMagicConfiguration.SecureSettings.MonitorPassword))
{
HttpContext.Session.SetString("LoggedIn" + PTMagicConfiguration.GeneralSettings.Monitor.Port.ToString(), DateTime.Now.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'")); HttpContext.Session.SetString("LoggedIn" + PTMagicConfiguration.GeneralSettings.Monitor.Port.ToString(), DateTime.Now.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'"));
if (cbRememberMe != null) { if (cbRememberMe != null)
if (cbRememberMe.Equals("on", StringComparison.InvariantCultureIgnoreCase)) { {
if (cbRememberMe.Equals("on", StringComparison.InvariantCultureIgnoreCase))
{
CookieOptions cookieOption = new CookieOptions(); CookieOptions cookieOption = new CookieOptions();
cookieOption.Expires = DateTime.Now.AddYears(1); cookieOption.Expires = DateTime.Now.AddYears(1);

View File

@ -7,40 +7,53 @@ using Core.Main;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Monitor.Pages { namespace Monitor.Pages
public class ManageSMSModel : _Internal.BasePageModelSecure { {
public class ManageSMSModel : _Internal.BasePageModelSecure
{
public List<SingleMarketSettingSummary> SingleMarketSettingSummaries = new List<SingleMarketSettingSummary>(); public List<SingleMarketSettingSummary> SingleMarketSettingSummaries = new List<SingleMarketSettingSummary>();
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
BindData(); BindData();
} }
private void BindData() { private void BindData()
if (System.IO.File.Exists(PTMagicBasePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar + "SingleMarketSettingSummary.json")) { {
try { if (System.IO.File.Exists(PTMagicBasePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar + "SingleMarketSettingSummary.json"))
{
try
{
SingleMarketSettingSummaries = JsonConvert.DeserializeObject<List<SingleMarketSettingSummary>>(System.IO.File.ReadAllText(PTMagicBasePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar + "SingleMarketSettingSummary.json")); SingleMarketSettingSummaries = JsonConvert.DeserializeObject<List<SingleMarketSettingSummary>>(System.IO.File.ReadAllText(PTMagicBasePath + Constants.PTMagicPathData + Path.DirectorySeparatorChar + "SingleMarketSettingSummary.json"));
} catch { } }
catch { }
} }
string notification = GetStringParameter("n", ""); string notification = GetStringParameter("n", "");
if (notification.Equals("SettingReset")) { if (notification.Equals("SettingReset"))
{
NotifyHeadline = "Setting Reset!"; NotifyHeadline = "Setting Reset!";
NotifyMessage = "The setting will get reset on the next interval!"; NotifyMessage = "The setting will get reset on the next interval!";
NotifyType = "success"; NotifyType = "success";
} }
} }
public double GetTrendChange(string marketTrend, MarketPairSummary mps, TriggerSnapshot ts, string marketTrendRelation) { public double GetTrendChange(string marketTrend, MarketPairSummary mps, TriggerSnapshot ts, string marketTrendRelation)
{
double result = 0; double result = 0;
if (mps.MarketTrendChanges.ContainsKey(marketTrend)) { if (mps.MarketTrendChanges.ContainsKey(marketTrend))
{
result = mps.MarketTrendChanges[marketTrend]; result = mps.MarketTrendChanges[marketTrend];
double averageMarketTrendChange = Summary.MarketTrendChanges[marketTrend].OrderByDescending(mtc => mtc.TrendDateTime).First().TrendChange; double averageMarketTrendChange = Summary.MarketTrendChanges[marketTrend].OrderByDescending(mtc => mtc.TrendDateTime).First().TrendChange;
if (marketTrendRelation.Equals(Constants.MarketTrendRelationAbsolute, StringComparison.InvariantCulture)) { if (marketTrendRelation.Equals(Constants.MarketTrendRelationAbsolute, StringComparison.InvariantCulture))
{
result = result - averageMarketTrendChange; result = result - averageMarketTrendChange;
} else if (marketTrendRelation.Equals(Constants.MarketTrendRelationRelativeTrigger, StringComparison.InvariantCulture)) { }
else if (marketTrendRelation.Equals(Constants.MarketTrendRelationRelativeTrigger, StringComparison.InvariantCulture))
{
double currentPrice = mps.LatestPrice; double currentPrice = mps.LatestPrice;
double triggerPrice = ts.LastPrice; double triggerPrice = ts.LastPrice;
double triggerTrend = (currentPrice - triggerPrice) / triggerPrice * 100; double triggerTrend = (currentPrice - triggerPrice) / triggerPrice * 100;

View File

@ -6,41 +6,54 @@ using Core.Main;
using Core.Helper; using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
namespace Monitor.Pages { namespace Monitor.Pages
public class MarketAnalyzerModel : _Internal.BasePageModelSecure { {
public class MarketAnalyzerModel : _Internal.BasePageModelSecure
{
public List<MarketTrend> MarketTrends { get; set; } = new List<MarketTrend>(); public List<MarketTrend> MarketTrends { get; set; } = new List<MarketTrend>();
public string TrendChartDataJSON = ""; public string TrendChartDataJSON = "";
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
BindData(); BindData();
} }
private void BindData() { private void BindData()
{
// Get market trends // Get market trends
MarketTrends = PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.OrderBy(mt => mt.TrendMinutes).ThenByDescending(mt => mt.Platform).ToList(); MarketTrends = PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.OrderBy(mt => mt.TrendMinutes).ThenByDescending(mt => mt.Platform).ToList();
BuildMarketTrendChartData(); BuildMarketTrendChartData();
} }
private void BuildMarketTrendChartData() { private void BuildMarketTrendChartData()
if (MarketTrends.Count > 0) { {
if (MarketTrends.Count > 0)
{
TrendChartDataJSON = "["; TrendChartDataJSON = "[";
int mtIndex = 0; int mtIndex = 0;
foreach (MarketTrend mt in MarketTrends) { foreach (MarketTrend mt in MarketTrends)
if (mt.DisplayGraph) { {
if (mt.DisplayGraph)
{
string lineColor = ""; string lineColor = "";
if (mtIndex < Constants.ChartLineColors.Length) { if (mtIndex < Constants.ChartLineColors.Length)
{
lineColor = Constants.ChartLineColors[mtIndex]; lineColor = Constants.ChartLineColors[mtIndex];
} else { }
else
{
lineColor = Constants.ChartLineColors[mtIndex - 20]; lineColor = Constants.ChartLineColors[mtIndex - 20];
} }
if (Summary.MarketTrendChanges.ContainsKey(mt.Name)) { if (Summary.MarketTrendChanges.ContainsKey(mt.Name))
{
List<MarketTrendChange> marketTrendChangeSummaries = Summary.MarketTrendChanges[mt.Name]; List<MarketTrendChange> marketTrendChangeSummaries = Summary.MarketTrendChanges[mt.Name];
if (marketTrendChangeSummaries.Count > 0) { if (marketTrendChangeSummaries.Count > 0)
{
if (!TrendChartDataJSON.Equals("[")) TrendChartDataJSON += ","; if (!TrendChartDataJSON.Equals("[")) TrendChartDataJSON += ",";
TrendChartDataJSON += "{"; TrendChartDataJSON += "{";
@ -53,9 +66,11 @@ namespace Monitor.Pages {
DateTime startDateTime = currentDateTime.AddHours(-PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours); DateTime startDateTime = currentDateTime.AddHours(-PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours);
DateTime endDateTime = currentDateTime; DateTime endDateTime = currentDateTime;
int trendChartTicks = 0; int trendChartTicks = 0;
for (DateTime tickTime = startDateTime; tickTime <= endDateTime; tickTime = tickTime.AddMinutes(PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes)) { for (DateTime tickTime = startDateTime; tickTime <= endDateTime; tickTime = tickTime.AddMinutes(PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes))
{
List<MarketTrendChange> tickRange = marketTrendChangeSummaries.FindAll(m => m.TrendDateTime >= tickTime).OrderBy(m => m.TrendDateTime).ToList(); List<MarketTrendChange> tickRange = marketTrendChangeSummaries.FindAll(m => m.TrendDateTime >= tickTime).OrderBy(m => m.TrendDateTime).ToList();
if (tickRange.Count > 0) { if (tickRange.Count > 0)
{
MarketTrendChange mtc = tickRange.First(); MarketTrendChange mtc = tickRange.First();
if (tickTime != startDateTime) TrendChartDataJSON += ",\n"; if (tickTime != startDateTime) TrendChartDataJSON += ",\n";
if (Double.IsInfinity(mtc.TrendChange)) mtc.TrendChange = 0; if (Double.IsInfinity(mtc.TrendChange)) mtc.TrendChange = 0;
@ -67,7 +82,8 @@ namespace Monitor.Pages {
// Add most recent tick // Add most recent tick
List<MarketTrendChange> latestTickRange = marketTrendChangeSummaries.OrderByDescending(m => m.TrendDateTime).ToList(); List<MarketTrendChange> latestTickRange = marketTrendChangeSummaries.OrderByDescending(m => m.TrendDateTime).ToList();
if (latestTickRange.Count > 0) { if (latestTickRange.Count > 0)
{
MarketTrendChange mtc = latestTickRange.First(); MarketTrendChange mtc = latestTickRange.First();
if (trendChartTicks > 0) TrendChartDataJSON += ",\n"; if (trendChartTicks > 0) TrendChartDataJSON += ",\n";
if (Double.IsInfinity(mtc.TrendChange)) mtc.TrendChange = 0; if (Double.IsInfinity(mtc.TrendChange)) mtc.TrendChange = 0;

View File

@ -7,26 +7,33 @@ using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using System.Globalization; using System.Globalization;
namespace Monitor.Pages { namespace Monitor.Pages
public class PresetFilesModel : _Internal.BasePageModelSecure { {
public class PresetFilesModel : _Internal.BasePageModelSecure
{
public List<GlobalSetting> GlobalSettingsWithPresets = new List<GlobalSetting>(); public List<GlobalSetting> GlobalSettingsWithPresets = new List<GlobalSetting>();
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
BindData(); BindData();
} }
public void BindData() { public void BindData()
{
string notification = GetStringParameter("n", ""); string notification = GetStringParameter("n", "");
if (notification.Equals("PresetFileSaved")) { if (notification.Equals("PresetFileSaved"))
{
NotifyHeadline = "Preset File Saved!"; NotifyHeadline = "Preset File Saved!";
NotifyMessage = "The preset file was saved and will be applied during the next interval."; NotifyMessage = "The preset file was saved and will be applied during the next interval.";
NotifyType = "success"; NotifyType = "success";
} }
foreach (GlobalSetting globalSetting in PTMagicConfiguration.AnalyzerSettings.GlobalSettings) { foreach (GlobalSetting globalSetting in PTMagicConfiguration.AnalyzerSettings.GlobalSettings)
if (globalSetting.PairsProperties.ContainsKey("File") || globalSetting.DCAProperties.ContainsKey("File") || globalSetting.IndicatorsProperties.ContainsKey("File")) { {
if (globalSetting.PairsProperties.ContainsKey("File") || globalSetting.DCAProperties.ContainsKey("File") || globalSetting.IndicatorsProperties.ContainsKey("File"))
{
GlobalSettingsWithPresets.Add(globalSetting); GlobalSettingsWithPresets.Add(globalSetting);
} }
} }

View File

@ -7,8 +7,10 @@ using Core.Helper;
using Core.Main.DataObjects; using Core.Main.DataObjects;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
namespace Monitor.Pages { namespace Monitor.Pages
public class SalesAnalyzer : _Internal.BasePageModelSecure { {
public class SalesAnalyzer : _Internal.BasePageModelSecure
{
public ProfitTrailerData PTData = null; public ProfitTrailerData PTData = null;
public string TradesChartDataJSON = ""; public string TradesChartDataJSON = "";
public string ProfitChartDataJSON = ""; public string ProfitChartDataJSON = "";
@ -18,13 +20,15 @@ namespace Monitor.Pages {
public Dictionary<DateTime, double> MonthlyGains = new Dictionary<DateTime, double>(); public Dictionary<DateTime, double> MonthlyGains = new Dictionary<DateTime, double>();
public DateTimeOffset DateTimeNow = Constants.confMinDate; public DateTimeOffset DateTimeNow = Constants.confMinDate;
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
BindData(); BindData();
} }
private void BindData() { private void BindData()
{
PTData = new ProfitTrailerData(PTMagicBasePath, PTMagicConfiguration); PTData = new ProfitTrailerData(PTMagicBasePath, PTMagicConfiguration);
// Convert local offset time to UTC // Convert local offset time to UTC
@ -35,10 +39,12 @@ namespace Monitor.Pages {
BuildSalesChartData(); BuildSalesChartData();
} }
private void BuildTopMarkets() { private void BuildTopMarkets()
{
var markets = PTData.SellLog.GroupBy(m => m.Market); var markets = PTData.SellLog.GroupBy(m => m.Market);
Dictionary<string, double> topMarketsDic = new Dictionary<string, double>(); Dictionary<string, double> topMarketsDic = new Dictionary<string, double>();
foreach (var market in markets) { foreach (var market in markets)
{
double totalProfit = PTData.SellLog.FindAll(m => m.Market == market.Key).Sum(m => m.Profit); double totalProfit = PTData.SellLog.FindAll(m => m.Market == market.Key).Sum(m => m.Profit);
topMarketsDic.Add(market.Key, totalProfit); topMarketsDic.Add(market.Key, totalProfit);
@ -46,8 +52,10 @@ namespace Monitor.Pages {
TopMarkets = new SortedDictionary<string, double>(topMarketsDic).OrderByDescending(m => m.Value).Take(PTMagicConfiguration.GeneralSettings.Monitor.MaxTopMarkets); TopMarkets = new SortedDictionary<string, double>(topMarketsDic).OrderByDescending(m => m.Value).Take(PTMagicConfiguration.GeneralSettings.Monitor.MaxTopMarkets);
} }
private void BuildSalesChartData() { private void BuildSalesChartData()
if (PTData.SellLog.Count > 0) { {
if (PTData.SellLog.Count > 0)
{
MinSellLogDate = PTData.SellLog.OrderBy(sl => sl.SoldDate).First().SoldDate.Date; MinSellLogDate = PTData.SellLog.OrderBy(sl => sl.SoldDate).First().SoldDate.Date;
DateTime graphStartDate = DateTimeNow.DateTime.Date.AddDays(-30); DateTime graphStartDate = DateTimeNow.DateTime.Date.AddDays(-30);
if (MinSellLogDate > graphStartDate) graphStartDate = MinSellLogDate; if (MinSellLogDate > graphStartDate) graphStartDate = MinSellLogDate;
@ -55,8 +63,10 @@ namespace Monitor.Pages {
int tradeDayIndex = 0; int tradeDayIndex = 0;
string tradesPerDayJSON = ""; string tradesPerDayJSON = "";
string profitPerDayJSON = ""; string profitPerDayJSON = "";
for (DateTime salesDate = graphStartDate; salesDate <= DateTimeNow.DateTime.Date; salesDate = salesDate.AddDays(1)) { for (DateTime salesDate = graphStartDate; salesDate <= DateTimeNow.DateTime.Date; salesDate = salesDate.AddDays(1))
if (tradeDayIndex > 0) { {
if (tradeDayIndex > 0)
{
tradesPerDayJSON += ",\n"; tradesPerDayJSON += ",\n";
profitPerDayJSON += ",\n"; profitPerDayJSON += ",\n";
} }
@ -87,7 +97,8 @@ namespace Monitor.Pages {
ProfitChartDataJSON += "}"; ProfitChartDataJSON += "}";
ProfitChartDataJSON += "]"; ProfitChartDataJSON += "]";
for (DateTime salesDate = DateTimeNow.DateTime.Date; salesDate >= MinSellLogDate; salesDate = salesDate.AddDays(-1)) { for (DateTime salesDate = DateTimeNow.DateTime.Date; salesDate >= MinSellLogDate; salesDate = salesDate.AddDays(-1))
{
List<SellLogData> salesDateSales = PTData.SellLog.FindAll(sl => sl.SoldDate.Date == salesDate); List<SellLogData> salesDateSales = PTData.SellLog.FindAll(sl => sl.SoldDate.Date == salesDate);
double salesDateProfit = salesDateSales.Sum(sl => sl.Profit); double salesDateProfit = salesDateSales.Sum(sl => sl.Profit);
double salesDateStartBalance = PTData.GetSnapshotBalance(salesDate); double salesDateStartBalance = PTData.GetSnapshotBalance(salesDate);
@ -98,7 +109,8 @@ namespace Monitor.Pages {
DateTime minSellLogMonthDate = new DateTime(MinSellLogDate.Year, MinSellLogDate.Month, 1).Date; DateTime minSellLogMonthDate = new DateTime(MinSellLogDate.Year, MinSellLogDate.Month, 1).Date;
DateTime salesMonthStartDate = new DateTime(DateTimeNow.DateTime.Year, DateTimeNow.DateTime.Month, 1).Date; DateTime salesMonthStartDate = new DateTime(DateTimeNow.DateTime.Year, DateTimeNow.DateTime.Month, 1).Date;
for (DateTime salesMonthDate = salesMonthStartDate.Date; salesMonthDate >= minSellLogMonthDate; salesMonthDate = salesMonthDate.AddMonths(-1)) { for (DateTime salesMonthDate = salesMonthStartDate.Date; salesMonthDate >= minSellLogMonthDate; salesMonthDate = salesMonthDate.AddMonths(-1))
{
List<Core.Main.DataObjects.PTMagicData.SellLogData> salesMonthSales = PTData.SellLog.FindAll(sl => sl.SoldDate.Date.Month == salesMonthDate.Month && sl.SoldDate.Date.Year == salesMonthDate.Year); List<Core.Main.DataObjects.PTMagicData.SellLogData> salesMonthSales = PTData.SellLog.FindAll(sl => sl.SoldDate.Date.Month == salesMonthDate.Month && sl.SoldDate.Date.Year == salesMonthDate.Year);
double salesDateProfit = salesMonthSales.Sum(sl => sl.Profit); double salesDateProfit = salesMonthSales.Sum(sl => sl.Profit);
double salesDateStartBalance = PTData.GetSnapshotBalance(salesMonthDate); double salesDateStartBalance = PTData.GetSnapshotBalance(salesMonthDate);

View File

@ -68,7 +68,6 @@
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<h4 class="m-t-0 header-title">Market Trends (@Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.Count)</h4> <h4 class="m-t-0 header-title">Market Trends (@Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.Count)</h4>
<ul> <ul>
@foreach (Core.Main.DataObjects.PTMagicData.MarketTrend mt in Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends) { @foreach (Core.Main.DataObjects.PTMagicData.MarketTrend mt in Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends) {
<li><a href="#MarketTrend_@Core.Helper.SystemHelper.StripBadCode(mt.Name, Core.Main.Constants.WhiteListNames)">@Core.Helper.SystemHelper.SplitCamelCase(mt.Name)</a></li> <li><a href="#MarketTrend_@Core.Helper.SystemHelper.StripBadCode(mt.Name, Core.Main.Constants.WhiteListNames)">@Core.Helper.SystemHelper.SplitCamelCase(mt.Name)</a></li>
@ -102,32 +101,14 @@
</button> </button>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="btn-group btn-block"> <button class="btn btn-ptmagic btn-custom btn-block text-uppercase waves-effect waves-light btn-new" data-datatype="GlobalSetting">
<button class="btn btn-ptmagic btn-custom btn-block text-uppercase waves-effect waves-light dropdown-toggle" data-toggle="dropdown"> Add Global Setting
Add Global Setting </button>
</button>
<div class="dropdown-menu">
@foreach (Core.Main.DataObjects.PTMagicData.GlobalSetting gs in Model.PTMagicConfiguration.AnalyzerSettings.GlobalSettings) {
<a class="dropdown-item btn-new" data-datatype="GlobalSetting" data-datatarget="@Core.Helper.SystemHelper.StripBadCode(gs.SettingName, Core.Main.Constants.WhiteListNames)">Add before <i>@Core.Helper.SystemHelper.SplitCamelCase(gs.SettingName)</i></a>
}
</div>
</div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="btn-group btn-block"> <button class="btn btn-ptmagic btn-custom btn-block text-uppercase waves-effect waves-light btn-new" data-datatype="SingleMarketSetting">
<button class="btn btn-ptmagic btn-custom btn-block text-uppercase waves-effect waves-light dropdown-toggle" data-toggle="dropdown"> Add Single Market Setting
Add Single Market Setting </button>
</button>
<div class="dropdown-menu">
@foreach (Core.Main.DataObjects.PTMagicData.SingleMarketSetting sms in Model.PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings) {
<a class="dropdown-item btn-new" data-datatype="SingleMarketSetting" data-datadirection="before" data-datatarget="@Core.Helper.SystemHelper.StripBadCode(sms.SettingName, Core.Main.Constants.WhiteListNames)">Add before <i>@Core.Helper.SystemHelper.SplitCamelCase(sms.SettingName)</i></a>
}
<div class="dropdown-divider"></div>
@foreach (Core.Main.DataObjects.PTMagicData.SingleMarketSetting sms in Model.PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings) {
<a class="dropdown-item btn-new" data-datatype="SingleMarketSetting" data-datadirection="after" data-datatarget="@Core.Helper.SystemHelper.StripBadCode(sms.SettingName, Core.Main.Constants.WhiteListNames)">Add after <i>@Core.Helper.SystemHelper.SplitCamelCase(sms.SettingName)</i></a>
}
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -138,26 +119,33 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="card-box"> <div class="card-box">
<h4 class="m-t-0 header-title">Market Analyzer</h4> <div class="panel-group" style="">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><strong><a href="#collapse0" data-toggle="collapse">MARKET ANALYZER</a></strong></h3>
</div>
<div id="collapse0" class="panel-collapse collapse">
<div class="form-group row">
<label class="col-md-4 col-form-label">Store Data Max Hours <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Number of hours to store market data."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="MarketAnalyzer_StoreDataMaxHours" value="@Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours.ToString()">
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Store Data Max Hours <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Number of hours to store market data."></i></label> <label class="col-md-4 col-form-label">Interval Minutes <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Interval in minutes for PTMagic to check market trends and triggers."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="MarketAnalyzer_StoreDataMaxHours" value="@Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours.ToString()"> <input type="text" class="form-control" name="MarketAnalyzer_IntervalMinutes" value="@Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes.ToString()">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Interval Minutes <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Interval in minutes for PTMagic to check market trends and triggers."></i></label> <label class="col-md-4 col-form-label">Exclude Main Currency <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Excludes the main currency (for example BTC) from market trend analysis."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="MarketAnalyzer_IntervalMinutes" value="@Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes.ToString()"> <input type="checkbox" name="MarketAnalyzer_ExcludeMainCurrency" checked="@(Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.ExcludeMainCurrency)" data-plugin="switchery" data-color="#81c868" data-size="small" />
</div> </div>
</div> </div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Exclude Main Currency <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Excludes the main currency (for example BTC) from market trend analysis."></i></label>
<div class="col-md-8">
<input type="checkbox" name="MarketAnalyzer_ExcludeMainCurrency" checked="@(Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.ExcludeMainCurrency)" data-plugin="switchery" data-color="#81c868" data-size="small" />
</div> </div>
</div> </div>
</div> </div>
@ -167,7 +155,22 @@
<div id="MarketAnalyzer_MarketTrends"> <div id="MarketAnalyzer_MarketTrends">
@if (Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.Count > 0) { @if (Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.Count > 0) {
@foreach (Core.Main.DataObjects.PTMagicData.MarketTrend mt in Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends) { @foreach (Core.Main.DataObjects.PTMagicData.MarketTrend mt in Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends) {
<div class="settings-markettrend" data-trendname="@Core.Helper.SystemHelper.StripBadCode(mt.Name, Core.Main.Constants.WhiteListNames)" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div> <div class="row">
<div class="col-md-12">
<div class="card-box">
<div class="panel-group" style="">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><strong><a href="#@Core.Helper.SystemHelper.StripBadCode(mt.Name, Core.Main.Constants.WhiteListNames)" data-toggle="collapse">MARKET TREND: @Core.Helper.SystemHelper.StripBadCode(mt.Name, Core.Main.Constants.WhiteListNames)</a></strong></h3>
</div>
<div id="@Core.Helper.SystemHelper.StripBadCode(mt.Name, Core.Main.Constants.WhiteListNames)" class="panel-collapse collapse">
<div class="settings-markettrend" data-trendname="@Core.Helper.SystemHelper.StripBadCode(mt.Name, Core.Main.Constants.WhiteListNames)" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div>
</div>
</div>
</div>
</div>
</div>
</div>
} }
} else { } else {
<div class="row"> <div class="row">
@ -183,7 +186,22 @@
<div id="MarketAnalyzer_GlobalSettings"> <div id="MarketAnalyzer_GlobalSettings">
@if (Model.PTMagicConfiguration.AnalyzerSettings.GlobalSettings.Count > 0) { @if (Model.PTMagicConfiguration.AnalyzerSettings.GlobalSettings.Count > 0) {
@foreach (Core.Main.DataObjects.PTMagicData.GlobalSetting gs in Model.PTMagicConfiguration.AnalyzerSettings.GlobalSettings) { @foreach (Core.Main.DataObjects.PTMagicData.GlobalSetting gs in Model.PTMagicConfiguration.AnalyzerSettings.GlobalSettings) {
<div class="settings-globalsetting" data-settingname="@Core.Helper.SystemHelper.StripBadCode(gs.SettingName, Core.Main.Constants.WhiteListNames)" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div> <div class="row">
<div class="col-md-12">
<div class="card-box">
<div class="panel-group" style="">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><strong><a href="#@Core.Helper.SystemHelper.StripBadCode(gs.SettingName, Core.Main.Constants.WhiteListNames)" data-toggle="collapse">GLOBAL SETTING: @Core.Helper.SystemHelper.StripBadCode(gs.SettingName, Core.Main.Constants.WhiteListNames)</a></strong></h3>
</div>
<div id="@Core.Helper.SystemHelper.StripBadCode(gs.SettingName, Core.Main.Constants.WhiteListNames)" class="panel-collapse collapse">
<div class="settings-globalsetting" data-settingname="@Core.Helper.SystemHelper.StripBadCode(gs.SettingName, Core.Main.Constants.WhiteListNames)" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div>
</div>
</div>
</div>
</div>
</div>
</div>
} }
} else { } else {
<div class="row"> <div class="row">
@ -199,7 +217,22 @@
<div id="MarketAnalyzer_SingleMarketSettings"> <div id="MarketAnalyzer_SingleMarketSettings">
@if (Model.PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings.Count > 0) { @if (Model.PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings.Count > 0) {
@foreach (Core.Main.DataObjects.PTMagicData.SingleMarketSetting sms in Model.PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings) { @foreach (Core.Main.DataObjects.PTMagicData.SingleMarketSetting sms in Model.PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings) {
<div class="settings-singlemarketsetting" data-settingname="@Core.Helper.SystemHelper.StripBadCode(sms.SettingName, Core.Main.Constants.WhiteListNames)" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div> <div class="row">
<div class="col-md-12">
<div class="card-box">
<div class="panel-group" style="">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><strong><a href="#@Core.Helper.SystemHelper.StripBadCode(sms.SettingName, Core.Main.Constants.WhiteListNames)" data-toggle="collapse">SINGLE MARKET SETTING: @Core.Helper.SystemHelper.StripBadCode(sms.SettingName, Core.Main.Constants.WhiteListNames)</a></strong></h3>
</div>
<div id="@Core.Helper.SystemHelper.StripBadCode(sms.SettingName, Core.Main.Constants.WhiteListNames)" class="panel-collapse collapse">
<div class="settings-singlemarketsetting" data-settingname="@Core.Helper.SystemHelper.StripBadCode(sms.SettingName, Core.Main.Constants.WhiteListNames)" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div>
</div>
</div>
</div>
</div>
</div>
</div>
} }
} else { } else {
<div class="row"> <div class="row">
@ -211,7 +244,6 @@
</div> </div>
} }
</div> </div>
<div id="div-loading-settings" class="row"> <div id="div-loading-settings" class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="card-box"> <div class="card-box">
@ -299,18 +331,14 @@
$('.settings-markettrend.new').buildMarketTrendSettings(); $('.settings-markettrend.new').buildMarketTrendSettings();
break; break;
case 'GlobalSetting': case 'GlobalSetting':
$('html, body').scrollTop($('#MarketAnalyzer_GlobalSettings > [data-settingname="' + dataTarget + '"]').offset().top - 100); $('#MarketAnalyzer_GlobalSettings').append('<div class="settings-globalsetting new" data-settingname="" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div>');
$('#MarketAnalyzer_GlobalSettings > [data-settingname="' + dataTarget + '"]').before('<div class="settings-globalsetting new" data-settingname="" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div>'); $('html, body').scrollTop($('#MarketAnalyzer_GlobalSettings').offset().top + $('#MarketAnalyzer_GlobalSettings').height() - 100);
$('.settings-globalsetting.new').buildGlobalSettings(); $('.settings-globalsetting.new').buildGlobalSettings();
break; break;
case 'SingleMarketSetting': case 'SingleMarketSetting':
if (dataDirection === 'before') {
$('html, body').scrollTop($('#MarketAnalyzer_SingleMarketSettings > [data-settingname="' + dataTarget + '"]').offset().top - 100); $('#MarketAnalyzer_SingleMarketSettings').append('<div class="settings-singlemarketsetting new" data-settingname="" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div>');
$('#MarketAnalyzer_SingleMarketSettings > [data-settingname="' + dataTarget + '"]').before('<div class="settings-singlemarketsetting new" data-settingname="" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div>'); $('html, body').scrollTop($('#MarketAnalyzer_SingleMarketSettings').offset().top + $('#MarketAnalyzer_SingleMarketSettings').height() - 100);
} else {
$('html, body').scrollTop($('#MarketAnalyzer_SingleMarketSettings > [data-settingname="' + dataTarget + '"]').offset().top + $('#MarketAnalyzer_SingleMarketSettings > [data-settingname="' + dataTarget + '"]').height() - 100);
$('#MarketAnalyzer_SingleMarketSettings > [data-settingname="' + dataTarget + '"]').after('<div class="settings-singlemarketsetting new" data-settingname="" data-rooturl="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div>');
}
$('.settings-singlemarketsetting.new').buildSingleMarketSettings(); $('.settings-singlemarketsetting.new').buildSingleMarketSettings();
break; break;
} }

View File

@ -7,22 +7,27 @@ using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
namespace Monitor.Pages { namespace Monitor.Pages
public class SettingsAnalyzerModel : _Internal.BasePageModelSecure { {
public class SettingsAnalyzerModel : _Internal.BasePageModelSecure
{
public string ValidationMessage = ""; public string ValidationMessage = "";
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
string notification = GetStringParameter("n", ""); string notification = GetStringParameter("n", "");
if (notification.Equals("BackupRestored")) { if (notification.Equals("BackupRestored"))
{
NotifyHeadline = "Backup restored!"; NotifyHeadline = "Backup restored!";
NotifyMessage = "Your backup of settings.analyzer.json was successfully restored."; NotifyMessage = "Your backup of settings.analyzer.json was successfully restored.";
NotifyType = "success"; NotifyType = "success";
} }
} }
public void OnPost() { public void OnPost()
{
base.Init(); base.Init();
PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours = SystemHelper.TextToInteger(HttpContext.Request.Form["MarketAnalyzer_StoreDataMaxHours"], PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours); PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours = SystemHelper.TextToInteger(HttpContext.Request.Form["MarketAnalyzer_StoreDataMaxHours"], PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.StoreDataMaxHours);
@ -42,18 +47,23 @@ namespace Monitor.Pages {
NotifyType = "success"; NotifyType = "success";
} }
private void SaveMarketTrends(List<string> formKeys) { private void SaveMarketTrends(List<string> formKeys)
{
List<MarketTrend> newMarketTrends = new List<MarketTrend>(); List<MarketTrend> newMarketTrends = new List<MarketTrend>();
List<string> marketTrendFormKeys = formKeys.FindAll(k => k.StartsWith("MarketAnalyzer_MarketTrend_") && k.EndsWith("|Name")); List<string> marketTrendFormKeys = formKeys.FindAll(k => k.StartsWith("MarketAnalyzer_MarketTrend_") && k.EndsWith("|Name"));
foreach (string marketTrendFormKey in marketTrendFormKeys) { foreach (string marketTrendFormKey in marketTrendFormKeys)
{
MarketTrend mt = null; MarketTrend mt = null;
string originalNameSimplified = marketTrendFormKey.Replace("MarketAnalyzer_MarketTrend_", "").Replace("|Name", ""); string originalNameSimplified = marketTrendFormKey.Replace("MarketAnalyzer_MarketTrend_", "").Replace("|Name", "");
string mtFormKey = "MarketAnalyzer_MarketTrend_" + originalNameSimplified + "|"; string mtFormKey = "MarketAnalyzer_MarketTrend_" + originalNameSimplified + "|";
if (originalNameSimplified.Equals("")) { if (originalNameSimplified.Equals(""))
{
mt = new MarketTrend(); mt = new MarketTrend();
} else { }
else
{
mt = PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.Find(m => SystemHelper.StripBadCode(m.Name, Constants.WhiteListNames).Equals(originalNameSimplified)); mt = PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.Find(m => SystemHelper.StripBadCode(m.Name, Constants.WhiteListNames).Equals(originalNameSimplified));
} }
@ -72,18 +82,23 @@ namespace Monitor.Pages {
PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends = newMarketTrends; PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends = newMarketTrends;
} }
private void SaveGlobalSettings(List<string> formKeys) { private void SaveGlobalSettings(List<string> formKeys)
{
List<GlobalSetting> newGlobalMarketSettings = new List<GlobalSetting>(); List<GlobalSetting> newGlobalMarketSettings = new List<GlobalSetting>();
List<string> globalSettingFormKeys = formKeys.FindAll(k => k.StartsWith("MarketAnalyzer_GlobalSetting_") && k.EndsWith("|SettingName")); List<string> globalSettingFormKeys = formKeys.FindAll(k => k.StartsWith("MarketAnalyzer_GlobalSetting_") && k.EndsWith("|SettingName"));
foreach (string globalSettingFormKey in globalSettingFormKeys) { foreach (string globalSettingFormKey in globalSettingFormKeys)
{
GlobalSetting gs = null; GlobalSetting gs = null;
string originalNameSimplified = globalSettingFormKey.Replace("MarketAnalyzer_GlobalSetting_", "").Replace("|SettingName", ""); string originalNameSimplified = globalSettingFormKey.Replace("MarketAnalyzer_GlobalSetting_", "").Replace("|SettingName", "");
string gsFormKey = "MarketAnalyzer_GlobalSetting_" + originalNameSimplified + "|"; string gsFormKey = "MarketAnalyzer_GlobalSetting_" + originalNameSimplified + "|";
if (originalNameSimplified.Equals("")) { if (originalNameSimplified.Equals(""))
{
gs = new GlobalSetting(); gs = new GlobalSetting();
} else { }
else
{
gs = PTMagicConfiguration.AnalyzerSettings.GlobalSettings.Find(s => SystemHelper.StripBadCode(s.SettingName, Constants.WhiteListNames).Equals(originalNameSimplified)); gs = PTMagicConfiguration.AnalyzerSettings.GlobalSettings.Find(s => SystemHelper.StripBadCode(s.SettingName, Constants.WhiteListNames).Equals(originalNameSimplified));
} }
@ -91,20 +106,26 @@ namespace Monitor.Pages {
gs.TriggerConnection = HttpContext.Request.Form[gsFormKey + "TriggerConnection"]; gs.TriggerConnection = HttpContext.Request.Form[gsFormKey + "TriggerConnection"];
// Triggers // Triggers
if (!gs.SettingName.Equals("Default", StringComparison.InvariantCultureIgnoreCase)) { if (!gs.SettingName.Equals("Default", StringComparison.InvariantCultureIgnoreCase))
{
List<Trigger> newTriggers = new List<Trigger>(); List<Trigger> newTriggers = new List<Trigger>();
List<string> globalSettingTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(gsFormKey + "Trigger_") && k.EndsWith("|MarketTrendName")); List<string> globalSettingTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(gsFormKey + "Trigger_") && k.EndsWith("|MarketTrendName"));
foreach (string globalSettingTriggerFormKey in globalSettingTriggerFormKeys) { foreach (string globalSettingTriggerFormKey in globalSettingTriggerFormKeys)
{
Trigger trigger = null; Trigger trigger = null;
string originalTriggerNameSimplified = globalSettingTriggerFormKey.Replace(gsFormKey + "Trigger_", "").Replace("|MarketTrendName", ""); string originalTriggerNameSimplified = globalSettingTriggerFormKey.Replace(gsFormKey + "Trigger_", "").Replace("|MarketTrendName", "");
string tFormKey = gsFormKey + "Trigger_" + originalTriggerNameSimplified + "|"; string tFormKey = gsFormKey + "Trigger_" + originalTriggerNameSimplified + "|";
for (int f = 0; f < HttpContext.Request.Form[tFormKey + "MarketTrendName"].Count; f++) { for (int f = 0; f < HttpContext.Request.Form[tFormKey + "MarketTrendName"].Count; f++)
{
if (originalTriggerNameSimplified.Equals("")) { if (originalTriggerNameSimplified.Equals(""))
{
trigger = new Trigger(); trigger = new Trigger();
} else { }
else
{
trigger = gs.Triggers.Find(t => SystemHelper.StripBadCode(t.MarketTrendName, Constants.WhiteListNames).Equals(originalTriggerNameSimplified)); trigger = gs.Triggers.Find(t => SystemHelper.StripBadCode(t.MarketTrendName, Constants.WhiteListNames).Equals(originalTriggerNameSimplified));
} }
@ -135,18 +156,23 @@ namespace Monitor.Pages {
PTMagicConfiguration.AnalyzerSettings.GlobalSettings = newGlobalMarketSettings; PTMagicConfiguration.AnalyzerSettings.GlobalSettings = newGlobalMarketSettings;
} }
private void SaveSingleMarketSettings(List<string> formKeys) { private void SaveSingleMarketSettings(List<string> formKeys)
{
List<SingleMarketSetting> newSingleMarketMarketSettings = new List<SingleMarketSetting>(); List<SingleMarketSetting> newSingleMarketMarketSettings = new List<SingleMarketSetting>();
List<string> singleMarketSettingFormKeys = formKeys.FindAll(k => k.StartsWith("MarketAnalyzer_SingleMarketSetting_") && k.EndsWith("|SettingName")); List<string> singleMarketSettingFormKeys = formKeys.FindAll(k => k.StartsWith("MarketAnalyzer_SingleMarketSetting_") && k.EndsWith("|SettingName"));
foreach (string singleMarketSettingFormKey in singleMarketSettingFormKeys) { foreach (string singleMarketSettingFormKey in singleMarketSettingFormKeys)
{
SingleMarketSetting sms = null; SingleMarketSetting sms = null;
string originalNameSimplified = singleMarketSettingFormKey.Replace("MarketAnalyzer_SingleMarketSetting_", "").Replace("|SettingName", ""); string originalNameSimplified = singleMarketSettingFormKey.Replace("MarketAnalyzer_SingleMarketSetting_", "").Replace("|SettingName", "");
string smsFormKey = "MarketAnalyzer_SingleMarketSetting_" + originalNameSimplified + "|"; string smsFormKey = "MarketAnalyzer_SingleMarketSetting_" + originalNameSimplified + "|";
if (originalNameSimplified.Equals("")) { if (originalNameSimplified.Equals(""))
{
sms = new SingleMarketSetting(); sms = new SingleMarketSetting();
} else { }
else
{
sms = PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings.Find(s => SystemHelper.StripBadCode(s.SettingName, Constants.WhiteListNames).Equals(originalNameSimplified)); sms = PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings.Find(s => SystemHelper.StripBadCode(s.SettingName, Constants.WhiteListNames).Equals(originalNameSimplified));
} }
@ -160,16 +186,21 @@ namespace Monitor.Pages {
#region Triggers #region Triggers
List<Trigger> newTriggers = new List<Trigger>(); List<Trigger> newTriggers = new List<Trigger>();
List<string> singleMarketSettingTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "Trigger_") && k.EndsWith("|MarketTrendName")); List<string> singleMarketSettingTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "Trigger_") && k.EndsWith("|MarketTrendName"));
foreach (string singleMarketSettingTriggerFormKey in singleMarketSettingTriggerFormKeys) { foreach (string singleMarketSettingTriggerFormKey in singleMarketSettingTriggerFormKeys)
{
Trigger trigger = null; Trigger trigger = null;
string originalTriggerNameSimplified = singleMarketSettingTriggerFormKey.Replace(smsFormKey + "Trigger_", "").Replace("|MarketTrendName", ""); string originalTriggerNameSimplified = singleMarketSettingTriggerFormKey.Replace(smsFormKey + "Trigger_", "").Replace("|MarketTrendName", "");
string tFormKey = smsFormKey + "Trigger_" + originalTriggerNameSimplified + "|"; string tFormKey = smsFormKey + "Trigger_" + originalTriggerNameSimplified + "|";
for (int f = 0; f < HttpContext.Request.Form[tFormKey + "MarketTrendName"].Count; f++) { for (int f = 0; f < HttpContext.Request.Form[tFormKey + "MarketTrendName"].Count; f++)
if (originalTriggerNameSimplified.Equals("")) { {
if (originalTriggerNameSimplified.Equals(""))
{
trigger = new Trigger(); trigger = new Trigger();
} else { }
else
{
trigger = sms.Triggers.Find(t => SystemHelper.StripBadCode(t.MarketTrendName, Constants.WhiteListNames).Equals(originalTriggerNameSimplified)); trigger = sms.Triggers.Find(t => SystemHelper.StripBadCode(t.MarketTrendName, Constants.WhiteListNames).Equals(originalTriggerNameSimplified));
} }
@ -183,13 +214,15 @@ namespace Monitor.Pages {
} }
List<string> singleMarketSettingCoinAgeTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "Trigger_AgeDaysLowerThan")); List<string> singleMarketSettingCoinAgeTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "Trigger_AgeDaysLowerThan"));
foreach (string singleMarketSettingCoinAgeTriggerFormKey in singleMarketSettingCoinAgeTriggerFormKeys) { foreach (string singleMarketSettingCoinAgeTriggerFormKey in singleMarketSettingCoinAgeTriggerFormKeys)
{
Trigger trigger = null; Trigger trigger = null;
string originalTriggerIndex = singleMarketSettingCoinAgeTriggerFormKey.Replace(smsFormKey + "Trigger_AgeDaysLowerThan", ""); string originalTriggerIndex = singleMarketSettingCoinAgeTriggerFormKey.Replace(smsFormKey + "Trigger_AgeDaysLowerThan", "");
string tFormKey = smsFormKey + "Trigger_AgeDaysLowerThan" + originalTriggerIndex; string tFormKey = smsFormKey + "Trigger_AgeDaysLowerThan" + originalTriggerIndex;
for (int f = 0; f < HttpContext.Request.Form[tFormKey].Count; f++) { for (int f = 0; f < HttpContext.Request.Form[tFormKey].Count; f++)
{
trigger = new Trigger(); trigger = new Trigger();
trigger.AgeDaysLowerThan = SystemHelper.TextToInteger(HttpContext.Request.Form[tFormKey][f], 0); trigger.AgeDaysLowerThan = SystemHelper.TextToInteger(HttpContext.Request.Form[tFormKey][f], 0);
@ -199,13 +232,15 @@ namespace Monitor.Pages {
} }
List<string> singleMarketSetting24hVolumeTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "Trigger_24hVolume") && k.EndsWith("|Min24hVolume")); List<string> singleMarketSetting24hVolumeTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "Trigger_24hVolume") && k.EndsWith("|Min24hVolume"));
foreach (string singleMarketSetting24hVolumeTriggerFormKey in singleMarketSetting24hVolumeTriggerFormKeys) { foreach (string singleMarketSetting24hVolumeTriggerFormKey in singleMarketSetting24hVolumeTriggerFormKeys)
{
Trigger trigger = null; Trigger trigger = null;
string originalTriggerIndex = singleMarketSetting24hVolumeTriggerFormKey.Replace(smsFormKey + "Trigger_24hVolume", "").Replace("|Min24hVolume", ""); string originalTriggerIndex = singleMarketSetting24hVolumeTriggerFormKey.Replace(smsFormKey + "Trigger_24hVolume", "").Replace("|Min24hVolume", "");
string tFormKey = smsFormKey + "Trigger_24hVolume" + originalTriggerIndex + "|"; string tFormKey = smsFormKey + "Trigger_24hVolume" + originalTriggerIndex + "|";
for (int f = 0; f < HttpContext.Request.Form[tFormKey + "Min24hVolume"].Count; f++) { for (int f = 0; f < HttpContext.Request.Form[tFormKey + "Min24hVolume"].Count; f++)
{
trigger = new Trigger(); trigger = new Trigger();
trigger.Min24hVolume = SystemHelper.TextToDouble(HttpContext.Request.Form[tFormKey + "Min24hVolume"][f], 0, "en-US"); trigger.Min24hVolume = SystemHelper.TextToDouble(HttpContext.Request.Form[tFormKey + "Min24hVolume"][f], 0, "en-US");
@ -221,16 +256,21 @@ namespace Monitor.Pages {
#region Off Triggers #region Off Triggers
List<OffTrigger> newOffTriggers = new List<OffTrigger>(); List<OffTrigger> newOffTriggers = new List<OffTrigger>();
List<string> singleMarketSettingOffTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "OffTrigger_") && k.EndsWith("|MarketTrendName")); List<string> singleMarketSettingOffTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "OffTrigger_") && k.EndsWith("|MarketTrendName"));
foreach (string singleMarketSettingOffTriggerFormKey in singleMarketSettingOffTriggerFormKeys) { foreach (string singleMarketSettingOffTriggerFormKey in singleMarketSettingOffTriggerFormKeys)
{
OffTrigger offTrigger = null; OffTrigger offTrigger = null;
string originalOffTriggerNameSimplified = singleMarketSettingOffTriggerFormKey.Replace(smsFormKey + "OffTrigger_", "").Replace("|MarketTrendName", ""); string originalOffTriggerNameSimplified = singleMarketSettingOffTriggerFormKey.Replace(smsFormKey + "OffTrigger_", "").Replace("|MarketTrendName", "");
string tFormKey = smsFormKey + "OffTrigger_" + originalOffTriggerNameSimplified + "|"; string tFormKey = smsFormKey + "OffTrigger_" + originalOffTriggerNameSimplified + "|";
for (int f = 0; f < HttpContext.Request.Form[tFormKey + "MarketTrendName"].Count; f++) { for (int f = 0; f < HttpContext.Request.Form[tFormKey + "MarketTrendName"].Count; f++)
if (originalOffTriggerNameSimplified.Equals("")) { {
if (originalOffTriggerNameSimplified.Equals(""))
{
offTrigger = new OffTrigger(); offTrigger = new OffTrigger();
} else { }
else
{
offTrigger = sms.OffTriggers.Find(t => SystemHelper.StripBadCode(t.MarketTrendName, Constants.WhiteListNames).Equals(originalOffTriggerNameSimplified)); offTrigger = sms.OffTriggers.Find(t => SystemHelper.StripBadCode(t.MarketTrendName, Constants.WhiteListNames).Equals(originalOffTriggerNameSimplified));
} }
@ -244,13 +284,15 @@ namespace Monitor.Pages {
} }
List<string> singleMarketSettingHoursActiveOffTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "OffTrigger_HoursSinceTriggered")); List<string> singleMarketSettingHoursActiveOffTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "OffTrigger_HoursSinceTriggered"));
foreach (string singleMarketSettingHoursActiveOffTriggerFormKey in singleMarketSettingHoursActiveOffTriggerFormKeys) { foreach (string singleMarketSettingHoursActiveOffTriggerFormKey in singleMarketSettingHoursActiveOffTriggerFormKeys)
{
OffTrigger offTrigger = null; OffTrigger offTrigger = null;
string originalOffTriggerIndex = singleMarketSettingHoursActiveOffTriggerFormKey.Replace(smsFormKey + "OffTrigger_HoursSinceTriggered", ""); string originalOffTriggerIndex = singleMarketSettingHoursActiveOffTriggerFormKey.Replace(smsFormKey + "OffTrigger_HoursSinceTriggered", "");
string tFormKey = smsFormKey + "OffTrigger_HoursSinceTriggered" + originalOffTriggerIndex; string tFormKey = smsFormKey + "OffTrigger_HoursSinceTriggered" + originalOffTriggerIndex;
for (int f = 0; f < HttpContext.Request.Form[tFormKey].Count; f++) { for (int f = 0; f < HttpContext.Request.Form[tFormKey].Count; f++)
{
offTrigger = new OffTrigger(); offTrigger = new OffTrigger();
offTrigger.HoursSinceTriggered = SystemHelper.TextToInteger(HttpContext.Request.Form[tFormKey][f], 0); offTrigger.HoursSinceTriggered = SystemHelper.TextToInteger(HttpContext.Request.Form[tFormKey][f], 0);
@ -260,13 +302,15 @@ namespace Monitor.Pages {
} }
List<string> singleMarketSetting24hVolumeOffTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "OffTrigger_24hVolume") && k.EndsWith("|Min24hVolume")); List<string> singleMarketSetting24hVolumeOffTriggerFormKeys = formKeys.FindAll(k => k.StartsWith(smsFormKey + "OffTrigger_24hVolume") && k.EndsWith("|Min24hVolume"));
foreach (string singleMarketSetting24hVolumeOffTriggerFormKey in singleMarketSetting24hVolumeOffTriggerFormKeys) { foreach (string singleMarketSetting24hVolumeOffTriggerFormKey in singleMarketSetting24hVolumeOffTriggerFormKeys)
{
OffTrigger offTrigger = null; OffTrigger offTrigger = null;
string originalOffTriggerIndex = singleMarketSetting24hVolumeOffTriggerFormKey.Replace(smsFormKey + "OffTrigger_24hVolume", "").Replace("|Min24hVolume", ""); string originalOffTriggerIndex = singleMarketSetting24hVolumeOffTriggerFormKey.Replace(smsFormKey + "OffTrigger_24hVolume", "").Replace("|Min24hVolume", "");
string tFormKey = smsFormKey + "OffTrigger_24hVolume" + originalOffTriggerIndex + "|"; string tFormKey = smsFormKey + "OffTrigger_24hVolume" + originalOffTriggerIndex + "|";
for (int f = 0; f < HttpContext.Request.Form[tFormKey + "Min24hVolume"].Count; f++) { for (int f = 0; f < HttpContext.Request.Form[tFormKey + "Min24hVolume"].Count; f++)
{
offTrigger = new OffTrigger(); offTrigger = new OffTrigger();
offTrigger.Min24hVolume = SystemHelper.TextToDouble(HttpContext.Request.Form[tFormKey + "Min24hVolume"][f], 0, "en-US"); offTrigger.Min24hVolume = SystemHelper.TextToDouble(HttpContext.Request.Form[tFormKey + "Min24hVolume"][f], 0, "en-US");
@ -296,29 +340,39 @@ namespace Monitor.Pages {
PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings = newSingleMarketMarketSettings; PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings = newSingleMarketMarketSettings;
} }
private Dictionary<string, object> GetProfitTrailerProperties(List<string> formKeys, string sFormKey, string propertyType) { private Dictionary<string, object> GetProfitTrailerProperties(List<string> formKeys, string sFormKey, string propertyType)
{
Dictionary<string, object> result = new Dictionary<string, object>(); Dictionary<string, object> result = new Dictionary<string, object>();
List<string> globalSettingPairsPropertiesFormKeys = formKeys.FindAll(k => k.StartsWith(sFormKey + propertyType + "Property_") && k.IndexOf("|Value") == -1); List<string> globalSettingPairsPropertiesFormKeys = formKeys.FindAll(k => k.StartsWith(sFormKey + propertyType + "Property_") && k.IndexOf("|Value") == -1);
foreach (string globalSettingPairsFormKey in globalSettingPairsPropertiesFormKeys) { foreach (string globalSettingPairsFormKey in globalSettingPairsPropertiesFormKeys)
{
string originalKeySimplified = globalSettingPairsFormKey.Replace(sFormKey + propertyType + "Property_", ""); string originalKeySimplified = globalSettingPairsFormKey.Replace(sFormKey + propertyType + "Property_", "");
string propertyFormKey = sFormKey + propertyType + "Property_" + originalKeySimplified; string propertyFormKey = sFormKey + propertyType + "Property_" + originalKeySimplified;
for (int f = 0; f < HttpContext.Request.Form[propertyFormKey].Count; f++) { for (int f = 0; f < HttpContext.Request.Form[propertyFormKey].Count; f++)
{
string propertyKey = HttpContext.Request.Form[propertyFormKey][f] + HttpContext.Request.Form[propertyFormKey + "|ValueMode"][f]; string propertyKey = HttpContext.Request.Form[propertyFormKey][f] + HttpContext.Request.Form[propertyFormKey + "|ValueMode"][f];
string propertyValueString = HttpContext.Request.Form[propertyFormKey + "|Value"][f]; string propertyValueString = HttpContext.Request.Form[propertyFormKey + "|Value"][f];
object propertyValue = new object(); object propertyValue = new object();
if (propertyValueString.Equals("true", StringComparison.InvariantCultureIgnoreCase) | propertyValueString.Equals("false", StringComparison.InvariantCultureIgnoreCase)) { if (propertyValueString.Equals("true", StringComparison.InvariantCultureIgnoreCase) | propertyValueString.Equals("false", StringComparison.InvariantCultureIgnoreCase))
{
propertyValue = Convert.ToBoolean(propertyValueString); propertyValue = Convert.ToBoolean(propertyValueString);
} else { }
if (SystemHelper.IsDouble(propertyValueString, "en-US")) { else
{
if (SystemHelper.IsDouble(propertyValueString, "en-US"))
{
propertyValue = SystemHelper.TextToDouble(propertyValueString, 0, "en-US"); propertyValue = SystemHelper.TextToDouble(propertyValueString, 0, "en-US");
if (((double)propertyValue % 1) == 0) { if (((double)propertyValue % 1) == 0)
{
propertyValue = Convert.ToInt32(propertyValue); propertyValue = Convert.ToInt32(propertyValue);
} }
} else { }
else
{
propertyValue = propertyValueString; propertyValue = propertyValueString;
} }
} }

View File

@ -41,102 +41,116 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="card-box"> <div class="card-box">
<h4 class="m-t-0 header-title">Application</h4> <div class="panel-group" style="">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><strong><a href="#collapse1" data-toggle="collapse">APPLICATION</a></strong></h3>
</div>
<div id="collapse1" class="panel-collapse collapse">
<div class="form-group row">
<label class="col-md-4 col-form-label">Is Enabled <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Enables the PTMagic bot."></i></label>
<div class="col-md-8">
<input type="checkbox" name="Application_IsEnabled" checked="@(Model.PTMagicConfiguration.GeneralSettings.Application.IsEnabled)" data-plugin="switchery" data-color="#81c868" data-size="small" />
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Is Enabled <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Enables the PTMagic bot."></i></label> <label class="col-md-4 col-form-label">Test Mode <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If TestMode is active, no properties files will be changed"></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="checkbox" name="Application_IsEnabled" checked="@(Model.PTMagicConfiguration.GeneralSettings.Application.IsEnabled)" data-plugin="switchery" data-color="#81c868" data-size="small" /> <input type="checkbox" name="Application_TestMode" checked="@(Model.PTMagicConfiguration.GeneralSettings.Application.TestMode)" data-plugin="switchery" data-color="#81c868" data-size="small" />
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Test Mode <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If TestMode is active, no properties files will be changed"></i></label> <label class="col-md-4 col-form-label">Profit Trailer Major Version <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Major version of your Profit Trailer."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="checkbox" name="Application_TestMode" checked="@(Model.PTMagicConfiguration.GeneralSettings.Application.TestMode)" data-plugin="switchery" data-color="#81c868" data-size="small" /> @Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerMajorVersion
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Profit Trailer Major Version <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Major version of your Profit Trailer."></i></label> <label class="col-md-4 col-form-label">Profit Trailer Path <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Path to your Profit Trailer main directory."></i></label>
<div class="col-md-8"> <div class="col-md-8">
@Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerMajorVersion @Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerPath
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Profit Trailer Path <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Path to your Profit Trailer main directory."></i></label> <label class="col-md-4 col-form-label">Profit Trailer License <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Your Profit Trailer license key (needed to change your settings for PT 2.0 and above)"></i></label>
<div class="col-md-8"> <div class="col-md-8">
@Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerPath @Model.PTMagicConfiguration.GetProfitTrailerLicenseKeyMasked()
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Profit Trailer License <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Your Profit Trailer license key (needed to change your settings for PT 2.0 and above)"></i></label> <label class="col-md-4 col-form-label">Profit Trailer Monitor URL <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The URL to your profit trailer monitor (needed to change your settings for PT 2.0 and above)"></i></label>
<div class="col-md-8"> <div class="col-md-8">
@Model.PTMagicConfiguration.GetProfitTrailerLicenseKeyMasked() <a href="@Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL" target="_blank">@Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL</a>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Profit Trailer Monitor URL <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The URL to your profit trailer monitor (needed to change your settings for PT 2.0 and above)"></i></label> <label class="col-md-4 col-form-label">Profit Trailer Default Setting Name <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Your Profit Trailer default setting name (needed to change your settings for PT 2.0 and above)"></i></label>
<div class="col-md-8"> <div class="col-md-8">
<a href="@Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL" target="_blank">@Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL</a> @Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Profit Trailer Default Setting Name <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Your Profit Trailer default setting name (needed to change your settings for PT 2.0 and above)"></i></label> <label class="col-md-4 col-form-label">Exchange <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The exchange your are running Profit Trailer on."></i></label>
<div class="col-md-8"> <div class="col-md-8">
@Model.PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName <select name="Application_Exchange" class="form-control">
</div> <option selected="@(Model.PTMagicConfiguration.GeneralSettings.Application.Exchange.Equals("Binance", StringComparison.InvariantCultureIgnoreCase))">Binance</option>
</div> <option selected="@(Model.PTMagicConfiguration.GeneralSettings.Application.Exchange.Equals("Bittrex", StringComparison.InvariantCultureIgnoreCase))">Bittrex</option>
<option selected="@(Model.PTMagicConfiguration.GeneralSettings.Application.Exchange.Equals("Poloniex", StringComparison.InvariantCultureIgnoreCase))">Poloniex</option>
</select>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Exchange <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The exchange your are running Profit Trailer on."></i></label> <label class="col-md-4 col-form-label">Start Balance <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The balance you had in your wallet when you started working with Profit Trailer."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<select name="Application_Exchange" class="form-control"> <input type="text" class="form-control" name="Application_StartBalance" value="@Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance.ToString(new System.Globalization.CultureInfo("en-US"))">
<option selected="@(Model.PTMagicConfiguration.GeneralSettings.Application.Exchange.Equals("Binance", StringComparison.InvariantCultureIgnoreCase))">Binance</option> </div>
<option selected="@(Model.PTMagicConfiguration.GeneralSettings.Application.Exchange.Equals("Bittrex", StringComparison.InvariantCultureIgnoreCase))">Bittrex</option> </div>
<option selected="@(Model.PTMagicConfiguration.GeneralSettings.Application.Exchange.Equals("Poloniex", StringComparison.InvariantCultureIgnoreCase))">Poloniex</option>
</select>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Start Balance <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The balance you had in your wallet when you started working with Profit Trailer."></i></label> <label class="col-md-4 col-form-label">Timezone Offset <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Your timezone offset from GMT."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Application_StartBalance" value="@Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance.ToString(new System.Globalization.CultureInfo("en-US"))"> <select name="Application_TimezoneOffset" class="form-control">
</div> @Html.Raw(Model.GetTimezoneSelection())
</div> </select>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Timezone Offset <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Your timezone offset from GMT."></i></label> <label class="col-md-4 col-form-label">Always Load Default Before Switch <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If this is enabled, PTMagic will always load default settings before switching to another setting."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<select name="Application_TimezoneOffset" class="form-control"> <input type="checkbox" name="Application_AlwaysLoadDefaultBeforeSwitch" checked="@(Model.PTMagicConfiguration.GeneralSettings.Application.AlwaysLoadDefaultBeforeSwitch)" data-plugin="switchery" data-color="#81c868" data-size="small" />
@Html.Raw(Model.GetTimezoneSelection()) </div>
</select> </div>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Always Load Default Before Switch <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If this is enabled, PTMagic will always load default settings before switching to another setting."></i></label> <label class="col-md-4 col-form-label">Flood Protection Minutes <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If a price trend is just zig-zagging around its trigger, you may want to protect your settings from getting switched back and forth every minute."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="checkbox" name="Application_AlwaysLoadDefaultBeforeSwitch" checked="@(Model.PTMagicConfiguration.GeneralSettings.Application.AlwaysLoadDefaultBeforeSwitch)" data-plugin="switchery" data-color="#81c868" data-size="small" /> <input type="text" class="form-control" name="Application_FloodProtectionMinutes" value="@Model.PTMagicConfiguration.GeneralSettings.Application.FloodProtectionMinutes.ToString()">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Flood Protection Minutes <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If a price trend is just zig-zagging around its trigger, you may want to protect your settings from getting switched back and forth every minute."></i></label> <label class="col-md-4 col-form-label">Instance Name <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The name of the instance of this bot. This will be used in your monitor and your Telegram messages. In case you are running more than one bot, you may set different names to separate them."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Application_FloodProtectionMinutes" value="@Model.PTMagicConfiguration.GeneralSettings.Application.FloodProtectionMinutes.ToString()"> <input type="text" class="form-control" name="Application_InstanceName" value="@Model.PTMagicConfiguration.GeneralSettings.Application.InstanceName">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Instance Name <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The name of the instance of this bot. This will be used in your monitor and your Telegram messages. In case you are running more than one bot, you may set different names to separate them."></i></label> <label class="col-md-4 col-form-label">CoinMarketCap API Key <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The API Key that will be used to get Coin Data from CoinMarketCap."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Application_InstanceName" value="@Model.PTMagicConfiguration.GeneralSettings.Application.InstanceName"> <input type="text" class="form-control" name="Application_CoinMarketCapAPIKey" value="@Model.PTMagicConfiguration.GeneralSettings.Application.CoinMarketCapAPIKey">
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -146,130 +160,137 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="card-box"> <div class="card-box">
<h4 class="m-t-0 header-title">Monitor</h4> <div class="panel-group" style="">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><strong><a href="#collapse2" data-toggle="collapse">MONITOR</a></strong></h3>
</div>
<div id="collapse2" class="panel-collapse collapse">
<div class="form-group row">
<label class="col-md-4 col-form-label">Is Password Protected <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Defines if your monitor will be asking to setup a password on its first start."></i></label>
<div class="col-md-8">
<input type="checkbox" name="Monitor_IsPasswordProtected" checked="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.IsPasswordProtected)" data-plugin="switchery" data-color="#81c868" data-size="small" />
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Is Password Protected <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Defines if your monitor will be asking to setup a password on its first start."></i></label> <label class="col-md-4 col-form-label">Open Browser On Start <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If active, a browser window will open as soon as you start the monitor."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="checkbox" name="Monitor_IsPasswordProtected" checked="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.IsPasswordProtected)" data-plugin="switchery" data-color="#81c868" data-size="small" /> <input type="checkbox" name="Monitor_OpenBrowserOnStart" checked="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.OpenBrowserOnStart)" data-plugin="switchery" data-color="#81c868" data-size="small" />
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Open Browser On Start <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If active, a browser window will open as soon as you start the monitor."></i></label> <label class="col-md-4 col-form-label">Port <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The port you want to run your monitor on"></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="checkbox" name="Monitor_OpenBrowserOnStart" checked="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.OpenBrowserOnStart)" data-plugin="switchery" data-color="#81c868" data-size="small" /> @Model.PTMagicConfiguration.GeneralSettings.Monitor.Port
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Port <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The port you want to run your monitor on"></i></label> <label class="col-md-4 col-form-label">RootUrl <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The root URL of your monitor website"></i></label>
<div class="col-md-8"> <div class="col-md-8">
@Model.PTMagicConfiguration.GeneralSettings.Monitor.Port @Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">RootUrl <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The root URL of your monitor website"></i></label> <label class="col-md-4 col-form-label">Graph Interval Minutes <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The interval for the monitor market trend graph to draw points."></i></label>
<div class="col-md-8"> <div class="col-md-8">
@Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl <input type="text" class="form-control" name="Monitor_GraphIntervalMinutes" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Graph Interval Minutes <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The interval for the monitor market trend graph to draw points."></i></label> <label class="col-md-4 col-form-label">Graph Max Timeframe Hours <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This defines the timeframe that your graph for market trends covers."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_GraphIntervalMinutes" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes.ToString(new System.Globalization.CultureInfo("en-US"))"> <input type="text" class="form-control" name="Monitor_GraphMaxTimeframeHours" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Graph Max Timeframe Hours <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This defines the timeframe that your graph for market trends covers."></i></label> <label class="col-md-4 col-form-label">Refresh Seconds <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval of your monitor main page."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_GraphMaxTimeframeHours" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours.ToString(new System.Globalization.CultureInfo("en-US"))"> <input type="text" class="form-control" name="Monitor_RefreshSeconds" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Refresh Seconds <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval of your monitor main page."></i></label> <label class="col-md-4 col-form-label">Bag AnalyzerRefresh Seconds <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval of your monitor bag analyzer page."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_RefreshSeconds" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds.ToString(new System.Globalization.CultureInfo("en-US"))"> <input type="text" class="form-control" name="Monitor_BagAnalyzerRefreshSeconds" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.BagAnalyzerRefreshSeconds.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Bag AnalyzerRefresh Seconds <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval of your monitor bag analyzer page."></i></label> <label class="col-md-4 col-form-label">Buy AnalyzerRefresh Seconds <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval of your monitor buy analyzer page."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_BagAnalyzerRefreshSeconds" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.BagAnalyzerRefreshSeconds.ToString(new System.Globalization.CultureInfo("en-US"))"> <input type="text" class="form-control" name="Monitor_BuyAnalyzerRefreshSeconds" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.BuyAnalyzerRefreshSeconds.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Buy AnalyzerRefresh Seconds <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval of your monitor buy analyzer page."></i></label> <label class="col-md-4 col-form-label">Link Platform <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The platform to which the pair name will link if you click on it."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_BuyAnalyzerRefreshSeconds" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.BuyAnalyzerRefreshSeconds.ToString(new System.Globalization.CultureInfo("en-US"))"> <select name="Monitor_LinkPlatform" class="form-control">
</div> <option selected="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform.Equals("TradingView", StringComparison.InvariantCultureIgnoreCase))">TradingView</option>
</div> <option selected="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform.Equals("Exchange", StringComparison.InvariantCultureIgnoreCase))">Exchange</option>
</select>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Link Platform <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The platform to which the pair name will link if you click on it."></i></label> <label class="col-md-4 col-form-label">Max Top Markets <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of top markets being show in your Sales Analyzer."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<select name="Monitor_LinkPlatform" class="form-control"> <input type="text" class="form-control" name="Monitor_MaxTopMarkets" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxTopMarkets.ToString(new System.Globalization.CultureInfo("en-US"))">
<option selected="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform.Equals("TradingView", StringComparison.InvariantCultureIgnoreCase))">TradingView</option> </div>
<option selected="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform.Equals("Exchange", StringComparison.InvariantCultureIgnoreCase))">Exchange</option> </div>
</select>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Max Top Markets <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of top markets being show in your Sales Analyzer."></i></label> <label class="col-md-4 col-form-label">Max Daily Summaries <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of Last Days being shown in your Sales Analyzer."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_MaxTopMarkets" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxTopMarkets.ToString(new System.Globalization.CultureInfo("en-US"))"> <input type="text" class="form-control" name="Monitor_MaxDailySummaries" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDailySummaries.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Max Daily Summaries <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of Last Days being shown in your Sales Analyzer."></i></label> <label class="col-md-4 col-form-label">Max Monthly Summaries <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of Last Months being shown in your Sales Analyzer."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_MaxDailySummaries" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDailySummaries.ToString(new System.Globalization.CultureInfo("en-US"))"> <input type="text" class="form-control" name="Monitor_MaxMonthlySummaries" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxMonthlySummaries.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Max Monthly Summaries <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of Last Months being shown in your Sales Analyzer."></i></label> <label class="col-md-4 col-form-label">Max Dashboard Buy Entries <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of entries being shown in your dashboard for possible buys."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_MaxMonthlySummaries" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxMonthlySummaries.ToString(new System.Globalization.CultureInfo("en-US"))"> <input type="text" class="form-control" name="Monitor_MaxDashboardBuyEntries" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDashboardBuyEntries.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Max Dashboard Buy Entries <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of entries being shown in your dashboard for possible buys."></i></label> <label class="col-md-4 col-form-label">Max Dashboard Bag Entries <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of top markets being shown in your dashboard for pairs and dca."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_MaxDashboardBuyEntries" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDashboardBuyEntries.ToString(new System.Globalization.CultureInfo("en-US"))"> <input type="text" class="form-control" name="Monitor_MaxDashboardBagEntries" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDashboardBagEntries.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Max Dashboard Bag Entries <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of top markets being shown in your dashboard for pairs and dca."></i></label> <label class="col-md-4 col-form-label">Max DCA Pairs <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The number of pairs (rows) to be shown in your DCA calculator."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_MaxDashboardBagEntries" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDashboardBagEntries.ToString(new System.Globalization.CultureInfo("en-US"))"> <input type="text" class="form-control" name="Monitor_MaxDCAPairs" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDCAPairs.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Max DCA Pairs <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The number of pairs (rows) to be shown in your DCA calculator."></i></label> <label class="col-md-4 col-form-label">Default DCA Mode <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Set the default mode of your DCA calculator.."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Monitor_MaxDCAPairs" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDCAPairs.ToString(new System.Globalization.CultureInfo("en-US"))"> <select name="Monitor_DefaultDCAMode" class="form-control">
</div> <option selected="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.DefaultDCAMode.Equals("Simple", StringComparison.InvariantCultureIgnoreCase))">Simple</option>
</div> <option selected="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.DefaultDCAMode.Equals("Advanced", StringComparison.InvariantCultureIgnoreCase))">Advanced</option>
</select>
<div class="form-group row"> </div>
<label class="col-md-4 col-form-label">Default DCA Mode <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Set the default mode of your DCA calculator.."></i></label> </div>
<div class="col-md-8"> </div>
<select name="Monitor_DefaultDCAMode" class="form-control">
<option selected="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.DefaultDCAMode.Equals("Simple", StringComparison.InvariantCultureIgnoreCase))">Simple</option>
<option selected="@(Model.PTMagicConfiguration.GeneralSettings.Monitor.DefaultDCAMode.Equals("Advanced", StringComparison.InvariantCultureIgnoreCase))">Advanced</option>
</select>
</div> </div>
</div> </div>
</div> </div>
@ -279,19 +300,26 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="card-box"> <div class="card-box">
<h4 class="m-t-0 header-title">Backup</h4> <div class="panel-group" style="">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><strong><a href="#collapse3" data-toggle="collapse">BACKUP</a></strong></h3>
</div>
<div id="collapse3" class="panel-collapse collapse">
<div class="form-group row">
<label class="col-md-4 col-form-label">Is Enabled <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Enables a backup procedure for your properties files. Before every switch PTMagic will backup the current properties."></i></label>
<div class="col-md-8">
<input type="checkbox" name="Backup_IsEnabled" checked="@(Model.PTMagicConfiguration.GeneralSettings.Backup.IsEnabled)" data-plugin="switchery" data-color="#81c868" data-size="small" />
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Is Enabled <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Enables a backup procedure for your properties files. Before every switch PTMagic will backup the current properties."></i></label> <label class="col-md-4 col-form-label">Max Hours <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Max number of hours to keep backup files."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="checkbox" name="Backup_IsEnabled" checked="@(Model.PTMagicConfiguration.GeneralSettings.Backup.IsEnabled)" data-plugin="switchery" data-color="#81c868" data-size="small" /> <input type="text" class="form-control" name="Backup_MaxHours" value="@Model.PTMagicConfiguration.GeneralSettings.Backup.MaxHours.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Max Hours <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Max number of hours to keep backup files."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Backup_MaxHours" value="@Model.PTMagicConfiguration.GeneralSettings.Backup.MaxHours.ToString(new System.Globalization.CultureInfo("en-US"))">
</div> </div>
</div> </div>
</div> </div>
@ -301,42 +329,49 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="card-box"> <div class="card-box">
<h4 class="m-t-0 header-title">Telegram</h4> <div class="panel-group" style="">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><strong><a href="#collapse4" data-toggle="collapse">TELEGRAM</a></strong></h3>
</div>
<div id="collapse4" class="panel-collapse collapse">
<div class="form-group row">
<label class="col-md-4 col-form-label">Is Enabled <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Enables PT Magic to send Telegram messages."></i></label>
<div class="col-md-8">
<input type="checkbox" name="Telegram_IsEnabled" checked="@(Model.PTMagicConfiguration.GeneralSettings.Telegram.IsEnabled)" data-plugin="switchery" data-color="#81c868" data-size="small" />
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Is Enabled <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Enables PT Magic to send Telegram messages."></i></label> <label class="col-md-4 col-form-label">Bot Token <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Your Telegram bot token."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="checkbox" name="Telegram_IsEnabled" checked="@(Model.PTMagicConfiguration.GeneralSettings.Telegram.IsEnabled)" data-plugin="switchery" data-color="#81c868" data-size="small" /> <input type="text" class="form-control" name="Telegram_BotToken" id="Telegram_BotToken" value="@Model.PTMagicConfiguration.GeneralSettings.Telegram.BotToken">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Bot Token <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Your Telegram bot token."></i></label> <label class="col-md-4 col-form-label">Chat Id <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Your Telegram Chat ID."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Telegram_BotToken" id="Telegram_BotToken" value="@Model.PTMagicConfiguration.GeneralSettings.Telegram.BotToken"> <input type="text" class="form-control" name="Telegram_ChatId" id="Telegram_ChatId" value="@Model.PTMagicConfiguration.GeneralSettings.Telegram.ChatId">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Chat Id <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="Your Telegram Chat ID."></i></label> <label class="col-md-4 col-form-label">Silent Mode <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If SilentMode is active, no notification sound or vibration will happen when the bot sends a Telegram message."></i></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" name="Telegram_ChatId" id="Telegram_ChatId" value="@Model.PTMagicConfiguration.GeneralSettings.Telegram.ChatId"> <input type="checkbox" name="Telegram_SilentMode" id="Telegram_SilentMode" checked="@(Model.PTMagicConfiguration.GeneralSettings.Telegram.SilentMode)" data-plugin="switchery" data-color="#81c868" data-size="small" />
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-md-4 col-form-label">Silent Mode <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If SilentMode is active, no notification sound or vibration will happen when the bot sends a Telegram message."></i></label> <label class="col-md-4 col-form-label"></label>
<div class="col-md-8"> <div class="col-md-8">
<input type="checkbox" name="Telegram_SilentMode" id="Telegram_SilentMode" checked="@(Model.PTMagicConfiguration.GeneralSettings.Telegram.SilentMode)" data-plugin="switchery" data-color="#81c868" data-size="small" /> <button id="btn-test-telegram" class="btn btn-ptmagic btn-block text-uppercase waves-effect waves-light">
</div> Send Telegram Test Message
</div> </button>
</div>
<div class="form-group row"> </div>
<label class="col-md-4 col-form-label"></label> </div>
<div class="col-md-8">
<button id="btn-test-telegram" class="btn btn-ptmagic btn-block text-uppercase waves-effect waves-light">
Send Telegram Test Message
</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,11 +6,14 @@ using Core.Main;
using Core.Helper; using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
namespace Monitor.Pages { namespace Monitor.Pages
public class SettingsGeneralModel : _Internal.BasePageModelSecure { {
public class SettingsGeneralModel : _Internal.BasePageModelSecure
{
public string ValidationMessage = ""; public string ValidationMessage = "";
private string GetTimezoneOffsetString(TimeZoneInfo tzi) { private string GetTimezoneOffsetString(TimeZoneInfo tzi)
{
string result = ""; string result = "";
result += (tzi.BaseUtcOffset >= TimeSpan.Zero) ? "+" : "-"; result += (tzi.BaseUtcOffset >= TimeSpan.Zero) ? "+" : "-";
@ -21,15 +24,19 @@ namespace Monitor.Pages {
return result; return result;
} }
public string GetTimezoneSelection() { public string GetTimezoneSelection()
{
string result = ""; string result = "";
List<string> tzOffsetList = new List<string>(); List<string> tzOffsetList = new List<string>();
foreach (TimeZoneInfo tzi in TimeZoneInfo.GetSystemTimeZones()) { foreach (TimeZoneInfo tzi in TimeZoneInfo.GetSystemTimeZones())
{
string offsetString = this.GetTimezoneOffsetString(tzi); string offsetString = this.GetTimezoneOffsetString(tzi);
if (!tzOffsetList.Contains(offsetString)) { if (!tzOffsetList.Contains(offsetString))
{
string selected = ""; string selected = "";
if (PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Equals(offsetString, StringComparison.InvariantCultureIgnoreCase)) { if (PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Equals(offsetString, StringComparison.InvariantCultureIgnoreCase))
{
selected = " selected=\"selected\""; selected = " selected=\"selected\"";
} }
@ -41,18 +48,21 @@ namespace Monitor.Pages {
return result; return result;
} }
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
string notification = GetStringParameter("n", ""); string notification = GetStringParameter("n", "");
if (notification.Equals("BackupRestored")) { if (notification.Equals("BackupRestored"))
{
NotifyHeadline = "Backup restored!"; NotifyHeadline = "Backup restored!";
NotifyMessage = "Your backup of settings.general.json was successfully restored."; NotifyMessage = "Your backup of settings.general.json was successfully restored.";
NotifyType = "success"; NotifyType = "success";
} }
} }
public void OnPost() { public void OnPost()
{
base.Init(); base.Init();
PTMagicConfiguration.GeneralSettings.Application.IsEnabled = HttpContext.Request.Form["Application_IsEnabled"].Equals("on"); PTMagicConfiguration.GeneralSettings.Application.IsEnabled = HttpContext.Request.Form["Application_IsEnabled"].Equals("on");
@ -63,6 +73,7 @@ namespace Monitor.Pages {
PTMagicConfiguration.GeneralSettings.Application.AlwaysLoadDefaultBeforeSwitch = HttpContext.Request.Form["Application_AlwaysLoadDefaultBeforeSwitch"].Equals("on"); PTMagicConfiguration.GeneralSettings.Application.AlwaysLoadDefaultBeforeSwitch = HttpContext.Request.Form["Application_AlwaysLoadDefaultBeforeSwitch"].Equals("on");
PTMagicConfiguration.GeneralSettings.Application.FloodProtectionMinutes = SystemHelper.TextToInteger(HttpContext.Request.Form["Application_FloodProtectionMinutes"], PTMagicConfiguration.GeneralSettings.Application.FloodProtectionMinutes); 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.InstanceName = HttpContext.Request.Form["Application_InstanceName"];
PTMagicConfiguration.GeneralSettings.Application.CoinMarketCapAPIKey = HttpContext.Request.Form["Application_CoinMarketCapAPIKey"];
PTMagicConfiguration.GeneralSettings.Monitor.IsPasswordProtected = HttpContext.Request.Form["Monitor_IsPasswordProtected"].Equals("on"); 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.OpenBrowserOnStart = HttpContext.Request.Form["Monitor_OpenBrowserOnStart"].Equals("on");

View File

@ -5,20 +5,26 @@ using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using Core.Main; using Core.Main;
namespace Monitor.Pages { namespace Monitor.Pages
public class SetupPasswordModel : _Internal.BasePageModel { {
public class SetupPasswordModel : _Internal.BasePageModel
{
public string ValidationMessage = ""; public string ValidationMessage = "";
public void OnGet() { public void OnGet()
{
base.PreInit(); base.PreInit();
} }
public void OnPost(string password, string passwordConfirm) { public void OnPost(string password, string passwordConfirm)
if (!password.Equals(passwordConfirm)) { {
if (!password.Equals(passwordConfirm))
{
ValidationMessage = "Password does not match the confirmation!"; ValidationMessage = "Password does not match the confirmation!";
} }
if (ModelState.IsValid) { if (ModelState.IsValid)
{
base.PreInit(); base.PreInit();
PTMagicConfiguration.WriteSecureSettings(password, PTMagicBasePath); PTMagicConfiguration.WriteSecureSettings(password, PTMagicBasePath);

View File

@ -6,31 +6,39 @@ using Core.Main;
using Core.Helper; using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
namespace Monitor.Pages { namespace Monitor.Pages
public class StatusSummaryModel : _Internal.BasePageModelSecure { {
public class StatusSummaryModel : _Internal.BasePageModelSecure
{
public List<string> MarketsWithSingleSettings = new List<string>(); public List<string> MarketsWithSingleSettings = new List<string>();
public string SettingsDistribution24hChartDataJSON = ""; public string SettingsDistribution24hChartDataJSON = "";
public string SettingsDistribution3dChartDataJSON = ""; public string SettingsDistribution3dChartDataJSON = "";
private Dictionary<string, string> settingsChartColors = new Dictionary<string, string>(); private Dictionary<string, string> settingsChartColors = new Dictionary<string, string>();
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
BindData(); BindData();
} }
private void BindData() { private void BindData()
{
BuildMarketsWithSingleSettings(); BuildMarketsWithSingleSettings();
BuildChartColors(); BuildChartColors();
Build24hChartData(); Build24hChartData();
Build3dChartData(); Build3dChartData();
} }
private void BuildMarketsWithSingleSettings() { private void BuildMarketsWithSingleSettings()
{
// Get markets with active single settings // Get markets with active single settings
foreach (string key in Summary.MarketSummary.Keys) { foreach (string key in Summary.MarketSummary.Keys)
if (Summary.MarketSummary[key].ActiveSingleSettings != null) { {
if (Summary.MarketSummary[key].ActiveSingleSettings.Count > 0) { if (Summary.MarketSummary[key].ActiveSingleSettings != null)
{
if (Summary.MarketSummary[key].ActiveSingleSettings.Count > 0)
{
MarketsWithSingleSettings.Add(key); MarketsWithSingleSettings.Add(key);
} }
} }
@ -38,13 +46,18 @@ namespace Monitor.Pages {
MarketsWithSingleSettings.Sort(); MarketsWithSingleSettings.Sort();
} }
private void BuildChartColors() { private void BuildChartColors()
{
int settingIndex = 0; int settingIndex = 0;
foreach (GlobalSetting globalSetting in PTMagicConfiguration.AnalyzerSettings.GlobalSettings) { foreach (GlobalSetting globalSetting in PTMagicConfiguration.AnalyzerSettings.GlobalSettings)
{
string chartColor = ""; string chartColor = "";
if (settingIndex < Constants.ChartLineColors.Length) { if (settingIndex < Constants.ChartLineColors.Length)
{
chartColor = Constants.ChartLineColors[settingIndex]; chartColor = Constants.ChartLineColors[settingIndex];
} else { }
else
{
chartColor = Constants.ChartLineColors[settingIndex - 20]; chartColor = Constants.ChartLineColors[settingIndex - 20];
} }
@ -54,40 +67,54 @@ namespace Monitor.Pages {
} }
} }
private void Build24hChartData() { private void Build24hChartData()
if (Summary.GlobalSettingSummary.Count > 0) { {
if (Summary.GlobalSettingSummary.Count > 0)
{
DateTime dateTime24hAgo = DateTime.Now.AddHours(-24); DateTime dateTime24hAgo = DateTime.Now.AddHours(-24);
List<GlobalSettingSummary> gsSummaries24h = Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime >= dateTime24hAgo); List<GlobalSettingSummary> gsSummaries24h = Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime >= dateTime24hAgo);
IEnumerable<GlobalSettingSummary> gsNames24h = gsSummaries24h.GroupBy(gss => gss.SettingName).Select(group => group.First()); IEnumerable<GlobalSettingSummary> gsNames24h = gsSummaries24h.GroupBy(gss => gss.SettingName).Select(group => group.First());
if (Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime <= dateTime24hAgo).Count > 0) { if (Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime <= dateTime24hAgo).Count > 0)
{
GlobalSettingSummary gsBefore24h = Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime <= dateTime24hAgo).OrderByDescending(gss => gss.SwitchDateTime).First(); GlobalSettingSummary gsBefore24h = Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime <= dateTime24hAgo).OrderByDescending(gss => gss.SwitchDateTime).First();
if (gsBefore24h != null) { if (gsBefore24h != null)
{
DateTime gsSwitchedOffDateTime = gsBefore24h.SwitchDateTime.AddSeconds(gsBefore24h.ActiveSeconds); DateTime gsSwitchedOffDateTime = gsBefore24h.SwitchDateTime.AddSeconds(gsBefore24h.ActiveSeconds);
if (gsSwitchedOffDateTime > dateTime24hAgo) { if (gsSwitchedOffDateTime > dateTime24hAgo)
{
gsBefore24h.ActiveSeconds = (int)Math.Floor(gsSwitchedOffDateTime.Subtract(dateTime24hAgo).TotalSeconds); gsBefore24h.ActiveSeconds = (int)Math.Floor(gsSwitchedOffDateTime.Subtract(dateTime24hAgo).TotalSeconds);
gsSummaries24h.Add(gsBefore24h); gsSummaries24h.Add(gsBefore24h);
if (gsNames24h.Select(gss => gss.SettingName.Equals(gsBefore24h.SettingName)) == null) { if (gsNames24h.Select(gss => gss.SettingName.Equals(gsBefore24h.SettingName)) == null)
{
gsNames24h.Append(gsBefore24h); gsNames24h.Append(gsBefore24h);
} }
} }
} }
} }
if (gsNames24h.Count() > 0) { if (gsNames24h.Count() > 0)
{
SettingsDistribution24hChartDataJSON = "["; SettingsDistribution24hChartDataJSON = "[";
int gssIndex = 0; int gssIndex = 0;
double totalCoveredSeconds = gsSummaries24h.Sum(gs => gs.ActiveSeconds); double totalCoveredSeconds = gsSummaries24h.Sum(gs => gs.ActiveSeconds);
foreach (GlobalSettingSummary gss in gsNames24h) { foreach (GlobalSettingSummary gss in gsNames24h)
{
string lineColor = ""; string lineColor = "";
if (settingsChartColors.ContainsKey(gss.SettingName)) { if (settingsChartColors.ContainsKey(gss.SettingName))
{
lineColor = settingsChartColors[gss.SettingName]; lineColor = settingsChartColors[gss.SettingName];
} else { }
if (gssIndex < Constants.ChartLineColors.Length) { else
{
if (gssIndex < Constants.ChartLineColors.Length)
{
lineColor = Constants.ChartLineColors[gssIndex]; lineColor = Constants.ChartLineColors[gssIndex];
} else { }
else
{
lineColor = Constants.ChartLineColors[gssIndex - 20]; lineColor = Constants.ChartLineColors[gssIndex - 20];
} }
} }
@ -110,40 +137,54 @@ namespace Monitor.Pages {
} }
} }
private void Build3dChartData() { private void Build3dChartData()
if (Summary.GlobalSettingSummary.Count > 0) { {
if (Summary.GlobalSettingSummary.Count > 0)
{
DateTime dateTime3dAgo = DateTime.Now.AddHours(-72); DateTime dateTime3dAgo = DateTime.Now.AddHours(-72);
List<GlobalSettingSummary> gsSummaries3d = Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime >= dateTime3dAgo); List<GlobalSettingSummary> gsSummaries3d = Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime >= dateTime3dAgo);
IEnumerable<GlobalSettingSummary> gsNames3d = gsSummaries3d.GroupBy(gss => gss.SettingName).Select(group => group.First()); IEnumerable<GlobalSettingSummary> gsNames3d = gsSummaries3d.GroupBy(gss => gss.SettingName).Select(group => group.First());
if (Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime <= dateTime3dAgo).Count > 0) { if (Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime <= dateTime3dAgo).Count > 0)
{
GlobalSettingSummary gsBefore3d = Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime <= dateTime3dAgo).OrderByDescending(gss => gss.SwitchDateTime).First(); GlobalSettingSummary gsBefore3d = Summary.GlobalSettingSummary.FindAll(gss => gss.SwitchDateTime <= dateTime3dAgo).OrderByDescending(gss => gss.SwitchDateTime).First();
if (gsBefore3d != null) { if (gsBefore3d != null)
{
DateTime gsSwitchedOffDateTime = gsBefore3d.SwitchDateTime.AddSeconds(gsBefore3d.ActiveSeconds); DateTime gsSwitchedOffDateTime = gsBefore3d.SwitchDateTime.AddSeconds(gsBefore3d.ActiveSeconds);
if (gsSwitchedOffDateTime > dateTime3dAgo) { if (gsSwitchedOffDateTime > dateTime3dAgo)
{
gsBefore3d.ActiveSeconds = (int)Math.Floor(gsSwitchedOffDateTime.Subtract(dateTime3dAgo).TotalSeconds); gsBefore3d.ActiveSeconds = (int)Math.Floor(gsSwitchedOffDateTime.Subtract(dateTime3dAgo).TotalSeconds);
gsSummaries3d.Add(gsBefore3d); gsSummaries3d.Add(gsBefore3d);
if (gsNames3d.Select(gss => gss.SettingName.Equals(gsBefore3d.SettingName)) == null) { if (gsNames3d.Select(gss => gss.SettingName.Equals(gsBefore3d.SettingName)) == null)
{
gsNames3d.Append(gsBefore3d); gsNames3d.Append(gsBefore3d);
} }
} }
} }
} }
if (gsNames3d.Count() > 0) { if (gsNames3d.Count() > 0)
{
SettingsDistribution3dChartDataJSON = "["; SettingsDistribution3dChartDataJSON = "[";
int gssIndex = 0; int gssIndex = 0;
double totalCoveredSeconds = gsSummaries3d.Sum(gs => gs.ActiveSeconds); double totalCoveredSeconds = gsSummaries3d.Sum(gs => gs.ActiveSeconds);
foreach (GlobalSettingSummary gss in gsNames3d) { foreach (GlobalSettingSummary gss in gsNames3d)
{
string lineColor = ""; string lineColor = "";
if (settingsChartColors.ContainsKey(gss.SettingName)) { if (settingsChartColors.ContainsKey(gss.SettingName))
{
lineColor = settingsChartColors[gss.SettingName]; lineColor = settingsChartColors[gss.SettingName];
} else { }
if (gssIndex < Constants.ChartLineColors.Length) { else
{
if (gssIndex < Constants.ChartLineColors.Length)
{
lineColor = Constants.ChartLineColors[gssIndex]; lineColor = Constants.ChartLineColors[gssIndex];
} else { }
else
{
lineColor = Constants.ChartLineColors[gssIndex - 20]; lineColor = Constants.ChartLineColors[gssIndex - 20];
} }
} }

View File

@ -8,22 +8,27 @@ using Core.Main.DataObjects;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using System.Globalization; using System.Globalization;
namespace Monitor.Pages { namespace Monitor.Pages
public class TransactionsModel : _Internal.BasePageModelSecure { {
public class TransactionsModel : _Internal.BasePageModelSecure
{
public TransactionData TransactionData = null; public TransactionData TransactionData = null;
public string ValidationMessage = ""; public string ValidationMessage = "";
public void OnGet() { public void OnGet()
{
base.Init(); base.Init();
BindData(); BindData();
} }
private void BindData() { private void BindData()
{
TransactionData = new TransactionData(PTMagicBasePath); TransactionData = new TransactionData(PTMagicBasePath);
} }
public void OnPost() { public void OnPost()
{
base.Init(); base.Init();
BindData(); BindData();
@ -31,11 +36,13 @@ namespace Monitor.Pages {
SaveTransaction(); SaveTransaction();
} }
private void SaveTransaction() { private void SaveTransaction()
{
double transactionAmount = 0; double transactionAmount = 0;
DateTimeOffset transactionDateTime = Constants.confMinDate; DateTimeOffset transactionDateTime = Constants.confMinDate;
try { try
{
transactionAmount = SystemHelper.TextToDouble(HttpContext.Request.Form["Transaction_Amount"], transactionAmount, "en-US"); transactionAmount = SystemHelper.TextToDouble(HttpContext.Request.Form["Transaction_Amount"], transactionAmount, "en-US");
//transactionDateTime = DateTimeOffset.Parse(HttpContext.Request.Form["Transaction_Date"] + " " + HttpContext.Request.Form["Transaction_Time"], CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); //transactionDateTime = DateTimeOffset.Parse(HttpContext.Request.Form["Transaction_Date"] + " " + HttpContext.Request.Form["Transaction_Time"], CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
DateTime tmp = DateTime.Parse(HttpContext.Request.Form["Transaction_Date"] + " " + HttpContext.Request.Form["Transaction_Time"], CultureInfo.InvariantCulture, DateTimeStyles.None); DateTime tmp = DateTime.Parse(HttpContext.Request.Form["Transaction_Date"] + " " + HttpContext.Request.Form["Transaction_Time"], CultureInfo.InvariantCulture, DateTimeStyles.None);
@ -43,14 +50,21 @@ namespace Monitor.Pages {
// Convert local offset time to UTC // Convert local offset time to UTC
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", "")); TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
transactionDateTime = new DateTimeOffset(tmp, offsetTimeSpan); transactionDateTime = new DateTimeOffset(tmp, offsetTimeSpan);
} catch { } }
catch { }
if (transactionAmount == 0) { if (transactionAmount == 0)
{
ValidationMessage = "Please enter a valid amount in the format 123.45!"; ValidationMessage = "Please enter a valid amount in the format 123.45!";
} else { }
if (transactionDateTime == Constants.confMinDate) { else
{
if (transactionDateTime == Constants.confMinDate)
{
ValidationMessage = "Please select a valid date and time!"; ValidationMessage = "Please select a valid date and time!";
} else { }
else
{
TransactionData.Transactions.Add(new Transaction() { GUID = Guid.NewGuid().ToString(), Amount = transactionAmount, UTCDateTime = transactionDateTime.UtcDateTime }); TransactionData.Transactions.Add(new Transaction() { GUID = Guid.NewGuid().ToString(), Amount = transactionAmount, UTCDateTime = transactionDateTime.UtcDateTime });
TransactionData.SaveTransactions(PTMagicBasePath); TransactionData.SaveTransactions(PTMagicBasePath);

View File

@ -101,7 +101,7 @@
<div class="col-md-12"> <div class="col-md-12">
<!-- TradingView Widget BEGIN --> <!-- TradingView Widget BEGIN -->
<div class="tradingview-widget-container"> <div class="tradingview-widget-container">
<div id="tradingview_6aa22" style="height:300px;"></div> <div id="tradingview_6aa22" style="height:600px;"></div>
<div class="tradingview-widget-copyright"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, Model.DCAMarket, Model.Summary.MainMarket)" rel="noopener" target="_blank"><span class="blue-text">@Model.DCAMarket</span> <span class="blue-text">chart</span> by TradingView</a></div> <div class="tradingview-widget-copyright"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, Model.DCAMarket, Model.Summary.MainMarket)" rel="noopener" target="_blank"><span class="blue-text">@Model.DCAMarket</span> <span class="blue-text">chart</span> by TradingView</a></div>
</div> </div>
<!-- TradingView Widget END --> <!-- TradingView Widget END -->

View File

@ -73,6 +73,7 @@
string sellStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, isSellStrategyTrue, isTrailingSellActive); string sellStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, isSellStrategyTrue, isTrailingSellActive);
string currentSellValueText = Core.ProfitTrailer.StrategyHelper.GetCurrentValueText(dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, dcaLogEntry.CurrentHighBBValue, dcaLogEntry.ProfitPercent, true); string currentSellValueText = Core.ProfitTrailer.StrategyHelper.GetCurrentValueText(dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, dcaLogEntry.CurrentHighBBValue, dcaLogEntry.ProfitPercent, true);
string triggerSellValueText = Core.ProfitTrailer.StrategyHelper.GetTriggerValueText(Model.Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, dcaLogEntry.BBTrigger, dcaLogEntry.SellTrigger, 0, true); string triggerSellValueText = Core.ProfitTrailer.StrategyHelper.GetTriggerValueText(Model.Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, dcaLogEntry.BBTrigger, dcaLogEntry.SellTrigger, 0, true);
double currentFiatValue = Math.Round(dcaLogEntry.Amount * dcaLogEntry.CurrentPrice * Model.Summary.MainMarketPrice, 2);
<tr> <tr>
@if (mps != null && (mps.ActiveSingleSettings == null || mps.ActiveSingleSettings.Count == 0)) { @if (mps != null && (mps.ActiveSingleSettings == null || mps.ActiveSingleSettings.Count == 0)) {
@ -111,7 +112,7 @@
</td> </td>
<td class="text-right">@dcaLogEntry.CurrentPrice.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td> <td class="text-right">@dcaLogEntry.CurrentPrice.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right">@dcaLogEntry.AverageBuyPrice.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td> <td class="text-right">@dcaLogEntry.AverageBuyPrice.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right">@dcaLogEntry.TotalCost.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td> <td class="text-right">@Html.Raw(@dcaLogEntry.TotalCost.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US")) + " (" + Model.MainFiatCurrencySymbol + currentFiatValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + ")")</td>
<td><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)_get/BagDetails/?m=@dcaLogEntry.Market" data-remote="false" data-toggle="modal" data-target="#dca-chart" class="btn btn-sm btn-ptmagic">Details</a></td> <td><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)_get/BagDetails/?m=@dcaLogEntry.Market" data-remote="false" data-toggle="modal" data-target="#dca-chart" class="btn btn-sm btn-ptmagic">Details</a></td>
</tr> </tr>
} }

View File

@ -85,7 +85,9 @@
<th class="text-right" data-toggle="tooltip" data-placement="top" title="Current DCA level">DCA</th> <th class="text-right" data-toggle="tooltip" data-placement="top" title="Current DCA level">DCA</th>
<th data-toggle="tooltip" data-placement="top" title="Active buy strategies">Buy Strats</th> <th data-toggle="tooltip" data-placement="top" title="Active buy strategies">Buy Strats</th>
<th data-toggle="tooltip" data-placement="top" title="Active sell strategies">Sell Strats</th> <th data-toggle="tooltip" data-placement="top" title="Active sell strategies">Sell Strats</th>
<th class="text-right" data-toggle="tooltip" data-placement="top" title="Current profit percentage">Profit</th> <th class="text-right" data-toggle="tooltip" data-placement="top" title=""></th>
<th class="text-left" data-toggle="tooltip" data-placement="top" title="Current Profit">Profit</th>
<th class="text-left" data-toggle="tooltip" data-placement="top" title="Current Total Cost">Cost</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -127,6 +129,8 @@
buyDisabled = true; buyDisabled = true;
} }
double currentFiatValue = Math.Round(dcaLogEntry.Amount * dcaLogEntry.CurrentPrice * Model.Summary.MainMarketPrice, 2);
string sellStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, isSellStrategyTrue, isTrailingSellActive); string sellStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, isSellStrategyTrue, isTrailingSellActive);
<tr> <tr>
@ -154,8 +158,10 @@
@if (isTrailingSellActive) { @if (isTrailingSellActive) {
<i class="fa fa-flag-checkered text-success" data-toggle="tooltip" data-placement="top" title="Trailing sell active!"></i> <i class="fa fa-flag-checkered text-success" data-toggle="tooltip" data-placement="top" title="Trailing sell active!"></i>
} }
<span class="text-autocolor">@dcaLogEntry.ProfitPercent.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))%</span>
</td> </td>
<td class="text-autocolor">@dcaLogEntry.ProfitPercent.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))%</td>
<td class="text-left">@Html.Raw(dcaLogEntry.TotalCost.ToString("#,#0.000000", new System.Globalization.CultureInfo("en-US")) + " (" + Model.MainFiatCurrencySymbol + @currentFiatValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + ")")</td>
<td class="text-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)_get/BagDetails/?m=@dcaLogEntry.Market" data-remote="false" data-toggle="modal" data-target="#dca-chart" class="btn btn-mini btn-ptmagic"><i class="fa fa-plus"></i></a></td> <td class="text-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)_get/BagDetails/?m=@dcaLogEntry.Market" data-remote="false" data-toggle="modal" data-target="#dca-chart" class="btn btn-mini btn-ptmagic"><i class="fa fa-plus"></i></a></td>
</tr> </tr>
} }

View File

@ -4,11 +4,15 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Monitor.ViewComponents { namespace Monitor.ViewComponents
public class PairIconViewComponent :ViewComponent { {
public async Task<IViewComponentResult> InvokeAsync(Core.Main.DataObjects.PTMagicData.MarketPairSummary mps) { public class PairIconViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(Core.Main.DataObjects.PTMagicData.MarketPairSummary mps)
{
IViewComponentResult result = null; IViewComponentResult result = null;
await Task.Run(() => { await Task.Run(() =>
{
result = View(mps); result = View(mps);
}); });
return result; return result;

View File

@ -14,9 +14,11 @@ using Core.ProfitTrailer;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using System.Diagnostics; using System.Diagnostics;
namespace Monitor._Internal { namespace Monitor._Internal
{
public class BasePageModel : PageModel { public class BasePageModel : PageModel
{
public string PTMagicBasePath = ""; public string PTMagicBasePath = "";
public string PTMagicMonitorBasePath = ""; public string PTMagicMonitorBasePath = "";
public PTMagicConfiguration PTMagicConfiguration = null; public PTMagicConfiguration PTMagicConfiguration = null;
@ -31,13 +33,16 @@ namespace Monitor._Internal {
public string MainFiatCurrencySymbol = "$"; public string MainFiatCurrencySymbol = "$";
public void PreInit() { public void PreInit()
{
PTMagicMonitorBasePath = Directory.GetCurrentDirectory(); PTMagicMonitorBasePath = Directory.GetCurrentDirectory();
if (!System.IO.File.Exists(PTMagicMonitorBasePath + Path.DirectorySeparatorChar + "appsettings.json")) { if (!System.IO.File.Exists(PTMagicMonitorBasePath + Path.DirectorySeparatorChar + "appsettings.json"))
{
PTMagicMonitorBasePath += Path.DirectorySeparatorChar + "Monitor"; PTMagicMonitorBasePath += Path.DirectorySeparatorChar + "Monitor";
} }
if (!PTMagicMonitorBasePath.EndsWith(Path.DirectorySeparatorChar)) { if (!PTMagicMonitorBasePath.EndsWith(Path.DirectorySeparatorChar))
{
PTMagicMonitorBasePath += Path.DirectorySeparatorChar; PTMagicMonitorBasePath += Path.DirectorySeparatorChar;
} }
@ -48,14 +53,18 @@ namespace Monitor._Internal {
PTMagicBasePath = config.GetValue<string>("PTMagicBasePath"); PTMagicBasePath = config.GetValue<string>("PTMagicBasePath");
if (!PTMagicBasePath.EndsWith(Path.DirectorySeparatorChar)) { if (!PTMagicBasePath.EndsWith(Path.DirectorySeparatorChar))
{
PTMagicBasePath += Path.DirectorySeparatorChar; PTMagicBasePath += Path.DirectorySeparatorChar;
} }
try { try
{
PTMagicConfiguration = new PTMagicConfiguration(PTMagicBasePath); PTMagicConfiguration = new PTMagicConfiguration(PTMagicBasePath);
} catch (Exception ex) { }
catch (Exception ex)
{
throw ex; throw ex;
} }
@ -67,44 +76,62 @@ namespace Monitor._Internal {
MainFiatCurrencySymbol = SystemHelper.GetCurrencySymbol(Summary.MainFiatCurrency); MainFiatCurrencySymbol = SystemHelper.GetCurrencySymbol(Summary.MainFiatCurrency);
try { try
{
// Get latest release from GitHub // Get latest release from GitHub
if (!String.IsNullOrEmpty(HttpContext.Session.GetString("LatestVersion"))) { if (!String.IsNullOrEmpty(HttpContext.Session.GetString("LatestVersion")))
{
LatestVersion = HttpContext.Session.GetString("LatestVersion"); LatestVersion = HttpContext.Session.GetString("LatestVersion");
} else { }
else
{
LatestVersion = BaseAnalyzer.GetLatestGitHubRelease(Log, Summary.Version); LatestVersion = BaseAnalyzer.GetLatestGitHubRelease(Log, Summary.Version);
HttpContext.Session.SetString("LatestVersion", LatestVersion); HttpContext.Session.SetString("LatestVersion", LatestVersion);
} }
} catch { } }
catch { }
try { try
{
// Get current bot version // Get current bot version
if (!String.IsNullOrEmpty(HttpContext.Session.GetString("CurrentBotVersion"))) { if (!String.IsNullOrEmpty(HttpContext.Session.GetString("CurrentBotVersion")))
{
CurrentBotVersion = HttpContext.Session.GetString("CurrentBotVersion"); CurrentBotVersion = HttpContext.Session.GetString("CurrentBotVersion");
} else { }
else
{
string ptMagicBotDllPath = PTMagicBasePath + "PTMagic.dll"; string ptMagicBotDllPath = PTMagicBasePath + "PTMagic.dll";
if (System.IO.File.Exists(ptMagicBotDllPath)) { if (System.IO.File.Exists(ptMagicBotDllPath))
{
FileVersionInfo ptMagicDllInfo = FileVersionInfo.GetVersionInfo(ptMagicBotDllPath); FileVersionInfo ptMagicDllInfo = FileVersionInfo.GetVersionInfo(ptMagicBotDllPath);
CurrentBotVersion = ptMagicDllInfo.ProductVersion.Substring(0, ptMagicDllInfo.ProductVersion.LastIndexOf(".")); CurrentBotVersion = ptMagicDllInfo.ProductVersion.Substring(0, ptMagicDllInfo.ProductVersion.LastIndexOf("."));
HttpContext.Session.SetString("CurrentBotVersion", CurrentBotVersion); HttpContext.Session.SetString("CurrentBotVersion", CurrentBotVersion);
} else { }
else
{
CurrentBotVersion = Summary.Version; CurrentBotVersion = Summary.Version;
} }
} }
} catch { }
catch
{
CurrentBotVersion = Summary.Version; CurrentBotVersion = Summary.Version;
} }
} }
protected string GetStringParameter(string paramName, string defaultValue) { protected string GetStringParameter(string paramName, string defaultValue)
{
string result = defaultValue; string result = defaultValue;
if (HttpContext.Request.Query.ContainsKey(paramName)) { if (HttpContext.Request.Query.ContainsKey(paramName))
{
result = HttpContext.Request.Query[paramName]; result = HttpContext.Request.Query[paramName];
} else if (HttpContext.Request.Method.Equals("POST") && HttpContext.Request.Form.ContainsKey(paramName)) { }
else if (HttpContext.Request.Method.Equals("POST") && HttpContext.Request.Form.ContainsKey(paramName))
{
result = HttpContext.Request.Form[paramName]; result = HttpContext.Request.Form[paramName];
} }
@ -117,19 +144,29 @@ namespace Monitor._Internal {
/// <param name="paramName">Name des Parameters</param> /// <param name="paramName">Name des Parameters</param>
/// <param name="defaultValue">Defaultvalue, wenn Parameter nicht vorhanden ist.</param> /// <param name="defaultValue">Defaultvalue, wenn Parameter nicht vorhanden ist.</param>
/// <returns>Der Wert des Parameters als Integer.</returns> /// <returns>Der Wert des Parameters als Integer.</returns>
protected int GetIntParameter(string paramName, int defaultValue) { protected int GetIntParameter(string paramName, int defaultValue)
{
int result = defaultValue; int result = defaultValue;
if (HttpContext.Request.Query.ContainsKey(paramName)) { if (HttpContext.Request.Query.ContainsKey(paramName))
try { {
try
{
result = Int32.Parse(HttpContext.Request.Query[paramName]); result = Int32.Parse(HttpContext.Request.Query[paramName]);
} catch { }
catch
{
result = defaultValue; result = defaultValue;
} }
} else if (HttpContext.Request.Method.Equals("POST") && HttpContext.Request.Form.ContainsKey(paramName)) { }
try { else if (HttpContext.Request.Method.Equals("POST") && HttpContext.Request.Form.ContainsKey(paramName))
{
try
{
result = Int32.Parse(HttpContext.Request.Form[paramName]); result = Int32.Parse(HttpContext.Request.Form[paramName]);
} catch { }
catch
{
result = defaultValue; result = defaultValue;
} }
} }

View File

@ -13,26 +13,34 @@ using Core.MarketAnalyzer;
using Core.ProfitTrailer; using Core.ProfitTrailer;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
namespace Monitor._Internal { namespace Monitor._Internal
{
public class BasePageModelSecure : BasePageModel { public class BasePageModelSecure : BasePageModel
public void Init() { {
public void Init()
{
base.PreInit(); base.PreInit();
if (String.IsNullOrEmpty(HttpContext.Session.GetString("LoggedIn" + PTMagicConfiguration.GeneralSettings.Monitor.Port.ToString())) && PTMagicConfiguration.GeneralSettings.Monitor.IsPasswordProtected) { if (String.IsNullOrEmpty(HttpContext.Session.GetString("LoggedIn" + PTMagicConfiguration.GeneralSettings.Monitor.Port.ToString())) && PTMagicConfiguration.GeneralSettings.Monitor.IsPasswordProtected)
{
bool redirectToLogin = true; bool redirectToLogin = true;
if (Request.Cookies.ContainsKey("PTMRememberMeKey")) { if (Request.Cookies.ContainsKey("PTMRememberMeKey"))
{
string rememberMeKey = Request.Cookies["PTMRememberMeKey"]; string rememberMeKey = Request.Cookies["PTMRememberMeKey"];
if (!rememberMeKey.Equals("")) { if (!rememberMeKey.Equals(""))
{
string encryptedPassword = EncryptionHelper.Decrypt(Request.Cookies["PTMRememberMeKey"]); string encryptedPassword = EncryptionHelper.Decrypt(Request.Cookies["PTMRememberMeKey"]);
if (encryptedPassword.Equals(PTMagicConfiguration.SecureSettings.MonitorPassword)) { if (encryptedPassword.Equals(PTMagicConfiguration.SecureSettings.MonitorPassword))
{
HttpContext.Session.SetString("LoggedIn" + PTMagicConfiguration.GeneralSettings.Monitor.Port.ToString(), DateTime.Now.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'")); HttpContext.Session.SetString("LoggedIn" + PTMagicConfiguration.GeneralSettings.Monitor.Port.ToString(), DateTime.Now.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'"));
redirectToLogin = false; redirectToLogin = false;
} }
} }
} }
if (redirectToLogin) { if (redirectToLogin)
{
HttpContext.Response.Redirect(PTMagicConfiguration.GeneralSettings.Monitor.RootUrl + "Login"); HttpContext.Response.Redirect(PTMagicConfiguration.GeneralSettings.Monitor.RootUrl + "Login");
} }
} }

View File

@ -13,26 +13,34 @@ using Core.MarketAnalyzer;
using Core.ProfitTrailer; using Core.ProfitTrailer;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
namespace Monitor._Internal { namespace Monitor._Internal
{
public class BasePageModelSecureAJAX : BasePageModel { public class BasePageModelSecureAJAX : BasePageModel
public void Init() { {
public void Init()
{
base.PreInit(); base.PreInit();
if (String.IsNullOrEmpty(HttpContext.Session.GetString("LoggedIn" + PTMagicConfiguration.GeneralSettings.Monitor.Port.ToString())) && PTMagicConfiguration.GeneralSettings.Monitor.IsPasswordProtected) { if (String.IsNullOrEmpty(HttpContext.Session.GetString("LoggedIn" + PTMagicConfiguration.GeneralSettings.Monitor.Port.ToString())) && PTMagicConfiguration.GeneralSettings.Monitor.IsPasswordProtected)
{
bool redirectToLogin = true; bool redirectToLogin = true;
if (Request.Cookies.ContainsKey("PTMRememberMeKey")) { if (Request.Cookies.ContainsKey("PTMRememberMeKey"))
{
string rememberMeKey = Request.Cookies["PTMRememberMeKey"]; string rememberMeKey = Request.Cookies["PTMRememberMeKey"];
if (!rememberMeKey.Equals("")) { if (!rememberMeKey.Equals(""))
{
string encryptedPassword = EncryptionHelper.Decrypt(Request.Cookies["PTMRememberMeKey"]); string encryptedPassword = EncryptionHelper.Decrypt(Request.Cookies["PTMRememberMeKey"]);
if (encryptedPassword.Equals(PTMagicConfiguration.SecureSettings.MonitorPassword)) { if (encryptedPassword.Equals(PTMagicConfiguration.SecureSettings.MonitorPassword))
{
HttpContext.Session.SetString("LoggedIn" + PTMagicConfiguration.GeneralSettings.Monitor.Port.ToString(), DateTime.Now.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'")); HttpContext.Session.SetString("LoggedIn" + PTMagicConfiguration.GeneralSettings.Monitor.Port.ToString(), DateTime.Now.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'"));
redirectToLogin = false; redirectToLogin = false;
} }
} }
} }
if (redirectToLogin) { if (redirectToLogin)
{
HttpContext.Response.Redirect(PTMagicConfiguration.GeneralSettings.Monitor.RootUrl + "_get/ReturnToLogin"); HttpContext.Response.Redirect(PTMagicConfiguration.GeneralSettings.Monitor.RootUrl + "_get/ReturnToLogin");
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -12,14 +12,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="NLog" Version="4.5.0-rc04" /> <PackageReference Include="NLog" Version="4.5.11" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.0.0-rtm-rc6" /> <PackageReference Include="NLog.Extensions.Logging" Version="1.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -7,12 +7,15 @@ using Core.Helper;
using Core.Main.DataObjects.PTMagicData; using Core.Main.DataObjects.PTMagicData;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
[assembly: AssemblyVersion("2.0.5")] [assembly: AssemblyVersion("2.0.6")]
[assembly: AssemblyProduct("PT Magic")] [assembly: AssemblyProduct("PT Magic")]
namespace PTMagic { namespace PTMagic
class Program { {
static void Main(string[] args) { class Program
{
static void Main(string[] args)
{
// Init PTMagic // Init PTMagic
Core.Main.PTMagic ptMagic = new Core.Main.PTMagic(ServiceHelper.BuildLoggerService().GetRequiredService<LogHelper>()); Core.Main.PTMagic ptMagic = new Core.Main.PTMagic(ServiceHelper.BuildLoggerService().GetRequiredService<LogHelper>());
ptMagic.CurrentVersion = Assembly.GetExecutingAssembly().GetName().Version; ptMagic.CurrentVersion = Assembly.GetExecutingAssembly().GetName().Version;
@ -21,7 +24,8 @@ namespace PTMagic {
ptMagic.StartProcess(); ptMagic.StartProcess();
// Keep the app running // Keep the app running
for (; ; ) { for (; ; )
{
Thread.Sleep(100); Thread.Sleep(100);
} }
} }

View File

@ -1,9 +0,0 @@
{
"PTMagicBasePath": "YOUR PT MAGIC PATH", // Path to your Profit Trailer Magic main directory (use double backslashes for windows like C:\\PTMagic\\)
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info" >
<!-- the targets to write to -->
<targets>
<!-- write logs to file -->
<target xsi:type="File" name="File" fileName="${basedir}/_logs/${shortdate}.txt"
layout="${date} ${level:uppercase=true} - ${message} ${exception:format=type,message,stacktrace}"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
<target xsi:type="ColoredConsole" name="Console"
layout="${date} ${level:uppercase=true} - ${message} ${exception:format=type,message,stacktrace}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<logger name="*" minlevel="Info" writeTo="Console" />
<logger name="*" minlevel="Info" writeTo="File" />
</rules>
</nlog>

View File

@ -1,241 +0,0 @@
{
"AnalyzerSettings": {
"MarketAnalyzer": {
"StoreDataMaxHours": 24, // Number of hours to store market data
"IntervalMinutes": 5, // 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": "CMC24h", // UNIQUE market trend name (to be referenced by your triggers below)
"Platform": "CoinMarketCap", // Platform to grab prices from (Allowed values are: CoinMarketCap, Exchange)
"MaxMarkets": 50, // Number of markets/pairs to analyze sorted by 24h volume
"TrendMinutes": 1440 // Number of minutes to build a trend (1440 = 24h, 720 = 12h, 60 = 1h)
},
{
"Name": "Exchange1h",
"Platform": "Exchange",
"MaxMarkets": 50,
"TrendMinutes": 60,
"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. (Allowed values are: Fiat, Market)
},
{
"Name": "Exchange12h",
"Platform": "Exchange",
"MaxMarkets": 50,
"TrendMinutes": 720,
"TrendCurrency": "Market"
},
{
"Name": "Exchange24h",
"Platform": "Exchange",
"MaxMarkets": 50,
"TrendMinutes": 1440,
"TrendCurrency": "Market"
}
]
},
"GlobalSettings": [ // Global settings for Profit Trailer properties
{
"SettingName": "EndOfTheWorld", // UNIQUE name of your setting
"TriggerConnection": "AND", // Define if triggers will be connected by AND or OR
"Triggers": [ // Your triggers for this setting
{
"MarketTrendName": "Exchange1h", // Reference to the market trend specified above
"MaxChange": 0 // Maximum trend change % for this setting to get triggered
},
{
"MarketTrendName": "Exchange12h",
"MaxChange": -1
},
{
"MarketTrendName": "Exchange24h",
"MaxChange": -5
}
],
"PairsProperties": { // Properties for PAIRS.PROPERTIES
"ALL_sell_only_mode": true,
"ALL_trailing_profit": 0.1
},
"DCAProperties": { // Properties for DCA.PROPERTIES
"trailing_profit": 0.1
}
},
{
"SettingName": "TankingDown",
"TriggerConnection": "AND",
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MaxChange": 0
},
{
"MarketTrendName": "Exchange12h",
"MaxChange": 0
},
{
"MarketTrendName": "Exchange24h",
"MaxChange": -3,
"MinChange": -5
}
],
"PairsProperties": {
"ALL_buy_value": -1.1,
"ALL_trailing_buy": 0.39,
"ALL_trailing_profit": 0.1
},
"DCAProperties": {
"trailing_buy": 0.1
}
},
{
"SettingName": "BearSighted",
"TriggerConnection": "AND",
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MaxChange": 1
},
{
"MarketTrendName": "Exchange12h",
"MaxChange": 0
},
{
"MarketTrendName": "Exchange24h",
"MaxChange": -1,
"MinChange": -3
}
],
"PairsProperties": {
"ALL_buy_value": -0.9,
"ALL_trailing_profit": 0.15
},
"DCAProperties": {
"trailing_profit": 0.15
}
},
{
"SettingName": "ReadyForLiftOff",
"TriggerConnection": "AND",
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MinChange": -1
},
{
"MarketTrendName": "Exchange12h",
"MinChange": 0
},
{
"MarketTrendName": "Exchange24h",
"MinChange": 1,
"MaxChange": 3
}
],
"PairsProperties": {
"ALL_trailing_buy": 0.2,
"ALL_sell_value": 1.1
},
"DCAProperties": {
"sell_value": 1.1
}
},
{
"SettingName": "ToTheMoon",
"TriggerConnection": "AND",
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MinChange": 0
},
{
"MarketTrendName": "Exchange12h",
"MinChange": 1
},
{
"MarketTrendName": "Exchange24h",
"MinChange": 3
}
],
"PairsProperties": {
"ALL_trailing_buy": 0.15,
"ALL_sell_value": 1.3
},
"DCAProperties": {
"sell_value": 1.3
}
},
{
"SettingName": "Default",
"PairsProperties": {
"File": "PAIRS.properties"
},
"DCAProperties": {
"File": "DCA.properties"
},
"IndicatorsProperties": {
"File": "INDICATORS.properties"
}
}
],
"SingleMarketSettings": [ // Single market/pair settings for Profit Trailer properties
{
"SettingName": "BlacklistNewCoins",
"StopProcessWhenTriggered": true,
"Triggers": [
{
"AgeDaysLowerThan": 14
}
],
"PairsProperties": {
"ALL_trading_enabled": false,
"ALL_sell_only_mode": true,
"ALL_DCA_enabled": false
}
},
{
"SettingName": "PumpNDumpProtection",
"TriggerConnection": "OR",
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "Relative", // The relation of the single market trend. Relative = Single market trend compared relative to the market trend / Absolute = Single market trend viewn on its own
"MinChange": 10
},
{
"MarketTrendName": "Exchange12h",
"MarketTrendRelation": "Relative",
"MinChange": 10
},
{
"MarketTrendName": "Exchange24h",
"MarketTrendRelation": "Relative",
"MinChange": 10
}
],
"PairsProperties": {
"ALL_trailing_profit_OFFSETPERCENT": -10,
"ALL_sell_value_OFFSETPERCENT": -30,
"ALL_sell_only_mode": true,
"ALL_DCA_enabled": false
}
},
{
"SettingName": "FreefallBlock",
"TriggerConnection": "OR",
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "Absolute",
"MaxChange": -5
}
],
"PairsProperties": {
"ALL_trailing_profit_OFFSETPERCENT": -10,
"ALL_sell_value_OFFSETPERCENT": -30,
"ALL_sell_only_mode": true,
"ALL_DCA_enabled": false
}
}
]
}
}

View File

@ -1,40 +0,0 @@
{
"GeneralSettings": {
"Application": {
"IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect)
"TestMode": false, // If TestMode is active, no properties files will be changed
"ProfitTrailerPath": "YOUR PROFIT TRAILER PATH", // Path to your Profit Trailer main directory (use double backslashes for windows like C:\\ProfitTrailer\\)
"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
"MainFiatCurrency": "USD", // Your main fiat currency that will be used in the monitor
"AlwaysLoadDefaultBeforeSwitch": true, // If this is enabled, PTMagic will always load default settings before switching to another setting
"FloodProtectionMinutes": 15, // If a price trend is just zig-zagging around its trigger, you may want to protect your settings from getting switched back and forth every minute
"InstanceName": "PT Magic", // The name of the instance of this bot. This will be used in your monitor and your Telegram messages. In case you are running more than one bot, you may set different names to separate them
"CoinMarketCapAPIKey": "" //CoinMarketCap Api
},
"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
"RootUrl": "/", // The root Url of your monitor
"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
"LinkPlatform": "TradingView", // The platform to which the pair name will link if you click on it
"MaxTopMarkets": 20, // The amount of top markets being shown in your Sales Analyzer
"MaxDailySummaries": 10, // The amount of "Last Days" being shown in your Sales Analyzer
"MaxMonthlySummaries": 10 // The amount of "Last Months" being shown in your Sales Analyzer
},
"Backup": {
"IsEnabled": true, // Enables a backup procedure for your properties files. Before every switch PTMagic will backup the current properties
"MaxHours": 12 // Max number of hours to keep backup files
},
"Telegram": {
"IsEnabled": false, // Enables PT Magic to send Telegram messages
"BotToken": "", // Your Telegram bot token
"ChatId": 0, // Your Telegram Chat ID
"SilentMode": false // If SilentMode is active, no notification sound or vibration will happen when the bot sends a Telegram message
}
}
}

View File

@ -1,9 +0,0 @@
{
"PTMagicBasePath": "YOUR PT MAGIC PATH", // Path to your Profit Trailer Magic main directory (use double backslashes for windows like C:\\PTMagic\\)
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info" >
<!-- the targets to write to -->
<targets>
<!-- write logs to file -->
<target xsi:type="File" name="File" fileName="${basedir}/_logs/${shortdate}.txt"
layout="${date} ${level:uppercase=true} - ${message} ${exception:format=type,message,stacktrace}"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
<target xsi:type="ColoredConsole" name="Console"
layout="${date} ${level:uppercase=true} - ${message} ${exception:format=type,message,stacktrace}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<logger name="*" minlevel="Info" writeTo="Console" />
<logger name="*" minlevel="Info" writeTo="File" />
</rules>
</nlog>

View File

@ -1,242 +0,0 @@
{
"AnalyzerSettings": {
"MarketAnalyzer": {
"StoreDataMaxHours": 24, // Number of hours to store market data
"IntervalMinutes": 1, // 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": "CMC24h", // UNIQUE market trend name (to be referenced by your triggers below)
"Platform": "CoinMarketCap", // Platform to grab prices from (Allowed values are: CoinMarketCap, Exchange)
"MaxMarkets": 50, // Number of markets/pairs to analyze sorted by 24h volume
"TrendMinutes": 1440 // Number of minutes to build a trend (1440 = 24h, 720 = 12h, 60 = 1h)
},
{
"Name": "Exchange1h",
"Platform": "Exchange",
"MaxMarkets": 50,
"TrendMinutes": 60,
"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. (Allowed values are: Fiat, Market)
"IgnoredMarkets": "BNBBTC" // Comma separated list of markets you want to be ignored in this market trend.
},
{
"Name": "Exchange12h",
"Platform": "Exchange",
"MaxMarkets": 50,
"TrendMinutes": 720,
"TrendCurrency": "Market",
"IgnoredMarkets": "BNBBTC"
},
{
"Name": "Exchange24h",
"Platform": "Exchange",
"MaxMarkets": 50,
"TrendMinutes": 1440,
"TrendCurrency": "Market",
"IgnoredMarkets": "BNBBTC"
}
]
},
"GlobalSettings": [ // Global settings for Profit Trailer properties
{
"SettingName": "EndOfTheWorld", // UNIQUE name of your setting
"TriggerConnection": "AND", // Define if triggers will be connected by AND or OR
"Triggers": [ // Your triggers for this setting
{
"MarketTrendName": "Exchange12h", // Reference to the market trend specified above
"MaxChange": -1 // Maximum trend change % for this setting to get triggered
},
{
"MarketTrendName": "Exchange24h",
"MaxChange": -5
}
],
"PairsProperties": { // Properties for PAIRS.PROPERTIES
"ALL_sell_only_mode": true,
"ALL_trailing_profit_OFFSETPERCENT": -50
},
"DCAProperties": { // Properties for DCA.PROPERTIES
"trailing_profit_OFFSETPERCENT": -50
}
},
{
"SettingName": "TankingDown",
"TriggerConnection": "AND",
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MaxChange": 1
},
{
"MarketTrendName": "Exchange12h",
"MaxChange": 0
},
{
"MarketTrendName": "Exchange24h",
"MaxChange": -3,
"MinChange": -5
}
],
"PairsProperties": {
"ALL_buy_value_OFFSETPERCENT": -10,
"ALL_trailing_buy_OFFSETPERCENT": 10,
"ALL_trailing_profit_OFFSETPERCENT": -25
},
"DCAProperties": {
"trailing_buy_OFFSETPERCENT": -25
}
},
{
"SettingName": "BearSighted",
"TriggerConnection": "AND",
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MaxChange": 1
},
{
"MarketTrendName": "Exchange12h",
"MaxChange": 0
},
{
"MarketTrendName": "Exchange24h",
"MaxChange": -1,
"MinChange": -3
}
],
"PairsProperties": {
"ALL_buy_value_OFFSETPERCENT": -5,
"ALL_trailing_profit_OFFSETPERCENT": -10
},
"DCAProperties": {
"trailing_profit_OFFSETPERCENT": -10
}
},
{
"SettingName": "ReadyForLiftOff",
"TriggerConnection": "AND",
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MinChange": -1
},
{
"MarketTrendName": "Exchange12h",
"MinChange": 0
},
{
"MarketTrendName": "Exchange24h",
"MinChange": 1,
"MaxChange": 3
}
],
"PairsProperties": {
"ALL_trailing_buy_OFFSETPERCENT": -25,
"ALL_sell_value_OFFSETPERCENT": 10
},
"DCAProperties": {
"sell_value_OFFSETPERCENT": 10
}
},
{
"SettingName": "ToTheMoon",
"TriggerConnection": "AND",
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MinChange": -1
},
{
"MarketTrendName": "Exchange12h",
"MinChange": 1
},
{
"MarketTrendName": "Exchange24h",
"MinChange": 3
}
],
"PairsProperties": {
"ALL_trailing_buy_OFFSETPERCENT": -50,
"ALL_sell_value_OFFSETPERCENT": 25
},
"DCAProperties": {
"sell_value_OFFSETPERCENT": 25
}
},
{
"SettingName": "Default",
"PairsProperties": {
"File": "PAIRS.PROPERTIES"
},
"DCAProperties": {
"File": "DCA.PROPERTIES"
},
"IndicatorsProperties": {
"File": "INDICATORS.PROPERTIES"
}
}
],
"SingleMarketSettings": [ // Single market/pair settings for Profit Trailer properties
{
"SettingName": "BlacklistNewCoins",
"StopProcessWhenTriggered": true,
"Triggers": [
{
"AgeDaysLowerThan": 14
}
],
"PairsProperties": {
"ALL_trading_enabled": false,
"ALL_sell_only_mode": true,
"ALL_DCA_enabled": false
}
},
{
"SettingName": "PumpNDumpProtection",
"TriggerConnection": "OR",
"StopProcessWhenTriggered": true,
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "Relative", // The relation of the single market trend. Relative = Single market trend compared relative to the market trend / Absolute = Single market trend viewn on its own
"MinChange": 5
},
{
"MarketTrendName": "Exchange12h",
"MarketTrendRelation": "Relative",
"MinChange": 5
},
{
"MarketTrendName": "Exchange24h",
"MarketTrendRelation": "Relative",
"MinChange": 5
}
],
"PairsProperties": {
"ALL_trailing_profit_OFFSETPERCENT": -10,
"ALL_sell_value_OFFSETPERCENT": -30,
"ALL_sell_only_mode": true,
"ALL_DCA_enabled": false
}
},
{
"SettingName": "FreefallBlock",
"TriggerConnection": "OR",
"StopProcessWhenTriggered": true,
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "Absolute",
"MaxChange": -5
}
],
"PairsProperties": {
"ALL_trailing_profit_OFFSETPERCENT": -10,
"ALL_sell_value_OFFSETPERCENT": -30,
"ALL_sell_only_mode": true,
"ALL_DCA_enabled": false
}
}
]
}
}

View File

@ -1,40 +0,0 @@
{
"GeneralSettings": {
"Application": {
"IsEnabled": true, // Enables the PTMagic bot (needs restart to take effect)
"TestMode": false, // If TestMode is active, no properties files will be changed
"ProfitTrailerPath": "YOUR PROFIT TRAILER PATH", // Path to your Profit Trailer main directory (use double backslashes for windows like C:\\ProfitTrailer\\)
"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
"MainFiatCurrency": "USD", // Your main fiat currency that will be used in the monitor
"AlwaysLoadDefaultBeforeSwitch": true, // If this is enabled, PTMagic will always load default settings before switching to another setting
"FloodProtectionMinutes": 15, // If a price trend is just zig-zagging around its trigger, you may want to protect your settings from getting switched back and forth every minute
"InstanceName": "PT Magic", // The name of the instance of this bot. This will be used in your monitor and your Telegram messages. In case you are running more than one bot, you may set different names to separate them
"CoinMarketCapAPIKey": "" //CoinMarketCap Api
},
"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
"RootUrl": "/", // The root Url of your monitor
"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
"LinkPlatform": "TradingView", // The platform to which the pair name will link if you click on it
"MaxTopMarkets": 20, // The amount of top markets being shown in your Sales Analyzer
"MaxDailySummaries": 10, // The amount of "Last Days" being shown in your Sales Analyzer
"MaxMonthlySummaries": 10 // The amount of "Last Months" being shown in your Sales Analyzer
},
"Backup": {
"IsEnabled": true, // Enables a backup procedure for your properties files. Before every switch PTMagic will backup the current properties
"MaxHours": 12 // Max number of hours to keep backup files
},
"Telegram": {
"IsEnabled": false, // Enables PT Magic to send Telegram messages
"BotToken": "", // Your Telegram bot token
"ChatId": 0, // Your Telegram Chat ID
"SilentMode": false // If SilentMode is active, no notification sound or vibration will happen when the bot sends a Telegram message
}
}
}

View File

@ -1,171 +1,238 @@
{ //
// 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": { "AnalyzerSettings": {
"MarketAnalyzer": { "MarketAnalyzer": {
"StoreDataMaxHours": 24, // Number of hours to store market data "StoreDataMaxHours": 48, // Number of hours to store market data
"IntervalMinutes": 5, // 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 "ExcludeMainCurrency": true, // Excludes the main currency (for example BTC) from market trend analysis
"MarketTrends": [ "MarketTrends": [
{ {
"Name": "CMC24h", // UNIQUE market trend name (to be referenced by your triggers below) "Name": "15m", // UNIQUE market trend name (to be referenced by your triggers below)
"Platform": "CoinMarketCap", // Platform to grab prices from (Allowed values are: CoinMarketCap, Exchange) "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": 1440 // Number of minutes to build a trend (1440 = 24h, 720 = 12h, 60 = 1h) "TrendMinutes": 15, // 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.
// (Allowed values are: Fiat, Market)
"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": "Exchange1h", "Name": "1h",
"Platform": "Exchange", "Platform": "Exchange",
"MaxMarkets": 50, "MaxMarkets": 50,
"TrendMinutes": 60, "TrendMinutes": 60,
"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. (Allowed values are: Fiat, Market) "TrendCurrency": "Market",
"DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
}, },
{ {
"Name": "Exchange12h", "Name": "6h",
"Platform": "Exchange",
"MaxMarkets": 50,
"TrendMinutes": 360,
"TrendCurrency": "Market",
"DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
},
{
"Name": "12h",
"Platform": "Exchange", "Platform": "Exchange",
"MaxMarkets": 50, "MaxMarkets": 50,
"TrendMinutes": 720, "TrendMinutes": 720,
"TrendCurrency": "Market" "TrendCurrency": "Market",
"DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
}, },
{ {
"Name": "Exchange24h", "Name": "24h",
"Platform": "Exchange", "Platform": "Exchange",
"MaxMarkets": 50, "MaxMarkets": 50,
"TrendMinutes": 1440, "TrendMinutes": 1440,
"TrendCurrency": "Market" "TrendCurrency": "Market",
"DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
} }
] ]
}, },
// ================================ GLOBAL SETTINGS ================================
//
"GlobalSettings": [ // Global settings for Profit Trailer properties "GlobalSettings": [ // Global settings for Profit Trailer properties
//
// -----------------------------
{ {
"SettingName": "EndOfTheWorld", // UNIQUE name of your setting "SettingName": "EndOfTheWorld", // ANY UNIQUE name of your setting
"TriggerConnection": "AND", // Define if triggers will be connected by AND or OR "TriggerConnection": "AND", // Define if triggers will be connected by AND or OR
"Triggers": [ // Your triggers for this setting "Triggers": [ // Your triggers for this setting. You can use any of your defined trends from above
{ {
"MarketTrendName": "Exchange1h", // Reference to the market trend specified above "MarketTrendName": "1h", // Reference to the market trend specified above
"MaxChange": 0 // Maximum trend change % for this setting to get triggered "MaxChange": 0 // The maximum value for this trigger to be true. (Any value below "0" will trigger this)
}, },
{ {
"MarketTrendName": "Exchange12h", "MarketTrendName": "12h",
"MaxChange": -1 "MaxChange": -2
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "24h",
"MaxChange": -5 "MaxChange": -5
} }
], ],
"PairsProperties": { // Properties for PAIRS.PROPERTIES "PairsProperties": { // Properties for PAIRS.PROPERTIES
// Any valid setting from https://wiki.profittrailer.com/doku.php?id=pairs.properties 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 "DEFAULT_trailing_profit_OFFSETPERCENT": -50
}, },
"DCAProperties": { // Properties for DCA.PROPERTIES "DCAProperties": { // Properties for DCA.PROPERTIES
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50 "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -75
} }
}, },
// -----------------------------
{ {
"SettingName": "TankingDown", "SettingName": "TankingDown",
"TriggerConnection": "AND", "TriggerConnection": "AND",
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "15m",
"MaxChange": 0
},
{
"MarketTrendName": "1h",
"MaxChange": 0 "MaxChange": 0
}, },
{ {
"MarketTrendName": "Exchange12h", "MarketTrendName": "12h",
"MaxChange": 0 "MaxChange": 0
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "24h", // Any value between -5 and -3 will make this trigger true.
"MaxChange": -3, "MaxChange": -3,
"MinChange": -5 "MinChange": -5 // The minimum value for this trigger to be true. (Any value above "-5" will trigger this)
} }
], ],
"PairsProperties": { "PairsProperties": {
"DEFAULT_A_buy_value_OFFSETPERCENT": -10, "max_trading_pairs_OFFSET": -2,
"DEFAULT_B_buy_value_OFFSETPERCENT": -10, "DEFAULT_min_buy_volume_OFFSETPERCENT": 100,
"DEFAULT_trailing_buy_OFFSETPERCENT": 10, //"DEFAULT_initial_cost_OFFSETPERCENT": -50,
//"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -50,
"DEFAULT_trailing_buy_OFFSETPERCENT": 25,
"DEFAULT_trailing_profit_OFFSETPERCENT": -25 "DEFAULT_trailing_profit_OFFSETPERCENT": -25
}, },
"DCAProperties": { "DCAProperties": {
"DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -25 //"DEFAULT_DCA_rebuy_timeout_OFFSETPERCENT": 100,
"DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 25,
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50
},
"IndicatorsProperties": {
} }
}, },
// -----------------------------
{ {
"SettingName": "BearSighted", "SettingName": "BearSighted",
"TriggerConnection": "AND", "TriggerConnection": "AND",
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "1h",
"MaxChange": 1 "MaxChange": 1
}, },
{ {
"MarketTrendName": "Exchange12h", "MarketTrendName": "12h",
"MaxChange": 0 "MaxChange": 0
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "24h",
"MaxChange": -1, "MaxChange": -1,
"MinChange": -3 "MinChange": -3
} }
], ],
"PairsProperties": { "PairsProperties": {
"DEFAULT_A_buy_value_OFFSETPERCENT": -5, "max_trading_pairs_OFFSET": -1,
"DEFAULT_B_buy_value_OFFSETPERCENT": -5, //"DEFAULT_initial_cost_OFFSETPERCENT": -25,
//"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -25,
"DEFAULT_trailing_buy_OFFSETPERCENT": 10,
"DEFAULT_trailing_profit_OFFSETPERCENT": -10 "DEFAULT_trailing_profit_OFFSETPERCENT": -10
}, },
"DCAProperties": { "DCAProperties": {
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10 "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 10,
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10,
},
"IndicatorsProperties": {
} }
}, },
// -----------------------------
{ {
"SettingName": "ReadyForLiftOff", "SettingName": "ReadyForLiftOff",
"TriggerConnection": "AND", "TriggerConnection": "AND",
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "1h",
"MinChange": -1
},
{
"MarketTrendName": "Exchange12h",
"MinChange": 0 "MinChange": 0
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "12h",
"MinChange": 0
},
{
"MarketTrendName": "24h",
"MinChange": 1, "MinChange": 1,
"MaxChange": 3 "MaxChange": 3
} }
], ],
"PairsProperties": { "PairsProperties": {
"DEFAULT_trailing_buy_OFFSETPERCENT": -25, "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_A_sell_value_OFFSETPERCENT": 10
}, },
"DCAProperties": { "DCAProperties": {
"DEFAULT_DCA_A_sell_value_OFFSETPERCENT": 10 "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -10,
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 10,
},
"IndicatorsProperties": {
} }
}, },
// -----------------------------
{ {
"SettingName": "ToTheMoon", "SettingName": "ToTheMoon",
"TriggerConnection": "AND", "TriggerConnection": "AND",
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "1h",
"MinChange": 0
},
{
"MarketTrendName": "Exchange12h",
"MinChange": 1 "MinChange": 1
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "12h",
"MinChange": 1
},
{
"MarketTrendName": "24h",
"MinChange": 3 "MinChange": 3
} }
], ],
"PairsProperties": { "PairsProperties": {
"DEFAULT_trailing_buy_OFFSETPERCENT": -50, "max_trading_pairs_OFFSET": 2,
"DEFAULT_A_sell_value_OFFSETPERCENT": 25 //"DEFAULT_initial_cost_OFFSETPERCENT": 20,
//"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 20,
"DEFAULT_trailing_buy_OFFSETPERCENT": -10,
"DEFAULT_A_sell_value_OFFSETPERCENT": 20
}, },
"DCAProperties": { "DCAProperties": {
"DEFAULT_DCA_A_sell_value_OFFSETPERCENT": 25 "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -20,
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 20,
},
"IndicatorsProperties": {
} }
}, },
// -----------------------------
{ {
"SettingName": "Default", "SettingName": "Default",
"PairsProperties": { "PairsProperties": {
@ -179,13 +246,18 @@
} }
} }
], ],
// ================================ COIN-SPECIFIC SETTINGS ================================
//
"SingleMarketSettings": [ // Single market/pair settings for Profit Trailer properties "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.
{ {
"SettingName": "BlacklistNewCoins", "SettingName": "BlacklistCoins",
"StopProcessWhenTriggered": true, "StopProcessWhenTriggered": true,
"Triggers": [ "Triggers": [
{ {
"AgeDaysLowerThan": 14 "AgeDaysLowerThan": 21
} }
], ],
"PairsProperties": { "PairsProperties": {
@ -194,24 +266,33 @@
"DEFAULT_DCA_enabled": false "DEFAULT_DCA_enabled": false
} }
}, },
// -----------------------------
{ {
"SettingName": "PumpNDumpProtection", "SettingName": "PumpNDumpProtection",
"TriggerConnection": "OR", "TriggerConnection": "OR",
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "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 viewn on its own "MarketTrendRelation": "Relative", // The relation of the single market trend. Relative = Single market
"MinChange": 10 // trend compared relative to the market trend
// Absolute = Single market trend viewed on its own
"MinChange": 8
}, },
{ {
"MarketTrendName": "Exchange12h", "MarketTrendName": "12h",
"MarketTrendRelation": "Relative", "MarketTrendRelation": "Relative",
"MinChange": 10 "MinChange": 10
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "24h",
"MarketTrendRelation": "Relative", "MarketTrendRelation": "Relative",
"MinChange": 10 "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": { "PairsProperties": {
@ -219,17 +300,23 @@
"DEFAULT_DCA_enabled": false "DEFAULT_DCA_enabled": false
} }
}, },
// -----------------------------
{ {
"SettingName": "FreefallBlock", "SettingName": "FreefallBlock",
"TriggerConnection": "OR", "TriggerConnection": "OR",
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "1h",
"MarketTrendRelation": "Absolute", "MarketTrendRelation": "Absolute",
"MaxChange": -5 "MaxChange": -5
} }
], ],
"PairsProperties": { "OffTriggers": [
{
"HoursSinceTriggered": 1
}
],
"PairsProperties": {
"DEFAULT_sell_only_mode_enabled": true, "DEFAULT_sell_only_mode_enabled": true,
"DEFAULT_DCA_enabled": false "DEFAULT_DCA_enabled": false
} }

View File

@ -1,190 +1,263 @@
{ //
// 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": { "AnalyzerSettings": {
"MarketAnalyzer": { "MarketAnalyzer": {
"StoreDataMaxHours": 24, // Number of hours to store market data "StoreDataMaxHours": 48, // Number of hours to store market data
"IntervalMinutes": 1, // 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 "ExcludeMainCurrency": true, // Excludes the main currency (for example BTC) from market trend analysis
"MarketTrends": [ "MarketTrends": [
{ {
"Name": "CMC24h", // UNIQUE market trend name (to be referenced by your triggers below) "Name": "15m", // UNIQUE market trend name (to be referenced by your triggers below)
"Platform": "CoinMarketCap", // Platform to grab prices from (Allowed values are: CoinMarketCap, Exchange) "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": 1440 // Number of minutes to build a trend (1440 = 24h, 720 = 12h, 60 = 1h) "TrendMinutes": 15, // 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.
// (Allowed values are: Fiat, Market)
"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": "Exchange1h", "Name": "1h",
"Platform": "Exchange", "Platform": "Exchange",
"MaxMarkets": 50, "MaxMarkets": 50,
"TrendMinutes": 60, "TrendMinutes": 60,
"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. (Allowed values are: Fiat, Market) "TrendCurrency": "Market",
"IgnoredMarkets": "BNBBTC" // Comma separated list of markets you want to be ignored in this market trend. "DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
}, },
{ {
"Name": "Exchange12h", "Name": "6h",
"Platform": "Exchange",
"MaxMarkets": 50,
"TrendMinutes": 360,
"TrendCurrency": "Market",
"DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
},
{
"Name": "12h",
"Platform": "Exchange", "Platform": "Exchange",
"MaxMarkets": 50, "MaxMarkets": 50,
"TrendMinutes": 720, "TrendMinutes": 720,
"TrendCurrency": "Market", "TrendCurrency": "Market",
"IgnoredMarkets": "BNBBTC" "DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
}, },
{ {
"Name": "Exchange24h", "Name": "24h",
"Platform": "Exchange", "Platform": "Exchange",
"MaxMarkets": 50, "MaxMarkets": 50,
"TrendMinutes": 1440, "TrendMinutes": 1440,
"TrendCurrency": "Market", "TrendCurrency": "Market",
"IgnoredMarkets": "BNBBTC" "DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
} }
] ]
}, },
// ================================ GLOBAL SETTINGS ================================
//
"GlobalSettings": [ // Global settings for Profit Trailer properties "GlobalSettings": [ // Global settings for Profit Trailer properties
//
// -----------------------------
{ {
"SettingName": "EndOfTheWorld", // UNIQUE name of your setting "SettingName": "EndOfTheWorld", // ANY UNIQUE name of your setting
"TriggerConnection": "AND", // Define if triggers will be connected by AND or OR "TriggerConnection": "AND", // Define if triggers will be connected by AND or OR
"Triggers": [ // Your triggers for this setting "Triggers": [ // Your triggers for this setting. You can use any of your defined trends from above
{ {
"MarketTrendName": "Exchange12h", // Reference to the market trend specified above "MarketTrendName": "1h", // Reference to the market trend specified above
"MaxChange": -1 // Maximum trend change % for this setting to get triggered "MaxChange": 0 // The maximum value for this trigger to be true. (Any value below "0" will trigger this)
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "12h",
"MaxChange": -2
},
{
"MarketTrendName": "24h",
"MaxChange": -5 "MaxChange": -5
} }
], ],
"PairsProperties": { // Properties for PAIRS.PROPERTIES "PairsProperties": { // Properties for PAIRS.PROPERTIES
// Any valid setting from https://wiki.profittrailer.com/doku.php?id=pairs.properties 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 "DEFAULT_trailing_profit_OFFSETPERCENT": -50
}, },
"DCAProperties": { // Properties for DCA.PROPERTIES "DCAProperties": { // Properties for DCA.PROPERTIES
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50 "DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -75
} }
}, },
// -----------------------------
{ {
"SettingName": "TankingDown", "SettingName": "TankingDown",
"TriggerConnection": "AND", "TriggerConnection": "AND",
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "15m",
"MaxChange": 1 "MaxChange": 0
}, },
{ {
"MarketTrendName": "Exchange12h", "MarketTrendName": "1h",
"MaxChange": 0 "MaxChange": 0
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "12h",
"MaxChange": 0
},
{
"MarketTrendName": "24h", // Any value between -5 and -3 will make this trigger true.
"MaxChange": -3, "MaxChange": -3,
"MinChange": -5 "MinChange": -5 // The minimum value for this trigger to be true. (Any value above "-5" will trigger this)
} }
], ],
"PairsProperties": { "PairsProperties": {
"DEFAULT_A_buy_value_OFFSETPERCENT": -10, "max_trading_pairs_OFFSET": -2,
"DEFAULT_B_buy_value_OFFSETPERCENT": -10, "DEFAULT_min_buy_volume_OFFSETPERCENT": 100,
"DEFAULT_trailing_buy_OFFSETPERCENT": 10, //"DEFAULT_initial_cost_OFFSETPERCENT": -50,
//"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -50,
"DEFAULT_trailing_buy_OFFSETPERCENT": 25,
"DEFAULT_trailing_profit_OFFSETPERCENT": -25 "DEFAULT_trailing_profit_OFFSETPERCENT": -25
}, },
"DCAProperties": { "DCAProperties": {
"DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -25 //"DEFAULT_DCA_rebuy_timeout_OFFSETPERCENT": 100,
"DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 25,
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50
},
"IndicatorsProperties": {
} }
}, },
// -----------------------------
{ {
"SettingName": "BearSighted", "SettingName": "BearSighted",
"TriggerConnection": "AND", "TriggerConnection": "AND",
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "1h",
"MaxChange": 1 "MaxChange": 1
}, },
{ {
"MarketTrendName": "Exchange12h", "MarketTrendName": "12h",
"MaxChange": 0 "MaxChange": 0
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "24h",
"MaxChange": -1, "MaxChange": -1,
"MinChange": -3 "MinChange": -3
} }
], ],
"PairsProperties": { "PairsProperties": {
"DEFAULT_A_buy_value_OFFSETPERCENT": -5, "max_trading_pairs_OFFSET": -1,
"DEFAULT_B_buy_value_OFFSETPERCENT": -5, //"DEFAULT_initial_cost_OFFSETPERCENT": -25,
//"DEFAULT_initial_cost_percentage_OFFSETPERCENT": -25,
"DEFAULT_trailing_buy_OFFSETPERCENT": 10,
"DEFAULT_trailing_profit_OFFSETPERCENT": -10 "DEFAULT_trailing_profit_OFFSETPERCENT": -10
}, },
"DCAProperties": { "DCAProperties": {
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10 "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": 10,
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -10,
},
"IndicatorsProperties": {
} }
}, },
// -----------------------------
{ {
"SettingName": "ReadyForLiftOff", "SettingName": "ReadyForLiftOff",
"TriggerConnection": "AND", "TriggerConnection": "AND",
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "1h",
"MinChange": -1
},
{
"MarketTrendName": "Exchange12h",
"MinChange": 0 "MinChange": 0
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "12h",
"MinChange": 0
},
{
"MarketTrendName": "24h",
"MinChange": 1, "MinChange": 1,
"MaxChange": 3 "MaxChange": 3
} }
], ],
"PairsProperties": { "PairsProperties": {
"DEFAULT_trailing_buy_OFFSETPERCENT": -25, "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_A_sell_value_OFFSETPERCENT": 10
}, },
"DCAProperties": { "DCAProperties": {
"DEFAULT_DCA_A_sell_value_OFFSETPERCENT": 10 "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -10,
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 10,
},
"IndicatorsProperties": {
} }
}, },
// -----------------------------
{ {
"SettingName": "ToTheMoon", "SettingName": "ToTheMoon",
"TriggerConnection": "AND", "TriggerConnection": "AND",
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "1h",
"MinChange": -1
},
{
"MarketTrendName": "Exchange12h",
"MinChange": 1 "MinChange": 1
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "12h",
"MinChange": 1
},
{
"MarketTrendName": "24h",
"MinChange": 3 "MinChange": 3
} }
], ],
"PairsProperties": { "PairsProperties": {
"DEFAULT_trailing_buy_OFFSETPERCENT": -50, "max_trading_pairs_OFFSET": 2,
"DEFAULT_A_sell_value_OFFSETPERCENT": 25 //"DEFAULT_initial_cost_OFFSETPERCENT": 20,
//"DEFAULT_initial_cost_percentage_OFFSETPERCENT": 20,
"DEFAULT_trailing_buy_OFFSETPERCENT": -10,
"DEFAULT_A_sell_value_OFFSETPERCENT": 20
}, },
"DCAProperties": { "DCAProperties": {
"DEFAULT_DCA_A_sell_value_OFFSETPERCENT": 25 "DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -20,
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": 20,
},
"IndicatorsProperties": {
} }
}, },
// -----------------------------
{ {
"SettingName": "Default", "SettingName": "Default",
"PairsProperties": { "PairsProperties": {
"File": "PAIRS.PROPERTIES" "File": "PAIRS.properties"
}, },
"DCAProperties": { "DCAProperties": {
"File": "DCA.PROPERTIES" "File": "DCA.properties"
}, },
"IndicatorsProperties": { "IndicatorsProperties": {
"File": "INDICATORS.PROPERTIES" "File": "INDICATORS.properties"
} }
} }
], ],
// ================================ COIN-SPECIFIC SETTINGS ================================
//
"SingleMarketSettings": [ // Single market/pair settings for Profit Trailer properties "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.
{ {
"SettingName": "BlacklistNewCoins", "SettingName": "BlacklistCoins",
"StopProcessWhenTriggered": true, "StopProcessWhenTriggered": true,
"Triggers": [ "Triggers": [
{ {
"AgeDaysLowerThan": 14 "AgeDaysLowerThan": 21
} }
], ],
"PairsProperties": { "PairsProperties": {
@ -193,25 +266,33 @@
"DEFAULT_DCA_enabled": false "DEFAULT_DCA_enabled": false
} }
}, },
// -----------------------------
{ {
"SettingName": "PumpNDumpProtection", "SettingName": "PumpNDumpProtection",
"TriggerConnection": "OR", "TriggerConnection": "OR",
"StopProcessWhenTriggered": true,
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "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 viewn on its own "MarketTrendRelation": "Relative", // The relation of the single market trend. Relative = Single market
"MinChange": 5 // trend compared relative to the market trend
// Absolute = Single market trend viewed on its own
"MinChange": 8
}, },
{ {
"MarketTrendName": "Exchange12h", "MarketTrendName": "12h",
"MarketTrendRelation": "Relative", "MarketTrendRelation": "Relative",
"MinChange": 5 "MinChange": 10
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "24h",
"MarketTrendRelation": "Relative", "MarketTrendRelation": "Relative",
"MinChange": 5 "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": { "PairsProperties": {
@ -219,20 +300,23 @@
"DEFAULT_DCA_enabled": false "DEFAULT_DCA_enabled": false
} }
}, },
// -----------------------------
{ {
"SettingName": "FreefallBlock", "SettingName": "FreefallBlock",
"TriggerConnection": "OR", "TriggerConnection": "OR",
"StopProcessWhenTriggered": true,
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "1h",
"MarketTrendRelation": "Absolute", "MarketTrendRelation": "Absolute",
"MaxChange": -5 "MaxChange": -5
} }
], ],
"PairsProperties": { "OffTriggers": [
"DEFAULT_trailing_profit_OFFSETPERCENT": -10, {
"DEFAULT_A_sell_value_OFFSETPERCENT": -30, "HoursSinceTriggered": 1
}
],
"PairsProperties": {
"DEFAULT_sell_only_mode_enabled": true, "DEFAULT_sell_only_mode_enabled": true,
"DEFAULT_DCA_enabled": false "DEFAULT_DCA_enabled": false
} }

View File

@ -1,79 +1,263 @@
//
// 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": { "AnalyzerSettings": {
"MarketAnalyzer": { "MarketAnalyzer": {
"StoreDataMaxHours": 24, // Number of hours to store market data "StoreDataMaxHours": 48, // Number of hours to store market data
"IntervalMinutes": 1, // 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 "ExcludeMainCurrency": true, // Excludes the main currency (for example BTC) from market trend analysis
"MarketTrends": [ "MarketTrends": [
{ {
"Name": "CMC24h", // UNIQUE market trend name (to be referenced by your triggers below) "Name": "15m", // UNIQUE market trend name (to be referenced by your triggers below)
"Platform": "CoinMarketCap", // Platform to grab prices from (Allowed values are: CoinMarketCap, Exchange) "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": 1440 // Number of minutes to build a trend (1440 = 24h, 720 = 12h, 60 = 1h) "TrendMinutes": 15, // 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.
// (Allowed values are: Fiat, Market)
"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": "Exchange1h", "Name": "1h",
"Platform": "Exchange", "Platform": "Exchange",
"MaxMarkets": 50, "MaxMarkets": 50,
"TrendMinutes": 60, "TrendMinutes": 60,
"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. (Allowed values are: Fiat, Market) "TrendCurrency": "Market",
"DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
}, },
{ {
"Name": "Exchange12h", "Name": "6h",
"Platform": "Exchange",
"MaxMarkets": 50,
"TrendMinutes": 360,
"TrendCurrency": "Market",
"DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
},
{
"Name": "12h",
"Platform": "Exchange", "Platform": "Exchange",
"MaxMarkets": 50, "MaxMarkets": 50,
"TrendMinutes": 720, "TrendMinutes": 720,
"TrendCurrency": "Market" "TrendCurrency": "Market",
"DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
}, },
{ {
"Name": "Exchange24h", "Name": "24h",
"Platform": "Exchange", "Platform": "Exchange",
"MaxMarkets": 50, "MaxMarkets": 50,
"TrendMinutes": 1440, "TrendMinutes": 1440,
"TrendCurrency": "Market" "TrendCurrency": "Market",
"DisplayGraph": true,
"DisplayOnMarketAnalyzerList": true
} }
] ]
}, },
// ================================ GLOBAL SETTINGS ================================
//
"GlobalSettings": [ // Global settings for Profit Trailer properties "GlobalSettings": [ // Global settings for Profit Trailer properties
//
// -----------------------------
{ {
"SettingName": "EndOfTheWorld", // UNIQUE name of your setting "SettingName": "EndOfTheWorld", // ANY UNIQUE name of your setting
"TriggerConnection": "AND", // Define if triggers will be connected by AND or OR "TriggerConnection": "AND", // Define if triggers will be connected by AND or OR
"Triggers": [ // Your triggers for this setting "Triggers": [ // Your triggers for this setting. You can use any of your defined trends from above
{ {
"MarketTrendName": "Exchange12h", // Reference to the market trend specified above "MarketTrendName": "1h", // Reference to the market trend specified above
"MaxChange": -1 // Maximum trend change % for this setting to get triggered "MaxChange": 0 // The maximum value for this trigger to be true. (Any value below "0" will trigger this)
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "12h",
"MaxChange": -2
},
{
"MarketTrendName": "24h",
"MaxChange": -5 "MaxChange": -5
} }
], ],
"PairsProperties": { // Properties for PAIRS.PROPERTIES "PairsProperties": { // Properties for PAIRS.PROPERTIES
"DEFAULT_sell_only_mode_enabled": true // Any valid setting from https://wiki.profittrailer.com/doku.php?id=pairs.properties 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": { // Properties for DCA.PROPERTIES
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -75
} }
}, },
// -----------------------------
{
"SettingName": "TankingDown",
"TriggerConnection": "AND",
"Triggers": [
{
"MarketTrendName": "15m",
"MaxChange": 0
},
{
"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", "SettingName": "Default",
"PairsProperties": { "PairsProperties": {
"File": "PAIRS.PROPERTIES" "File": "PAIRS.properties"
}, },
"DCAProperties": { "DCAProperties": {
"File": "DCA.PROPERTIES" "File": "DCA.properties"
}, },
"IndicatorsProperties": { "IndicatorsProperties": {
"File": "INDICATORS.PROPERTIES" "File": "INDICATORS.properties"
} }
} }
], ],
// ================================ COIN-SPECIFIC SETTINGS ================================
//
"SingleMarketSettings": [ // Single market/pair settings for Profit Trailer properties "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.
{ {
"SettingName": "BlacklistNewCoins", "SettingName": "BlacklistCoins",
"StopProcessWhenTriggered": true, "StopProcessWhenTriggered": true,
"Triggers": [ "Triggers": [
{ {
"AgeDaysLowerThan": 14 "AgeDaysLowerThan": 21
} }
], ],
"PairsProperties": { "PairsProperties": {
@ -82,46 +266,33 @@
"DEFAULT_DCA_enabled": false "DEFAULT_DCA_enabled": false
} }
}, },
// -----------------------------
{ {
"SettingName": "PumpNDumpProtection", "SettingName": "PumpNDumpProtection",
"TriggerConnection": "OR", "TriggerConnection": "OR",
"OffTriggerConnection": "OR",
"StopProcessWhenTriggered": true,
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "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 viewn on its own "MarketTrendRelation": "Relative", // The relation of the single market trend. Relative = Single market
"MinChange": 5 // trend compared relative to the market trend
// Absolute = Single market trend viewed on its own
"MinChange": 8
}, },
{ {
"MarketTrendName": "Exchange12h", "MarketTrendName": "12h",
"MarketTrendRelation": "Relative", "MarketTrendRelation": "Relative",
"MinChange": 7 "MinChange": 10
}, },
{ {
"MarketTrendName": "Exchange24h", "MarketTrendName": "24h",
"MarketTrendRelation": "Relative", "MarketTrendRelation": "Relative",
"MinChange": 7 "MinChange": 12
} }
], ],
"OffTriggers": [ "OffTriggers": [
{ {
"MarketTrendName": "Exchange1h", "HoursSinceTriggered": 3 // Any coin that triggers this setting, will remain under this setting
"MarketTrendRelation": "RelativeTrigger", // for 3 hours, since the last time it triggered.
"MaxChange": -4
},
{
"MarketTrendName": "Exchange12h",
"MarketTrendRelation": "RelativeTrigger",
"MaxChange": -5
},
{
"MarketTrendName": "Exchange24h",
"MarketTrendRelation": "RelativeTrigger",
"MaxChange": -5
},
{
"HoursSinceTriggered": 48
} }
], ],
"PairsProperties": { "PairsProperties": {
@ -129,225 +300,25 @@
"DEFAULT_DCA_enabled": false "DEFAULT_DCA_enabled": false
} }
}, },
// -----------------------------
{ {
"SettingName": "FreefallBlock", "SettingName": "FreefallBlock",
"TriggerConnection": "OR", "TriggerConnection": "OR",
"OffTriggerConnection": "OR",
"StopProcessWhenTriggered": true,
"Triggers": [ "Triggers": [
{ {
"MarketTrendName": "Exchange1h", "MarketTrendName": "1h",
"MarketTrendRelation": "Absolute",
"MaxChange": -8
}
],
"OffTriggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "RelativeTrigger",
"MinChange": 6
},
{
"HoursSinceTriggered": 24
}
],
"PairsProperties": {
"DEFAULT_trailing_profit_OFFSETPERCENT": -10,
"DEFAULT_A_sell_value_OFFSETPERCENT": -50,
"DEFAULT_sell_only_mode_enabled": true,
"DEFAULT_DCA_enabled": false
}
},
{
"SettingName": "StraightToHell",
"TriggerConnection": "AND",
"StopProcessWhenTriggered": true,
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "Absolute",
"MaxChange": -1
},
{
"MarketTrendName": "Exchange12h",
"MarketTrendRelation": "Absolute",
"MaxChange": -3
},
{
"MarketTrendName": "Exchange24h",
"MarketTrendRelation": "Absolute", "MarketTrendRelation": "Absolute",
"MaxChange": -5 "MaxChange": -5
} }
], ],
"PairsProperties": { "OffTriggers": [
{
"HoursSinceTriggered": 1
}
],
"PairsProperties": {
"DEFAULT_sell_only_mode_enabled": true, "DEFAULT_sell_only_mode_enabled": true,
"DEFAULT_trailing_profit_OFFSETPERCENT": -75, "DEFAULT_DCA_enabled": false
"DEFAULT_A_sell_value_OFFSETPERCENT": -50
},
"DCAProperties": {
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -75,
"DEFAULT_DCA_A_sell_value_OFFSETPERCENT": -50
}
},
{
"SettingName": "StrongDownTrend",
"TriggerConnection": "AND",
"StopProcessWhenTriggered": true,
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "Absolute",
"MaxChange": 1
},
{
"MarketTrendName": "Exchange12h",
"MarketTrendRelation": "Absolute",
"MaxChange": 0
},
{
"MarketTrendName": "Exchange24h",
"MarketTrendRelation": "Absolute",
"MaxChange": -3,
"MinChange": -5
}
],
"PairsProperties": {
"DEFAULT_A_buy_value_OFFSETPERCENT": -100,
"DEFAULT_B_buy_value_OFFSETPERCENT": -15,
"DEFAULT_trailing_buy_OFFSETPERCENT": 20,
"DEFAULT_trailing_profit_OFFSETPERCENT": -75,
"DEFAULT_A_sell_value_OFFSETPERCENT": -30
},
"DCAProperties": {
"DEFAULT_DCA_trailing_buy_OFFSETPERCENT": -75,
"DEFAULT_DCA_A_sell_value_OFFSETPERCENT": -30
}
},
{
"SettingName": "WeakDownTrend",
"TriggerConnection": "AND",
"StopProcessWhenTriggered": true,
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "Absolute",
"MaxChange": 1
},
{
"MarketTrendName": "Exchange12h",
"MarketTrendRelation": "Absolute",
"MaxChange": 0
},
{
"MarketTrendName": "Exchange24h",
"MarketTrendRelation": "Absolute",
"MaxChange": -1,
"MinChange": -3
}
],
"PairsProperties": {
"DEFAULT_A_buy_value_OFFSETPERCENT": -50,
"DEFAULT_B_buy_value_OFFSETPERCENT": -7,
"DEFAULT_trailing_profit_OFFSETPERCENT": -50,
"DEFAULT_A_sell_value_OFFSETPERCENT": -20
},
"DCAProperties": {
"DEFAULT_DCA_trailing_profit_OFFSETPERCENT": -50,
"DEFAULT_DCA_A_sell_value_OFFSETPERCENT": -20
}
},
{
"SettingName": "WeakUpTrend",
"TriggerConnection": "AND",
"StopProcessWhenTriggered": true,
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "Absolute",
"MinChange": -1
},
{
"MarketTrendName": "Exchange12h",
"MarketTrendRelation": "Absolute",
"MinChange": 0
},
{
"MarketTrendName": "Exchange24h",
"MarketTrendRelation": "Absolute",
"MinChange": 1,
"MaxChange": 3
}
],
"PairsProperties": {
"DEFAULT_A_buy_value_OFFSETPERCENT": 10,
"DEFAULT_B_buy_value_OFFSETPERCENT": 10,
"DEFAULT_A_sell_value_OFFSETPERCENT": 20
},
"DCAProperties": {
"DEFAULT_DCA_A_sell_value_OFFSETPERCENT": 20
}
},
{
"SettingName": "StrongUpTrend",
"TriggerConnection": "AND",
"StopProcessWhenTriggered": true,
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "Absolute",
"MinChange": -1
},
{
"MarketTrendName": "Exchange12h",
"MarketTrendRelation": "Absolute",
"MinChange": 1
},
{
"MarketTrendName": "Exchange24h",
"MarketTrendRelation": "Absolute",
"MinChange": 3,
"MaxChange": 5
}
],
"PairsProperties": {
"DEFAULT_A_buy_value_OFFSETPERCENT": 30,
"DEFAULT_B_buy_value_OFFSETPERCENT": 30,
"DEFAULT_trailing_buy_OFFSETPERCENT": -50,
"DEFAULT_A_sell_value_OFFSETPERCENT": 30
},
"DCAProperties": {
"DEFAULT_DCA_A_sell_value_OFFSETPERCENT": 30
}
},
{
"SettingName": "ToTheMoon",
"TriggerConnection": "AND",
"StopProcessWhenTriggered": true,
"Triggers": [
{
"MarketTrendName": "Exchange1h",
"MarketTrendRelation": "Absolute",
"MinChange": 0
},
{
"MarketTrendName": "Exchange12h",
"MarketTrendRelation": "Absolute",
"MinChange": 1
},
{
"MarketTrendName": "Exchange24h",
"MarketTrendRelation": "Absolute",
"MinChange": 5
}
],
"PairsProperties": {
"DEFAULT_A_buy_value_OFFSETPERCENT": 30,
"DEFAULT_B_buy_value_OFFSETPERCENT": 30,
"DEFAULT_trailing_buy_OFFSETPERCENT": -50,
"DEFAULT_A_sell_value_OFFSETPERCENT": 40
},
"DCAProperties": {
"DEFAULT_DCA_A_sell_value_OFFSETPERCENT": 40
} }
} }
] ]

View File

@ -2,7 +2,7 @@
"GeneralSettings": { "GeneralSettings": {
"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": true, // If TestMode is active, no properties files will be changed "TestMode": false, // If TestMode is active, no properties files will be changed
"ProfitTrailerMajorVersion": 2, // Major version of your Profit Trailer (If you are using 1.2.x the major version is "1", if you are using 2.x the major version is "2" and so on) "ProfitTrailerMajorVersion": 2, // Major version of your Profit Trailer (If you are using 1.2.x the major version is "1", if you are using 2.x the major version is "2" and so on)
"ProfitTrailerPath": "YOUR PROFIT TRAILER PATH", // Path to your Profit Trailer main directory (use double backslashes for windows like C:\\ProfitTrailer\\) "ProfitTrailerPath": "YOUR PROFIT TRAILER PATH", // Path to your Profit Trailer main directory (use double backslashes for windows like C:\\ProfitTrailer\\)
"ProfitTrailerLicense": "YOUR PROFIT TRAILER LICENSE KEY", // Your Profit Trailer license key (needed to change your settings for PT 2.0 and above) "ProfitTrailerLicense": "YOUR PROFIT TRAILER LICENSE KEY", // Your Profit Trailer license key (needed to change your settings for PT 2.0 and above)
@ -14,12 +14,12 @@
"MainFiatCurrency": "USD", // Your main fiat currency that will be used in the monitor "MainFiatCurrency": "USD", // Your main fiat currency that will be used in the monitor
"AlwaysLoadDefaultBeforeSwitch": true, // If this is enabled, PTMagic will always load default settings before switching to another setting "AlwaysLoadDefaultBeforeSwitch": true, // If this is enabled, PTMagic will always load default settings before switching to another setting
"FloodProtectionMinutes": 15, // If a price trend is just zig-zagging around its trigger, you may want to protect your settings from getting switched back and forth every minute "FloodProtectionMinutes": 15, // If a price trend is just zig-zagging around its trigger, you may want to protect your settings from getting switched back and forth every minute
"InstanceName": "PT Magic Development", // The name of the instance of this bot. This will be used in your monitor and your Telegram messages. In case you are running more than one bot, you may set different names to separate them "InstanceName": "PT Magic", // The name of the instance of this bot. This will be used in your monitor and your Telegram messages. In case you are running more than one bot, you may set different names to separate them
"CoinMarketCapAPIKey": "" //CoinMarketCap ApiKey "CoinMarketCapAPIKey": "" //CoinMarketCap Api
}, },
"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": true, // 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": 5000, // The port you want to run your monitor on
"RootUrl": "/", // The root Url of your monitor "RootUrl": "/", // The root Url of your monitor
"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

View File

@ -0,0 +1,23 @@
@echo off
:start
cls
echo PTMagic Git Commands
echo The following Commands are available:
echo 1: Sync current Branch with Main Repo(This will remove all changes you made!)
SET /P Input= Please enter an input(1):
IF "%Input%" == "1" GOTO :sync
GOTO :start
:sync
git remote add upstream https://github.com/PTMagicians/PTMagic.git
git fetch upstream
git checkout develop
git reset --hard upstream/develop
git push origin develop --force
git pull origin develop
GOTO :end
:end
pause

View File

@ -3,17 +3,17 @@
"UseTabs": false, "UseTabs": false,
"TabSize": 2, "TabSize": 2,
"IndentationSize": 2, "IndentationSize": 2,
"NewLinesForBracesInTypes": false, "NewLinesForBracesInTypes": true,
"NewLinesForBracesInMethods": false, "NewLinesForBracesInMethods": true,
"NewLinesForBracesInProperties": false, "NewLinesForBracesInProperties": true,
"NewLinesForBracesInAccessors": false, "NewLinesForBracesInAccessors": true,
"NewLinesForBracesInAnonymousMethods": false, "NewLinesForBracesInAnonymousMethods": true,
"NewLinesForBracesInControlBlocks": false, "NewLinesForBracesInControlBlocks": true,
"NewLinesForBracesInAnonymousTypes": false, "NewLinesForBracesInAnonymousTypes": true,
"NewLinesForBracesInObjectCollectionArrayInitializers": false, "NewLinesForBracesInObjectCollectionArrayInitializers": true,
"NewLinesForBracesInLambdaExpressionBody": false, "NewLinesForBracesInLambdaExpressionBody": true,
"NewLineForElse": false, "NewLineForElse": true,
"NewLineForCatch": false, "NewLineForCatch": true,
"NewLineForFinally": false "NewLineForFinally": true
} }
} }