You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
6.6 KiB
112 lines
6.6 KiB
from datetime import datetime |
|
|
|
import pytest |
|
from jmclient import jm_single, load_test_config, FidelityBondMixin |
|
from jmclient.bond_calc import get_next_locktime, get_bond_values, get_percentiles |
|
|
|
pytestmark = pytest.mark.usefixtures("setup_regtest_bitcoind") |
|
|
|
|
|
@pytest.mark.parametrize(('date', 'next_locktime'), |
|
((datetime(2022, 1, 1, 1, 1), datetime(2022, 2, 1)), |
|
(datetime(2022, 11, 1, 1, 1), datetime(2022, 12, 1)), |
|
(datetime(2022, 12, 1, 1, 1), datetime(2023, 1, 1)))) |
|
def test_get_next_locktime(date: datetime, next_locktime: datetime) -> None: |
|
assert get_next_locktime(date) == next_locktime |
|
|
|
|
|
@pytest.mark.parametrize(("data", "percentiles"), |
|
(([1, 2], |
|
[1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.1, 1.11, 1.12, 1.13, 1.14, 1.15, |
|
1.16, 1.17, 1.18, 1.19, 1.2, 1.21, 1.22, 1.23, 1.24, 1.25, 1.26, 1.27, 1.28, 1.29, 1.3, 1.31, |
|
1.32, 1.33, 1.34, 1.35, 1.36, 1.37, 1.38, 1.39, 1.4, 1.41, 1.42, 1.43, 1.44, 1.45, 1.46, |
|
1.47, 1.48, 1.49, 1.5, 1.51, 1.52, 1.53, 1.54, 1.55, 1.56, 1.57, 1.58, 1.59, 1.6, 1.61, 1.62, |
|
1.63, 1.64, 1.65, 1.66, 1.67, 1.68, 1.69, 1.7, 1.71, 1.72, 1.73, 1.74, 1.75, 1.76, 1.77, |
|
1.78, 1.79, 1.8, 1.81, 1.82, 1.83, 1.84, 1.85, 1.86, 1.87, 1.88, 1.89, 1.9, 1.91, 1.92, 1.93, |
|
1.94, 1.95, 1.96, 1.97, 1.98, 1.99]), |
|
([1, 2, 10, 100], |
|
[1.03, 1.06, 1.09, 1.12, 1.15, 1.18, 1.21, 1.24, 1.27, 1.3, 1.33, 1.36, 1.39, 1.42, 1.45, |
|
1.48, 1.51, 1.54, 1.57, 1.6, 1.63, 1.66, 1.69, 1.72, 1.75, 1.78, 1.81, 1.84, 1.87, 1.9, 1.93, |
|
1.96, 1.99, 2.16, 2.4, 2.64, 2.88, 3.12, 3.36, 3.6, 3.84, 4.08, 4.32, 4.56, 4.8, 5.04, 5.28, |
|
5.52, 5.76, 6.0, 6.24, 6.48, 6.72, 6.96, 7.2, 7.44, 7.68, 7.92, 8.16, 8.4, 8.64, 8.88, 9.12, |
|
9.36, 9.6, 9.84, 10.9, 13.6, 16.3, 19.0, 21.7, 24.4, 27.1, 29.8, 32.5, 35.2, 37.9, 40.6, |
|
43.3, 46.0, 48.7, 51.4, 54.1, 56.8, 59.5, 62.2, 64.9, 67.6, 70.3, 73.0, 75.7, 78.4, 81.1, |
|
83.8, 86.5, 89.2, 91.9, 94.6, 97.3]), |
|
((0.1, 0.2, 1.1, 2.3, 4.7), |
|
[0.10400000000000002, 0.10800000000000001, 0.11200000000000002, 0.11600000000000002, 0.12, |
|
0.12400000000000003, 0.128, 0.132, 0.136, 0.14, 0.14400000000000002, 0.14800000000000002, |
|
0.15200000000000002, 0.15600000000000003, 0.16, 0.16400000000000003, 0.168, 0.172, |
|
0.17600000000000002, 0.18, 0.18400000000000002, 0.188, 0.19200000000000003, 0.196, 0.2, |
|
0.23600000000000002, 0.272, 0.30800000000000005, 0.3440000000000001, 0.38, |
|
0.41600000000000004, 0.452, 0.48800000000000004, 0.524, 0.56, 0.5960000000000001, 0.632, |
|
0.6680000000000001, 0.7040000000000001, 0.74, 0.7760000000000001, 0.8120000000000002, 0.848, |
|
0.884, 0.92, 0.9560000000000001, 0.9920000000000002, 1.028, 1.064, 1.1, 1.1480000000000001, |
|
1.196, 1.244, 1.2919999999999998, 1.34, 1.3880000000000001, 1.436, 1.484, 1.5319999999999998, |
|
1.58, 1.6280000000000001, 1.676, 1.724, 1.7719999999999998, 1.82, 1.8679999999999999, |
|
1.9159999999999997, 1.964, 2.012, 2.06, 2.1079999999999997, 2.1559999999999997, 2.204, 2.252, |
|
2.3, 2.396, 2.492, 2.5879999999999996, 2.6839999999999997, 2.78, 2.8760000000000003, 2.972, |
|
3.0679999999999996, 3.1639999999999997, 3.26, 3.3560000000000003, 3.4520000000000004, 3.548, |
|
3.6439999999999997, 3.74, 3.8360000000000003, 3.9320000000000004, 4.0280000000000005, 4.124, |
|
4.22, 4.316, 4.412000000000001, 4.508, 4.604]))) |
|
def test_get_percentiles(data, percentiles): |
|
assert get_percentiles(data) == percentiles |
|
|
|
|
|
def test_get_bond_values() -> None: |
|
load_test_config() |
|
# 1 BTC |
|
amount = pow(10, 8) |
|
months = 1 |
|
interest = jm_single().config.getfloat("POLICY", "interest_rate") |
|
exponent = jm_single().config.getfloat("POLICY", "bond_value_exponent") |
|
parameters, results = get_bond_values(amount, months) |
|
assert parameters["amount"] == amount |
|
assert parameters["current_time"] == parameters["confirm_time"] |
|
assert parameters["interest"] == interest |
|
assert parameters["exponent"] == exponent |
|
assert len(results) == months |
|
locktime = datetime.fromtimestamp(results[0]["locktime"]) |
|
assert locktime.month == get_next_locktime(datetime.now()).month |
|
value = FidelityBondMixin.calculate_timelocked_fidelity_bond_value( |
|
parameters["amount"], |
|
parameters["confirm_time"], |
|
results[0]["locktime"], |
|
parameters["current_time"], |
|
parameters["interest"], |
|
) |
|
assert results[0]["value"] == value |
|
|
|
months = 12 |
|
interest = 0.02 |
|
exponent = 2 |
|
confirm_time = datetime(2021, 12, 1).timestamp() |
|
parameters, results = get_bond_values(amount, |
|
months, |
|
confirm_time, |
|
interest, |
|
exponent) |
|
assert parameters["amount"] == amount |
|
assert parameters["current_time"] != parameters["confirm_time"] |
|
assert parameters["confirm_time"] == confirm_time |
|
assert parameters["interest"] == interest |
|
assert parameters["exponent"] == exponent |
|
assert len(results) == months |
|
current_time = datetime.now() |
|
# get_bond_values(), at the end, reset the exponent to the config one. |
|
# So we have to set the exponent here, otherwise the bond value calculation |
|
# won't match and the assert would fail. |
|
old_exponent = jm_single().config.get("POLICY", "bond_value_exponent") |
|
jm_single().config.set("POLICY", "bond_value_exponent", str(exponent)) |
|
for result in results: |
|
locktime = datetime.fromtimestamp(result["locktime"]) |
|
assert locktime.month == get_next_locktime(current_time).month |
|
current_time = locktime |
|
value = FidelityBondMixin.calculate_timelocked_fidelity_bond_value( |
|
parameters["amount"], |
|
parameters["confirm_time"], |
|
result["locktime"], |
|
parameters["current_time"], |
|
parameters["interest"], |
|
) |
|
assert result["value"] == value |
|
jm_single().config.set("POLICY", "bond_value_exponent", old_exponent)
|
|
|