Last active
January 4, 2016 08:49
-
-
Save justmoon/8597643 to your computer and use it in GitHub Desktop.
Demurrage currency code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Currently, we're using this currency code format (from ripple.com/wiki/Currency_format): | |
00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ | |
ZERO------------------------------- CURCODE- VER-- RESERVED | |
Let's define the first byte as the type byte. | |
Type 0x00 means the normal format: | |
00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ | |
ZERO---------------------------- CURCODE- VER-- RESERVED | |
Types 0x80 - 0xFF are reserved for hashes - i.e. if the first bit is one, the remaining 159 bits are a hash. | |
Type 0x01 means demurraging currency: | |
01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ | |
CURCODE- DATE------- RATE------------------- RESERVED--- | |
CURCODE - Three character uppercase ASCII | |
DATE - DEPRECATED Demurrage start date (Ripple epoch; seconds since 2000) | |
`-> There is no reason to choose one reference date over another so this feature will be removed. | |
For now just make sure you ALWAYS set the date to 00 00 00 00 | |
RATE - Demurrage rate, defined as e-folding time in seconds (IEEE 754 double-precision floating-point) | |
RESERVED - Reserved for future use, duh | |
Note: Date and rate are four-byte aligned, rate is eight-byte aligned, for easy parsing on 32/64 bit CPUs. | |
Demurrage example: | |
01 58 41 55 00 00 00 00 C1 F7 6F F6 EC B0 BA C6 00 00 00 00 | |
// Calculating the demurrage rate | |
// | |
// We want 0.5% per year. There are 31536000 in a year, so the e-folding time in seconds is: | |
31536000 / ln(0.995) = -6291418827.045599 | |
// In plain English: The nominal amount of this asset will decrease (hence the minus sign) e times (≈2.71828) every 6291418827.045599 seconds | |
// As hex (IEEE double): | |
http://gregstoll.dyndns.org/~gregstoll/floattohex/ | |
0xc1f76ff6ecb0bac6 | |
// Final currency code | |
0158415500000000C1F76FF6ECB0BAC600000000 | |
// Example TrustSet | |
{"Flags":131072,"TransactionType":"TrustSet","Account":"rNb721TdNHN37yoURrMYDiQFmvXmENCZW6","LimitAmount":{"value":"1000","currency":"0158415500000000C1F76FF6ECB0BAC600000000","issuer":"rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN"}} |
Great idea, the e-folding time for an annual rate of 0.5% is -6291418827.05, so if we plug that in:
e ^ (31536000 / -6291418827.05) = 0.995
Much better precision compared the previous approach (per-second interest/demurrage):
0.99999999984 ^ 31536000 = 0.99496694802
I'll update the doc.
static public BigDecimal applyRate(BigDecimal amount, BigDecimal rate, TimeUnit time, long units) {
BigDecimal appliedRate = getSeconds(time, units).divide(rate, MathContext.DECIMAL64);
BigDecimal factor = BigDecimal.valueOf(Math.pow(Math.E, appliedRate.doubleValue()));
return amount.multiply(factor, MathContext.DECIMAL64);
}
Overuse of BigDecimal aside, is that how you can apply a rate, to calculate the reduction?
eg. https://gist.github.com/sublimator/0e97703c8d8ae78d6079
You can do
BigDecimal factor = BigDecimal.valueOf(Math.exp(appliedRate.doubleValue()));
to save a little computing time.
Cheers :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Maybe it'd make sense to express the rate as something like "e-folding time in seconds"? That would concentrate the precision more where it's needed, in the range very close to 1. Also, it's easy for a computer to calculate the demurrage factor as e^( time / T ), where T is the e-folding time. See also: https://en.wikipedia.org/wiki/Compound_interest#Continuous_compounding