Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] collective_kappa: using the median staking duration to modify the reward coefficient #3

Open
wants to merge 6 commits into
base: collective_kappa
Choose a base branch
from

Conversation

arjunhassard
Copy link
Member

Idea for a new economic mechanism: a self-correcting reward coefficient ("collective_kappa"), determined by the collective decisions of other stakers with respect to the median duration of their staking commitment.


#### Problem ####

Currently, stakers choose to lock their NU tokens for a variety of durations, in units of month. The staker's inflation-based rewards are are modified by the reward coefficient 'kappa', which can be any of 12 discrete figures between 0.54 (= 1 month lock) and 1.0 (>= 12 months lock) – 0.54, 0.58, 0.63, etc. The longer you commit your stake, the higher the coefficient.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not rounded off to months actually, so can well be 1.05 months


#### Input variable: T_med ####

What is the input variable with which to modify our reward coefficient? There are actually a number of possibilities here – since stakers can theoretically divide their stake into as many durations as the number of tokens they own, the overall distribution of stake durations is rather complex. However, a simple approach is to line up all the tokens already staked by their individual duration attribute (from 1 to <12). For now, we can ignore who owns the token or how long their other tokens are staked for. From this two-column table it is straightforward to derive the median duration of all staked tokens. We will use this variable, T_med, as our input, which will always be in discrete units of month (e.g. T_med = 4 months).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want median or average?
I'd say that average is more relevant here (also easier to modify - it's obvious how it changes every day, as well as how it changes with every stake added)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not just average, but average weighted by stake.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 on weighted average by stake.

Median would imply we are trying to ensure 50% of nodes are "shorter-term" and 50% of nodes are "longer-term" - it's not clear that this is what we want.

T_max = 12

def calc_c_kappa(T_med, T_s):
if T_s > T_med:
Copy link

@michwill michwill Apr 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't both branches of if the same if small_stake_multiplier = 1/2? Why if then?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left the (currently redundant) if statement to illustrate the option of configuring the output of the reward coefficient to be asymmetrical around the multiplier, for example an exponentially increasing coefficient for every month longer than the median (or average) you choose for your duration, and/or a constant coefficient (e.g. 0.25) for all durations chose to be shorter than the median.

| T_s: 12 | 0.96 | 0.92 | 0.88 | 0.83 | 0.79 | 0.75 | 0.71 | 0.67 | 0.63 | 0.58 | 0.54 | 0.50 |


![Visualised outputs in a scatter graph](collective_kappa_outputs.png)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, basically the whole graph is linear and shifted down by T_med / (2 * 12 months): if T_med = 0 it's linear from 0.5 (at 0 months) to 1 (at 12 months), but at T_med = 12, it's going from 0 to 0.5.

As a result, if everyone is staking for a short time, it's not as punishable to stake for a short time (0.5 vs 1) than it is when everyone is staking for a long time (0 vs 0.5)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's right! As I mention at the end of the markdown doc and in my comment above, there's certainly room for improving this calculation.

However, one way to look at this - if T_med was actually 1 or 2 months, that would likely mean there were some very strong external factors convincing everyone against long term staking. In that instance, any group of stakers brave/committed enough to stake for 9, 10, 11 months should be rewarded handsomely for breaking away from the crowd (and dragging T_med up). Even someone staking for 3 or 4 months is 'contributing' to the network in this scenario.

I can see a possible issue in the reverse situation, where T_med is very high, and the incentive to stake short-term makes it almost pointless to do so, which could lead to a positive feedback loop of some kind where T_med keeps increasing. However, that begs the question, how important is short-term staking to the network? It's rather useless for many sharing use cases. I'm also not totally sure that short-term staking and token liquidity are highly correlated – my hunch is that some token holders will stake, and some will only trade, and short-term stakers (who maybe do both?) do not have a big impact on this dualism. This is where a community survey and/or address activity analysis would be very very helpful.




#### Expected Outcomes ####

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, I don't see how is this mechanism achieving anything.
We want to prevent the abundance of short stakers, right? So, if there are too many short stakers, c_kappa will be around 0.5. So I'd quite comfortably sit and stake for a short time (losing only factor of 2).
We are yet to discover what's the preferred behaviour, but we know for sure that no one prefers zero compensation. So IMO what would make sense is quite opposite: when T_med=12 graph is for T_med=0, and T_med=0 is for T_med=12

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this a little harsh, for the following reasons:

  • The objective of this PR is to introduce self-correction for our duration-based reward coefficient. It's not easy to get every single aspect of it perfect the first time around – altering the exact calculation was always going to be a matter of debate within the team. I deliberately chose a relatively simple one to begin with to focus minds on the concept.
  • 'Losing only a factor of 2' for short staking is precisely what occurs in the current design. If you stake for 1 month, you get kappa = 0.54. Whereas with collective_kappa, this only true if most other stakers are staking for 1 month (which is unlikely). In all other scenarios, you get less than 0.5 for a 1 month stake. So if too many stakers 'sitting comfortably' and staking for a short time is a problematic consequence of only halving their earnings, then by this logic the current design is more problematic!
  • I understand the issue of possibly overly-rewarding stakers simply because others are choosing short durations. However, see my comment above: if T_med was actually 1 or 2 months, that would likely mean there were some very strong external factors convincing everyone against long term staking. For example, if the price of NU is depreciating and there are no fundamentals to suggest this trend will reverse. Reducing the reward further in that scenario may lead to an exodus from the network.
  • It's true that it's not as punishable to stake for a short time when others are also doing so. But this is ignoring the far greater carrot in that scenario – the highest coefficient one can earn is where others are staking for short times and you choose stake for a long time.

Copy link

@michwill michwill Apr 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the current design is more problematic in that case. However, that's why coefficients are not set in stone: could well be zero when T_s=0 and 1 when T_s>=T_max (and that's the most you can make out of current design).
Why I disagree with it is because if T_med ~= 1-2 month, then the incentive to stake longer is actually no more than in the current design.
In your scenario, when everyone stakes for a short time and you're staking for a long time, you're making x2 more, that's similar to what we had originally. Did you mean to do something like "if everyone is staking for a short time, the difference you make staking a long time is drastic"? In this case, the graphs should be swapped the other way around (e.g. if T_med~=0, the graph goes out of zero).

if T_s > T_med:
c_kappa = (min(T_s, T_max) - T_med) / float(T_max * 2) + small_stake_multiplier
else:
c_kappa = (1 + ((min(T_s, T_max) - T_med) / float(T_max))) / 2

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try removing the else branch and see what happens. It seems to me that it's the same result without it

Copy link

@michwill michwill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, see the comments, but I don't like it.
What's our goal here? I think, to kick out people out of comfortable staking for 1 month. The proposed method achieves the opposite.
IMO if we want to go this route, let's try to make it exactly opposite (reward is 0 if T_med~=0 and you're staking for 0 time). How would that look like?

Copy link

@michwill michwill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even better. Start from the graph, and how you want it to look like ideally. Then, figure out some analytical function which approximates main properties of that graph

Copy link

@michwill michwill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this, for example (and dashed line is approximation which is easier to implement in Solidity)
Example of kappa_c

Copy link

@michwill michwill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More than that. It could well be a cumulative normal distribution (with mean(Ts) for the center and std(Ts) for the width), approximated with linear clipped at the top (1) and bottom (0, or maybe some min_compensation.

The idea: if you are staking for longer than the herd, you get a significantly better compensation. If shorter - 0 or very minimal.

Copy link
Member

@mswilkison mswilkison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting idea. I do have an overarching concern (even with the existing design) over the complexity of our economic system. There's not an easy to grok number (e.g. 21M BTC, 1% tail inflation Grin, etc.) in NuCypher and it takes a fair amount of work to determine what your compensation will be. This complexity is something we might need to consider as a potential friction for people making the decision whether or not to stake.


#### Input variable: T_med ####

What is the input variable with which to modify our reward coefficient? There are actually a number of possibilities here – since stakers can theoretically divide their stake into as many durations as the number of tokens they own, the overall distribution of stake durations is rather complex. However, a simple approach is to line up all the tokens already staked by their individual duration attribute (from 1 to <12). For now, we can ignore who owns the token or how long their other tokens are staked for. From this two-column table it is straightforward to derive the median duration of all staked tokens. We will use this variable, T_med, as our input, which will always be in discrete units of month (e.g. T_med = 4 months).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not just average, but average weighted by stake.

@michwill
Copy link

michwill commented Apr 14, 2019

@mswilkison yes, I totally agree with that. I still believe that it should be incentivised to stake longer, however I wouldn't make the system too complex. So, perhaps, I'd rather keep it as it is now (maybe tuning the minimal "short staking" reward)

collective_kappa.md Outdated Show resolved Hide resolved
collective_kappa.md Outdated Show resolved Hide resolved

#### Input variable: T_med ####

What is the input variable with which to modify our reward coefficient? There are actually a number of possibilities here – since stakers can theoretically divide their stake into as many durations as the number of tokens they own, the overall distribution of stake durations is rather complex. However, a simple approach is to line up all the tokens already staked by their individual duration attribute (from 1 to <12). For now, we can ignore who owns the token or how long their other tokens are staked for. From this two-column table it is straightforward to derive the median duration of all staked tokens. We will use this variable, T_med, as our input, which will always be in discrete units of month (e.g. T_med = 4 months).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 on weighted average by stake.

Median would imply we are trying to ensure 50% of nodes are "shorter-term" and 50% of nodes are "longer-term" - it's not clear that this is what we want.

@arjunhassard
Copy link
Member Author

This is an interesting idea. I do have an overarching concern (even with the existing design) over the complexity of our economic system. There's not an easy to grok number (e.g. 21M BTC, 1% tail inflation Grin, etc.) in NuCypher and it takes a fair amount of work to determine what your compensation will be. This complexity is something we might need to consider as a potential friction for people making the decision whether or not to stake.

Just added a new calculation proposal which takes on some of the issues raised. Also added a graph of @michwill's suggestion for comparison.

With regard to increasing complexity, the good thing about a variable kappa (whether driven by collective preferences or static) is that it applies to everyone equally – in the sense that for a given staking duration, a given average staking duration, and a given stage in the inflation schedule, you will always get the same reward coefficient (which then must be applied to the size of your stake). Therefore these figures can be advertised on a community dashboard --- e.g. Today, the average staking duration is 7.4 months. Therefore, if you stake for 12 months, your reward coefficient will be 0.80, which translates into an effective inflation rate of X%, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants