Updates market averages

This commit is contained in:
Ben 2024-04-22 14:27:09 +02:00
parent d3390892af
commit 2f6256756a
No known key found for this signature in database
GPG Key ID: 541B9D8C9F1426A1
4 changed files with 49 additions and 89 deletions

View File

@ -15,8 +15,7 @@
public class MarketAverage
{
public int NumberOfFinished { get; set; }
public int TimeRangeSeconds { get; set; }
public string Title { get; set; } = string.Empty;
public float Price { get; set; }
public float Size { get; set; }
public float Duration { get; set; }

View File

@ -1,7 +1,6 @@
using BiblioTech.Options;
using DiscordRewards;
using System.Globalization;
using Utils;
namespace BiblioTech.Commands
{
@ -31,13 +30,7 @@ namespace BiblioTech.Commands
private string[] GetInsight(MarketAverage avg)
{
var timeRange = TimeSpan.FromSeconds(avg.TimeRangeSeconds);
var headerLine = $"[Last {Time.FormatDuration(timeRange)}] ({avg.NumberOfFinished} Contracts finished)";
if (avg.NumberOfFinished == 0)
{
return new[] { headerLine };
}
var headerLine = $"[{avg.Title}]";
return new[]
{

View File

@ -19,9 +19,6 @@ namespace TestNetRewarder
[Uniform("check-history", "ch", "CHECKHISTORY", true, "Unix epoc timestamp of a moment in history on which processing begins. Required for hosting rewards. Should be 'launch of the testnet'.")]
public int CheckHistoryTimestamp { get; set; } = 0;
[Uniform("market-insights", "mi", "MARKETINSIGHTS", false, "Semi-colon separated integers. Each represents a multiple of intervals, for which a market insights average will be generated.")]
public string MarketInsights { get; set; } = "1;96";
[Uniform("events-overview", "eo", "EVENTSOVERVIEW", false, "When greater than zero, chain event summary will be generated. (default 1)")]
public int CreateChainEventsOverview { get; set; } = 1;

View File

@ -6,66 +6,47 @@ namespace TestNetRewarder
{
public class MarketTracker
{
private readonly List<ChainState> buffer = new List<ChainState>();
private readonly MarketAverage MostRecent = new MarketAverage
{
Title = "Most recent"
};
private readonly MarketAverage Irf = new MarketAverage
{
Title = "Recent average"
};
public MarketAverage[] ProcessChainState(ChainState chainState)
{
var intervalCounts = GetInsightCounts();
if (!intervalCounts.Any()) return Array.Empty<MarketAverage>();
UpdateMostRecent(chainState);
UpdateIrf(chainState);
UpdateBuffer(chainState, intervalCounts.Max());
var result = intervalCounts
.Select(GenerateMarketAverage)
.Where(a => a != null)
.Cast<MarketAverage>()
.ToArray();
if (!result.Any()) result = Array.Empty<MarketAverage>();
return result;
}
private void UpdateBuffer(ChainState chainState, int maxNumberOfIntervals)
return new[]
{
buffer.Add(chainState);
while (buffer.Count > maxNumberOfIntervals)
{
buffer.RemoveAt(0);
}
}
private MarketAverage? GenerateMarketAverage(int numberOfIntervals)
{
var states = SelectStates(numberOfIntervals);
return CreateAverage(states);
}
private ChainState[] SelectStates(int numberOfIntervals)
{
if (numberOfIntervals < 1) return Array.Empty<ChainState>();
if (numberOfIntervals > buffer.Count) return Array.Empty<ChainState>();
return buffer.TakeLast(numberOfIntervals).ToArray();
}
private MarketAverage? CreateAverage(ChainState[] states)
{
try
{
return new MarketAverage
{
NumberOfFinished = CountNumberOfFinishedRequests(states),
TimeRangeSeconds = GetTotalTimeRange(states),
Price = Average(states, s => s.Request.Ask.Reward),
Duration = Average(states, s => s.Request.Ask.Duration),
Size = Average(states, s => GetTotalSize(s.Request.Ask)),
Collateral = Average(states, s => s.Request.Ask.Collateral),
ProofProbability = Average(states, s => s.Request.Ask.ProofProbability)
MostRecent,
Irf
};
}
catch (Exception ex)
private void UpdateIrf(ChainState chainState)
{
Program.Log.Error($"Exception in CreateAverage: {ex}");
return null;
if (!chainState.FinishedRequests.Any()) return;
MostRecent.Price = GetIrf(MostRecent.Price, chainState, s => s.Request.Ask.Reward);
MostRecent.Duration = GetIrf(MostRecent.Duration, chainState, s => s.Request.Ask.Duration);
MostRecent.Size = GetIrf(MostRecent.Size, chainState, s => GetTotalSize(s.Request.Ask));
MostRecent.Collateral = GetIrf(MostRecent.Collateral, chainState, s => s.Request.Ask.Collateral);
MostRecent.ProofProbability = GetIrf(MostRecent.ProofProbability, chainState, s => s.Request.Ask.ProofProbability);
}
private void UpdateMostRecent(ChainState chainState)
{
if (!chainState.FinishedRequests.Any()) return;
MostRecent.Price = Average(chainState, s => s.Request.Ask.Reward);
MostRecent.Duration = Average(chainState, s => s.Request.Ask.Duration);
MostRecent.Size = Average(chainState, s => GetTotalSize(s.Request.Ask));
MostRecent.Collateral = Average(chainState, s => s.Request.Ask.Collateral);
MostRecent.ProofProbability = Average(chainState, s => s.Request.Ask.ProofProbability);
}
private int GetTotalSize(Ask ask)
@ -75,50 +56,40 @@ namespace TestNetRewarder
return nSlots * slotSize;
}
private float Average(ChainState[] states, Func<StorageRequest, BigInteger> getValue)
private float Average(ChainState state, Func<StorageRequest, BigInteger> getValue)
{
return Average(states, s => Convert.ToInt32(getValue(s)));
return Average(state, s => Convert.ToInt32(getValue(s)));
}
private float Average(ChainState[] states, Func<StorageRequest, int> getValue)
private float GetIrf(float current, ChainState state, Func<StorageRequest, BigInteger> getValue)
{
return GetIrf(current, state, s => Convert.ToInt32(getValue(s)));
}
private float Average(ChainState state, Func<StorageRequest, int> getValue)
{
var sum = 0.0f;
var count = 0.0f;
foreach (var state in states)
{
foreach (var finishedRequest in state.FinishedRequests)
{
sum += getValue(finishedRequest);
count++;
}
}
if (count < 1.0f) return 0.0f;
return sum / count;
}
private int GetTotalTimeRange(ChainState[] states)
private float GetIrf(float current, ChainState state, Func<StorageRequest, int> getValue)
{
return Convert.ToInt32((Program.Config.Interval * states.Length).TotalSeconds);
var result = current;
foreach (var finishedRequest in state.FinishedRequests)
{
float v = getValue(finishedRequest);
result = (result + v) / 2.0f;
}
private int CountNumberOfFinishedRequests(ChainState[] states)
{
return states.Sum(s => s.FinishedRequests.Length);
}
private int[] GetInsightCounts()
{
try
{
var tokens = Program.Config.MarketInsights.Split(';').ToArray();
return tokens.Select(t => Convert.ToInt32(t)).ToArray();
}
catch (Exception ex)
{
Program.Log.Error($"Exception when parsing MarketInsights config parameters: {ex}");
}
return Array.Empty<int>();
return result;
}
}
}