zawy12 / difficulty-algorithms

See the Issues for difficulty algorithms
MIT License
108 stars 25 forks source link

Dynamic EMA difficulty algorithm #5

Open zawy12 opened 6 years ago

zawy12 commented 6 years ago

This keeps a really smooth difficulty by defaulting to a large N, but switches to a smaller N if there is a sudden >3x increase or <1/3 decrease in hashrate. It may be that the basic EMA with N=70 is generally just as good for all coins. N here is in a e^(-2/N) formula instead of e^(-1/N).

# Dynamic EMA difficulty algo (Jacob Eliosoff's EMA and Zawy's adjustable window). 
# Bitcoin cash dev(?) came up with the median of three to reduce timestamp errors.
# "Dynamic" means it triggers to a faster-responding value for N if a substantial change in hashrate
# is detected. It increases from that event back to Nmax

Nmax=140 # max EMA window
Nmin=50 # min EMA window
A=11, B=2.1, C=0.36  # A,B,C = 11,2.1,0.36 or 20, 1.65 0.45, 

# TS=timestamp, T=target solvetime, i.e. 600 seconds
# Find the most recent unusual event in the past 20 blocks event
for (i=height-Nmax; i < height; i++) {  # height - 1 = most recently solved block
    if ( (median(TS[i],TS[i-1],TS[i-2]) - median(TS[i-A],TS[i-A-1],TS[i-A-2]))/T/A  > B 
           or  
         (median(TS[i],TS[i-1],TS[i-2]) - median(TS[i-A],TS[i-A-1],TS[i-A-2]))/T/A  < C  ) 
      {   unusual_event= i-height+1+Nmin   } 
}
N = min(Nmax, unusual_event))

# now do the EMA-Z with this N. See link below:

See EMA-Z algorithm for the rest of the algorithm.

Another dynamic window idea I want to test and specify here triggers on a more advanced and more responsive rule. The above has a problem: it needs 20 blocks out of fear of timestamp manipulation. The statistical check could be more precise and flexible. I'm thinking along the lines of: For past i= 3 to N/2 blocks, check if the sumST of each "i" is above or below the (say) 1% level of expectation. It has to be done carefully. For example, getting only 3 when we expect 10 occurs 1% of time. "Out of the time" means per group of 10 blocks. How does a rolling check on this figure into it if the 10 should be a random selection? But it appears it would be triggered 1 per 1000 blocks. Let's jump ahead to i=7 and I see this few may occur in 16xT at the 1% level...but it's in 16xT blocks, so it occurs 1 per 1600. To get 1 in 1000 again, I need i=7 or less in time 15.3xT. It looks like a lot of work and trial and error to get the constants for each "i", but it might work a lot better than the above.