public WtmData Clone() { var _new = new WtmData(); //_new.Coin = this.Coin; _new.DefaultHashrate = this.DefaultHashrate; _new.Json = new Dictionary <string, string>(); foreach (var entry in this.Json) { _new.Json.Add(entry.Key, entry.Value); } _new.HasAverage = this.HasAverage; _new.AverageDays = this.AverageDays; _new.AveragePrice = this.AveragePrice; return(_new); }
// Calculate historical averages in wtmDataDict from historical data of historicalData public void GetHistoricalAverages(Dictionary <string, WtmData> wtmDataDict, List <HistoricalData> historicalData) { if (wtmDataDict == null || wtmDataDict.Count == 0 || historicalData == null || historicalData.Count == 0) { return; } var historyCount = historicalData.Count; foreach (var coin in wtmDataDict) { decimal priceAccum = 0; bool coinAverageSuccess = true; var date = DateTime.Now.Date; foreach (var day in historicalData) { Debug.WriteLine("Loop round " + historicalData.IndexOf(day)); if (day.Date.Date != date) { coinAverageSuccess = false; break; } WtmData historicalRecord = null; day.PriceData.TryGetValue(coin.Key, out historicalRecord); if (historicalRecord != null) { var tmpPrice = Helpers.StringToDecimal(historicalRecord.Json["exchange_rate24"]); priceAccum += tmpPrice; } else { coinAverageSuccess = false; break; } date = date.Date.AddDays(-1); } if (coinAverageSuccess) { coin.Value.HasAverage = true; coin.Value.AverageDays = historyCount; coin.Value.AveragePrice = priceAccum / historyCount; } } }
public static (decimal profit24, decimal revenue) CalculateProfit( CoinTable coinTable, Dictionary <string, WtmData> wtmDataDict, WtmData btc, WtmSettingsObject settings, decimal powerCost ) { decimal revenueAllCoins = 0; revenueAllCoins = 0; decimal coinRate = 0; decimal btcRate = 0; foreach (Coin coin in coinTable.Coins) { WtmData currentCoin = null; wtmDataDict.TryGetValue(coin.Name, out currentCoin); if (currentCoin == null) { continue; } if (settings.UseHistoricalAverage && currentCoin.HasAverage) { coinRate = currentCoin.AveragePrice; btcRate = btc != null ? btc.AveragePrice : 0; } else { string keyName; if (settings.Average24) { keyName = "exchange_rate24"; } else { keyName = "exchange_rate"; } string coinValue; currentCoin.Json.TryGetValue(keyName, out coinValue); if (coinValue != null) { coinRate = Helpers.StringToDecimal(coinValue); } string btcValue = null; btc?.Json.TryGetValue(keyName, out btcValue); if (btcValue != null) { btcRate = Helpers.StringToDecimal(btcValue); } } decimal ratio = (decimal)coin.Hashrate / (decimal)currentCoin.DefaultHashrate; decimal revenueOneCoin = 0; decimal estimatedRewards = Helpers.StringToDecimal(currentCoin.Json["estimated_rewards"]); revenueOneCoin = ratio * estimatedRewards * coinRate * btcRate; revenueAllCoins += revenueOneCoin; //totalHashrate += Convert.ToString(coin.Hashrate, CultureInfo.InvariantCulture) + "+"; //name += coin.Name + "+"; //algorithm += currentCoin.Json["algorithm"] + "+"; } decimal profit24 = 0; //name = name.TrimEnd('+'); profit24 = revenueAllCoins - (revenueAllCoins * (decimal)coinTable.Fees / 100) - (((decimal)coinTable.Power / 1000) * 24 * powerCost); return(profit24, revenueAllCoins); }
private void LoadHistoricalChartsCommand(object obj) { DateTime FromDate; DateTime ToDate; using (var db = new LiteDatabase(Constants.DataBase)) { Helpers.MouseCursorWait(); var collection = db.GetCollection <HistoricalData>(Constants.LightDB_HistoricalDataCollection); var allDays = collection.FindAll(); if (allDays.Count() == 0) { MessageBox.Show("The historical prices database is empty. Set up 'Accumulate Historical Prices', collect some stats for a while and return then.", "Nothing to show", MessageBoxButton.OK, MessageBoxImage.Warning); Helpers.MouseCursorNormal(); return; } var selectDatesWindow = new SelectDateRange(); var viewModel = new SelectDateRangeVM(allDays.First().Date, allDays.Last().Date); selectDatesWindow.DataContext = viewModel; Helpers.MouseCursorNormal(); var dialogResult = selectDatesWindow.ShowDialog(); if (dialogResult == false) { return; } FromDate = viewModel.FromDate; ToDate = viewModel.ToDate; } var workersChecked = Workers.WorkerList.Where(w => w.Query).ToList(); var historicalCharts = new Dictionary <string, HistoricalChart>(); // Create a chart for each worker foreach (var worker in workersChecked) { //var coinListFullName = Workers.GetCoins(new List<Worker> { worker }, false, false, true); var chart = new HistoricalChart { Name = worker.Name, Description = worker.Description, Computers = new ObservableCollection <string>(worker.Computers), Coins = new ObservablePairCollection <string, ChartCoin>(), PlotModel = new PlotModel(), DisplayCoinAs = Workers.DisplayCoinAs }; chart.HookUpCoinsCollectionChanged(); // Add AutoSwitch "coin" chart.Coins.Add("0, AutoSwitch", new ChartCoin { Color = OxyColors.Red.ToBrush(), IsChecked = true, Name = "AutoSwitch", Symbol = "AutoSwitch" }); var serie = new LineSeries { StrokeThickness = 2, MarkerSize = 3, Color = OxyColors.Red, MarkerType = MarkerType.Circle, CanTrackerInterpolatePoints = false, Title = "AutoSwitch", Smooth = false, Tag = 0 }; chart.PlotModel.Series.Add(serie); // Add real coins int index = 1; foreach (var coinTable in worker.CoinList) { var lockExpiry = FromDate.Date.Date.AddHours(WtmSettings.DelayNextSwitchTime); var oxyColor = ChartColors.Colors[chart.PlotModel.Series.Count % ChartColors.Colors.Count]; chart.Coins.Add($"{index}, {coinTable.FullName}", new ChartCoin { Index = index, IsChecked = true, LockedUntil = lockExpiry, Color = oxyColor.ToBrush(), Name = coinTable.FullName, Symbol = coinTable.FullSymbol }); var newSerie = new LineSeries { StrokeThickness = 2, MarkerSize = 3, Color = oxyColor, MarkerType = MarkerType.Circle, CanTrackerInterpolatePoints = false, Title = coinTable.FullName, Smooth = false, Tag = index }; chart.PlotModel.Series.Add(newSerie); index++; } CultureInfo currentCulture = CultureInfo.GetCultureInfo(CultureInfo.CurrentCulture.ToString()); chart.PlotModel.Axes.Add(new DateTimeAxis { IsPanEnabled = true, IsZoomEnabled = false, Position = AxisPosition.Bottom, StringFormat = currentCulture.DateTimeFormat.ShortDatePattern, MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot, TextColor = ChartColors.DarkBlue, TicklineColor = ChartColors.DarkBlue, MajorGridlineColor = ChartColors.DarkBlue, MinorGridlineThickness = 0.9, AxislineThickness = 0.9, MajorGridlineThickness = 0.9, IntervalLength = 80 }); chart.PlotModel.Axes.Add(new LinearAxis { IsZoomEnabled = false, Position = AxisPosition.Left, Title = "Daily profit", Minimum = 0, TitleColor = ChartColors.DarkBlue, TextColor = ChartColors.DarkBlue, TicklineColor = ChartColors.DarkBlue, MajorGridlineColor = ChartColors.DarkBlue, MinorTicklineColor = ChartColors.DarkBlue, MinorGridlineColor = ChartColors.DarkBlue, MajorGridlineStyle = LineStyle.Solid, MinorGridlineStyle = LineStyle.Dot, AxislineThickness = 0.9, MinorGridlineThickness = 0.9, MajorGridlineThickness = 0.9, }); chart.PlotModel.IsLegendVisible = false; chart.PlotModel.PlotAreaBorderThickness = new OxyThickness(0.9, 0.9, 0.9, 0.9); chart.PlotModel.PlotAreaBorderColor = ChartColors.DarkBlue; chart.PlotModel.Padding = new OxyThickness(0, 10, 0, -10); chart.PlotModel.DefaultColors = ChartColors.Colors; historicalCharts.Add(worker.Name, chart); } //Fill PlotModel with data using (var db = new LiteDatabase(Constants.DataBase)) { var collection = db.GetCollection <HistoricalData>(Constants.LightDB_HistoricalDataCollection); var selectedDays = collection.Find(x => x.Date >= FromDate && x.Date <= ToDate); if (selectedDays.FirstOrDefault() == null) { MessageBox.Show("The time selection is missing actual records in database.", "ERROR", MessageBoxButton.OK, MessageBoxImage.Error); return; } DateTime previousDay = selectedDays.FirstOrDefault().Date.Date; foreach (var day in selectedDays) { // Check if there's a gap and fill the missing days with blank data var difference = (day.Date.Date - previousDay.Date).Days; if (difference > 1) { for (int i = 1; i <= difference - 1; i++) { foreach (var worker in workersChecked) { var index = 1; var chart = historicalCharts[worker.Name]; // The chart that corresponds to the worker chart.AutoSwitchCoinName = null; var serie = chart.PlotModel.Series.First() as LineSeries; var point = new DataPoint(DateTimeAxis.ToDouble(previousDay.Date.AddDays(i)), 0); serie.Points.Add(point); foreach (var coinTable in worker.CoinList) { serie = chart.PlotModel.Series.FirstOrDefault(x => (int)x.Tag == index) as LineSeries; point = new DataPoint(DateTimeAxis.ToDouble(previousDay.Date.AddDays(i)), 0); serie.Points.Add(point); index++; } } } } WtmData btc = null; day.PriceData.TryGetValue("Bitcoin", out btc); foreach (var worker in workersChecked) { var chart = historicalCharts[worker.Name]; // The chart that corresponds to the worker var AutoSwitchPseudoCoin = chart.Coins["0, AutoSwitch"]; var index = 1; foreach (var coinTable in worker.CoinList) { var currentChartCoin = chart.Coins[$"{index}, {coinTable.FullName}"]; if (currentChartCoin.Accumulator == null) { currentChartCoin.Accumulator = new Accumulator(coinTable.Coins); } // Calculate profit var profitResult = WhatToMine.CalculateProfit(coinTable, day.PriceData, btc, WtmSettings, (decimal)Workers.PowerCost); decimal profit24 = profitResult.profit24; currentChartCoin.TodaysProfit = profit24; // Accumulate daily reward foreach (var coin in coinTable.Coins) { if (day.PriceData.ContainsKey(coin.Name)) { decimal ratio = (decimal)coin.Hashrate / (decimal)day.PriceData[coin.Name].DefaultHashrate; var dayReward = Helpers.StringToDecimal(day.PriceData[coin.Name].Json["estimated_rewards"]) * ratio; // Daily reward in mined coin dayReward -= dayReward * (decimal)coinTable.Fees / 100; // Deduct fees currentChartCoin.Accumulator.AddValue(coin.Name, dayReward); } else { currentChartCoin.Accumulator.AddValue(coin.Name, 0); } } currentChartCoin.PowerAccumulator += coinTable.Power / 1000 * 24; // Accumulate daily power consumption // Sell accumulated reward if lock is expired bool invalidateCoin = false; if (day.Date.Date >= currentChartCoin.LockedUntil.Date) { decimal btcRate = 0; if (WtmSettings.Average24) { btcRate = btc != null?Helpers.StringToDecimal(btc.Json["exchange_rate24"]) : 0; } else { btcRate = btc != null?Helpers.StringToDecimal(btc.Json["exchange_rate"]) : 0; } foreach (var coin in currentChartCoin.Accumulator.CoinList) { if (day.PriceData.ContainsKey(coin.Name)) { var coinRate = WtmSettings.Average24 ? Helpers.StringToDecimal(day.PriceData[coin.Name].Json["exchange_rate24"]) : Helpers.StringToDecimal(day.PriceData[coin.Name].Json["exchange_rate"]); var revenue = coin.Value * coinRate * btcRate; currentChartCoin.TotalProfit += revenue; if (chart.AutoSwitchCoinName == coinTable.FullName) { AutoSwitchPseudoCoin.TotalProfit += revenue; } } else { invalidateCoin = true; } } if (!invalidateCoin) { var powerExpense = (decimal)(currentChartCoin.PowerAccumulator * Workers.PowerCost); currentChartCoin.TotalProfit -= powerExpense; if (chart.AutoSwitchCoinName == coinTable.FullName) { AutoSwitchPseudoCoin.TotalProfit -= powerExpense; } } currentChartCoin.Accumulator.Clear(); currentChartCoin.PowerAccumulator = 0; currentChartCoin.LockedUntil = day.Date.Date.AddHours(WtmSettings.DelayNextSwitchTime); } // Add a new point for this day to the Graph var point = new DataPoint(DateTimeAxis.ToDouble(day.Date), (double)profit24); var serie = chart.PlotModel.Series.FirstOrDefault(x => (int)x.Tag == index) as LineSeries; if (serie != null) { serie.Points.Add(point); } index++; }// foreach CoinTable ChartCoin currentAutoSwitchCoin = null; if (chart.AutoSwitchCoinName != null) { currentAutoSwitchCoin = chart.Coins[chart.AutoSwitchCoinName]; } // AutoSwitch emulator if (day.Date.Date >= AutoSwitchPseudoCoin.LockedUntil.Date) { var mostProfitableCoin = chart.GetMostProfitableCoin(); decimal maxProfit = mostProfitableCoin.Value != null ? mostProfitableCoin.Value.TodaysProfit : 0; if (chart.AutoSwitchCoinName == null) { chart.AutoSwitchCoinName = mostProfitableCoin.Key != null ? mostProfitableCoin.Key : null; //AutoSwitchPseudoCoin.TotalProfit = mostProfitableCoin.Value != null ? mostProfitableCoin.Value.TotalProfit : 0; currentAutoSwitchCoin = chart.AutoSwitchCoinName != null ? chart.Coins[chart.AutoSwitchCoinName] : null; } var currentProfit = chart.AutoSwitchCoinName != null ? chart.Coins[chart.AutoSwitchCoinName].TodaysProfit : 0; if (maxProfit > (currentProfit + (currentProfit * WtmSettings.PriceMargin / 100))) // Switch coin in new profit is higher { chart.AutoSwitchCoinName = mostProfitableCoin.Key != null ? mostProfitableCoin.Key : null; AutoSwitchPseudoCoin.LockedUntil = day.Date.Date.AddHours(WtmSettings.DelayNextSwitchTime); } } var currentAutoSwitchCoinProfit = currentAutoSwitchCoin != null ? currentAutoSwitchCoin.TodaysProfit : 0; AutoSwitchPseudoCoin.TotalProfit += currentAutoSwitchCoinProfit; var autoSwitchPoint = new DataPoint(DateTimeAxis.ToDouble(day.Date), (double)currentAutoSwitchCoinProfit); var autoSwitchSerie = chart.PlotModel.Series.First() as LineSeries; autoSwitchSerie.Points.Add(autoSwitchPoint); } // foreach Worker previousDay = day.Date.Date; }// foreach days } HistoricalCharts.Clear(); foreach (var chart in historicalCharts) { HistoricalCharts.Add(chart.Value); } HistoricalChartsEnabled = true; Helpers.MouseCursorWait(); }