Fix margin call price calculation
This commit is contained in:
parent
08bf4ec3fe
commit
177950b791
5 changed files with 24 additions and 19 deletions
|
|
@ -99,26 +99,21 @@ namespace graphene { namespace chain {
|
||||||
}
|
}
|
||||||
price price::max( asset_id_type base, asset_id_type quote ) { return asset( share_type(GRAPHENE_MAX_SHARE_SUPPLY), base ) / asset( share_type(1), quote); }
|
price price::max( asset_id_type base, asset_id_type quote ) { return asset( share_type(GRAPHENE_MAX_SHARE_SUPPLY), base ) / asset( share_type(1), quote); }
|
||||||
price price::min( asset_id_type base, asset_id_type quote ) { return asset( 1, base ) / asset( GRAPHENE_MAX_SHARE_SUPPLY, quote); }
|
price price::min( asset_id_type base, asset_id_type quote ) { return asset( 1, base ) / asset( GRAPHENE_MAX_SHARE_SUPPLY, quote); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The call price is defined so that the collateral is able to purchase debt * collateral ratio.
|
* The black swan price is defined as debt/collateral, we want to perform a margin call
|
||||||
|
* before debt == collateral. Given a debt/collateral ratio of 1 USD / CORE and
|
||||||
|
* a maintenance collateral requirement of 2x we can define the call price to be
|
||||||
|
* 2 USD / CORE.
|
||||||
*
|
*
|
||||||
* Give a margin order with @ref debt and @ref collateral we can infer the market price that
|
* This method divides the collateral by the maintenance collateral ratio to derive
|
||||||
* would be necessary to maintain the invariant that the collateral can purchase debt * collateral ratio
|
* a call price for the given black swan ratio.
|
||||||
*
|
|
||||||
* (debt / collateral_ratio) / collateral == fair market price
|
|
||||||
*
|
|
||||||
* Stated another way:
|
|
||||||
*
|
|
||||||
* C * R / D
|
|
||||||
*
|
|
||||||
* This method only works if attempting to calculate the call price from a margin position.
|
|
||||||
*/
|
*/
|
||||||
price price::call_price(const asset& debt, const asset& collateral, uint16_t collateral_ratio)
|
price price::call_price(const asset& debt, const asset& collateral, uint16_t collateral_ratio)
|
||||||
{ try {
|
{ try {
|
||||||
fc::uint128 tmp( collateral.amount.value );
|
fc::uint128 tmp( collateral.amount.value );
|
||||||
tmp *= collateral_ratio - 1000;
|
tmp *= 1000;
|
||||||
tmp /= 1000;
|
tmp /= collateral_ratio;
|
||||||
FC_ASSERT( tmp <= GRAPHENE_MAX_SHARE_SUPPLY );
|
FC_ASSERT( tmp <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||||
return asset( tmp.to_uint64(), collateral.asset_id) / debt;
|
return asset( tmp.to_uint64(), collateral.asset_id) / debt;
|
||||||
} FC_CAPTURE_AND_RETHROW( (debt)(collateral)(collateral_ratio) ) }
|
} FC_CAPTURE_AND_RETHROW( (debt)(collateral)(collateral_ratio) ) }
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ void_result call_order_update_evaluator::do_apply(const call_order_update_operat
|
||||||
call.borrower = o.funding_account;
|
call.borrower = o.funding_account;
|
||||||
call.collateral = o.delta_collateral.amount;
|
call.collateral = o.delta_collateral.amount;
|
||||||
call.debt = o.delta_debt.amount;
|
call.debt = o.delta_debt.amount;
|
||||||
call.call_price = ~price::call_price(o.delta_debt, o.delta_collateral,
|
call.call_price = price::call_price(o.delta_debt, o.delta_collateral,
|
||||||
_bitasset_data->current_feed.maintenance_collateral_ratio);
|
_bitasset_data->current_feed.maintenance_collateral_ratio);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +117,7 @@ void_result call_order_update_evaluator::do_apply(const call_order_update_operat
|
||||||
d.modify( *call_obj, [&]( call_order_object& call ){
|
d.modify( *call_obj, [&]( call_order_object& call ){
|
||||||
call.collateral += o.delta_collateral.amount;
|
call.collateral += o.delta_collateral.amount;
|
||||||
call.debt += o.delta_debt.amount;
|
call.debt += o.delta_debt.amount;
|
||||||
call.call_price = ~price::call_price(call.get_debt(), call.get_collateral(),
|
call.call_price = price::call_price(call.get_debt(), call.get_collateral(),
|
||||||
_bitasset_data->current_feed.maintenance_collateral_ratio);
|
_bitasset_data->current_feed.maintenance_collateral_ratio);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -333,6 +333,7 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa
|
||||||
auto max_price = price::max( mia.id, bitasset.options.short_backing_asset );
|
auto max_price = price::max( mia.id, bitasset.options.short_backing_asset );
|
||||||
// stop when limit orders are selling too little USD for too much CORE
|
// stop when limit orders are selling too little USD for too much CORE
|
||||||
auto min_price = bitasset.current_feed.max_short_squeeze_price();
|
auto min_price = bitasset.current_feed.max_short_squeeze_price();
|
||||||
|
/*
|
||||||
// edump((bitasset.current_feed));
|
// edump((bitasset.current_feed));
|
||||||
edump((min_price.to_real())(min_price));
|
edump((min_price.to_real())(min_price));
|
||||||
edump((max_price.to_real())(max_price));
|
edump((max_price.to_real())(max_price));
|
||||||
|
|
@ -350,6 +351,7 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa
|
||||||
wdump((max_price)(max_price.to_real()));
|
wdump((max_price)(max_price.to_real()));
|
||||||
wdump((min_price)(min_price.to_real()));
|
wdump((min_price)(min_price.to_real()));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
assert( max_price.base.asset_id == min_price.base.asset_id );
|
assert( max_price.base.asset_id == min_price.base.asset_id );
|
||||||
wlog( "from ${a} Debt/Col to ${b} Debt/Col ", ("a", max_price.to_real())("b",min_price.to_real()) );
|
wlog( "from ${a} Debt/Col to ${b} Debt/Col ", ("a", max_price.to_real())("b",min_price.to_real()) );
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit dde8ed9d7ab49807f2556488c0815f3741b11e00
|
Subproject commit c09035dba0cdab7fcb2c11bf81aaeaffaa981f66
|
||||||
|
|
@ -42,11 +42,19 @@ BOOST_FIXTURE_TEST_SUITE( operation_tests, database_fixture )
|
||||||
BOOST_AUTO_TEST_CASE( feed_limit_logic_test )
|
BOOST_AUTO_TEST_CASE( feed_limit_logic_test )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
asset usd(100,1);
|
asset usd(1000,1);
|
||||||
asset core(100,0);
|
asset core(1000,0);
|
||||||
price_feed feed;
|
price_feed feed;
|
||||||
feed.settlement_price = usd / core;
|
feed.settlement_price = usd / core;
|
||||||
|
|
||||||
|
// require 3x min collateral
|
||||||
|
auto swanp = usd / core;
|
||||||
|
auto callp = ~price::call_price( usd, core, 1750 );
|
||||||
|
// 1:1 collateral
|
||||||
|
wdump((callp.to_real())(callp));
|
||||||
|
wdump((swanp.to_real())(swanp));
|
||||||
|
FC_ASSERT( callp.to_real() > swanp.to_real() );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
wdump((feed.settlement_price.to_real()));
|
wdump((feed.settlement_price.to_real()));
|
||||||
wdump((feed.maintenance_price().to_real()));
|
wdump((feed.maintenance_price().to_real()));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue