# System Parameters

A operational description of Checker’s internal parameters, and operations on them. NOTE: here we focus primarily on the specifics of the calculations; for the meaning of the concepts, see Design.

## State

• q: of type (1 / kit).

• index: of type tez.

• protected_index: of type tez.

• target: TODO: said dimensionless, but I think tez/kit? Hmmm. I have to re-check the units of measure.

• drift_derivative

• drift

• outstanding_kit: approximation of the total amount of kit that would be currently required to close all burrows.

• circulating_kit: approximation of the total amount of kit that is currently in circulation.

• last_touched: the last time the parameters were touched.

And two additional indices, one used in the calculation of burrowing fees and one in the calculation of the imbalance adjustment:

• burrow_fee_index

• imbalance_index

## Initialization

We currently initialize checker with the following parameters:

q = 1
index = 1xtz
protected_index = 1xtz
target = 1
drift = 0
drift_derivative = 0
outstanding_kit = 0kit
circulating_kit = 0kit
last_touched = now
burrow_fee_index = 1
imbalance_index  = 1


## Price API

tz_minting     = max index protected_index (in tez)
tz_liquidation = min index protected_index (in tez)


To calculate the current prices in (tez/kit), we multiply with the current quantity:

minting_price     = q * tz_minting
liquidation_price = q * tz_liquidation


### Note

The definition of tz_minting and tz_liquidation implies that at any given moment, tz_minting >= tz_liquidation > 0. Combined with fminting > fliquidation, we have that

tz_minting * fminting > tz_liquidation * fliquidation


which is useful in liquidation logic (see burrow-state-liquidations.md).

The adjustment index, as required by burrowing logic, can be calculated from the system parameters as the product of the burrow fee index and the imbalance index:

adjustment_index = burrow_fee_index * imbalance_index


## Touching

Touching the system parameters has the effect of updating all aforementioned fields, and calculating the burrowing fees that need to be accrued to the cfmm sub-contract. This is done under the assumption that we have available the current time now, the current index index_now (calculated by the medianizer), and the current price of kit in tez kit_in_tez_now (calculated by the cfmm sub-contract). In fact, the cfmm sub-contract gives us the one calculated at the end of the last block, to make manipulation a little harder. We update each field:

### last_touched

Update the timestamp from the last time it was touched to now

new_last_touched = now


### index

Update the index from the last time the parameters were touched to the current one

new_index = index_now


### protected_index

Update the protected index, by multiplying it with a bounded factor:

new_protected_index = old_protected_index * clamp (current_index / protected_index, low, high)


where low and high depend on how much time has passed since the last time the parameters were touched, effectively limiting how fast protected_index can change:

low  = exp (-epsilon * (now - last_touched))
high = exp (+epsilon * (now - last_touched))


NOTE: exp (x) = 1 + x here; we expect the contract to be touched rather frequently, which keeps the exponent rather small, which makes this a good approximation of exp.

### drift_derivative

For the calculation of the derivative of drift, drift_derivative, we only use the last-observed target (TODO: show how we get from the original formula with the logarithms to this?) We calculate as follows:

new_drift_derivative =
-0.0005 / (secs_in_a_day ^ 2) , if                        target <= exp (-high_bracket)
-0.0001 / (secs_in_a_day ^ 2) , if exp (-high_bracket) <  target <= exp (-low_bracket)
0                            , if exp (-low_bracket)  <  target <  exp ( low_bracket)
0.0001 / (secs_in_a_day ^ 2) , if exp ( low_bracket)  <= target <  exp ( high_bracket)
0.0005 / (secs_in_a_day ^ 2) , if exp ( high_bracket) <= target


### drift

For the calculation of the current drift, we use use the following formula:

new_drift = old_drift + (1/2) * (old_drift_derivative + new_drift_derivative) * (now - last_touched)


### q

For the calculation of the current quantity q, we use the following formula:

new_q = old_q
* exp (
(old_drift + (1/6) * ((2 * old_drift_derivative) + new_drift_derivative) * (now - last_touched))
* (now - last_touched)
)


NOTE: exp (x) = 1 + x here; TODO: not sure if the exponent is small enough for this to be a good approximation.

### target

new_target = new_q * (new_index / kit_in_tez_now)


### burrow_fee_index

The burrow fee index is updated linearly on the number of seconds that have passed since the last time the parameters were touched.

new_burrow_fee_index = old_burrow_fee_index
* (1 + burrow_fee_rate * (now - last_touched) / seconds_in_a_year)


### imbalance_index

The imbalance index is also updated linearly on the number of seconds that have passed since the last time the parameters were touched

new_imbalance_index = old_imbalance_index
* (1 + imbalance_rate * (now - last_touched) / seconds_in_a_year)


but imbalance_rate varies, depending on the difference between old_outstanding_kit and old_circulating_kit:

imbalance_rate =
clamp
( imbalance_scaling_factor * (circulating - outstanding) / circulating,
-imbalance_limit,
+imbalance_limit
)


or, equivalently:

imbalance_rate =
min (imbalance_scaling_factor * (circulating - outstanding) / circulating, +imbalance_limit), if circulating >= outstanding
max (imbalance_scaling_factor * (circulating - outstanding) / circulating, -imbalance_limit), if circulating < outstanding


And in the edge cases the imbalance_rate is calculated as follows:

• if old_circulating_kit = 0 and old_outstanding_kit = 0 then imbalance_rate = 0.

• if old_circulating_kit = 0 and old_outstanding_kit > 0 then imbalance_rate = -imbalance_limit. (the outstanding kit is infinitely greater than the circulating kit, so the rate is saturated).

### Intermediate outstanding_kit

In order to compute the updates for the two remaining fields (outstanding_kit and circulating_kit), we first need to calculate the current amount of kit outstanding, taking into account the accrued burrowing fee, thus

outstanding_with_fees = old_outstanding_kit * (new_burrow_fee_index / old_burrow_fee_index)


### Accrual to cfmm

The accrued burrowing fees are to be given to the cfmm sub-contract. The total amount we easily compute as

accrual_to_cfmm = outstanding_with_fees - old_outstanding


### outstanding_kit

To obtain the updated outstanding_kit, we need to account for both the accrued burrowing fees, and the imbalance adjustment

new_outstanding_kit = old_outstanding_kit
* (new_burrow_fee_index / old_burrow_fee_index)
* (new_imbalance_index / old_imbalance_index)


or equivalently

new_outstanding_kit = outstanding_with_fees * (new_imbalance_index / old_imbalance_index)


### circulating_kit

Finally, to obtain the up-to-date circulating_kit, we just need to record the new kit in circulation, that is, accrual_to_cfmm:

new_circulating_kit = old_circulating_kit + accrual_to_cfmm


NOTE: If the current timestamp is identical to that stored in the parameters, we do not perform any of the above.

## Misc

• seconds_in_a_year = 31556952 (= (365 + 1/4 - 1/100 + 1/400) days * 24 * 60 * 60)

• seconds_in_a_day  = 86400 (= 24 * 60 * 60)

• low_bracket  = 0.005

• high_bracket = 0.05

• imbalance_scaling_factor = 0.75

• imbalance_limit = 0.05