Progress on margin call tests
This commit is contained in:
parent
66ab805458
commit
db43f41de8
6 changed files with 384 additions and 264 deletions
|
|
@ -126,4 +126,26 @@ namespace graphene { namespace chain {
|
||||||
FC_ASSERT( maintenance_collateral_ratio >= maximum_short_squeeze_ratio );
|
FC_ASSERT( maintenance_collateral_ratio >= maximum_short_squeeze_ratio );
|
||||||
} FC_CAPTURE_AND_RETHROW( (*this) ) }
|
} FC_CAPTURE_AND_RETHROW( (*this) ) }
|
||||||
|
|
||||||
|
price price_feed::max_short_squeeze_price()const
|
||||||
|
{
|
||||||
|
asset collateral = settlement_price.quote;
|
||||||
|
fc::uint128 tmp( collateral.amount.value );
|
||||||
|
tmp *= maximum_short_squeeze_ratio - 1000;
|
||||||
|
tmp /= 1000;
|
||||||
|
FC_ASSERT( tmp <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||||
|
collateral.amount = tmp.to_uint64();
|
||||||
|
return settlement_price.base / collateral;
|
||||||
|
}
|
||||||
|
price price_feed::maintenance_price()const
|
||||||
|
{
|
||||||
|
asset collateral = settlement_price.quote;
|
||||||
|
fc::uint128 tmp( collateral.amount.value );
|
||||||
|
tmp *= maintenance_collateral_ratio - 1000;
|
||||||
|
tmp /= 1000;
|
||||||
|
FC_ASSERT( tmp <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||||
|
collateral.amount = tmp.to_uint64();
|
||||||
|
return settlement_price.base / collateral;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
|
||||||
|
|
@ -308,6 +308,7 @@ void_result asset_update_feed_producers_evaluator::do_apply(const asset_update_f
|
||||||
a.update_median_feeds(db().head_block_time());
|
a.update_median_feeds(db().head_block_time());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return void_result();
|
return void_result();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -396,6 +397,9 @@ void_result asset_publish_feeds_evaluator::do_apply(const asset_publish_feed_ope
|
||||||
a.update_median_feeds(d.head_block_time());
|
a.update_median_feeds(d.head_block_time());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// TODO: only do this if the median feed actually changed, otherwise there is no point
|
||||||
|
db().check_call_orders( base );
|
||||||
|
|
||||||
return void_result();
|
return void_result();
|
||||||
} FC_CAPTURE_AND_RETHROW((o)) }
|
} FC_CAPTURE_AND_RETHROW((o)) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -388,10 +388,12 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa
|
||||||
const limit_order_index& limit_index = get_index_type<limit_order_index>();
|
const limit_order_index& limit_index = get_index_type<limit_order_index>();
|
||||||
const auto& limit_price_index = limit_index.indices().get<by_price>();
|
const auto& limit_price_index = limit_index.indices().get<by_price>();
|
||||||
|
|
||||||
|
// looking for limit orders selling the most USD for the least CORE
|
||||||
auto max_price = price::max( mia.id, bitasset.options.short_backing_asset );
|
auto max_price = price::max( mia.id, bitasset.options.short_backing_asset );
|
||||||
auto min_price = bitasset.current_feed.max_short_squeeze_price();
|
// stop when limit orders are selling too little USD for too much CORE
|
||||||
/*
|
//auto min_price = bitasset.current_feed.max_short_squeeze_price();
|
||||||
if( require_orders )
|
auto min_price = price::min( mia.id, bitasset.options.short_backing_asset );
|
||||||
|
idump((bitasset.current_feed.settlement_price)(bitasset.current_feed.settlement_price.to_real()));
|
||||||
{
|
{
|
||||||
for( const auto& order : limit_price_index )
|
for( const auto& order : limit_price_index )
|
||||||
wdump((order)(order.sell_price.to_real()));
|
wdump((order)(order.sell_price.to_real()));
|
||||||
|
|
@ -404,24 +406,21 @@ 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()));
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
FC_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()) );
|
||||||
// NOTE limit_price_index is sorted from greatest to least
|
// NOTE limit_price_index is sorted from greatest to least
|
||||||
auto limit_itr = limit_price_index.lower_bound( max_price );
|
auto limit_itr = limit_price_index.lower_bound( max_price );
|
||||||
auto limit_end = limit_price_index.upper_bound( min_price );
|
auto limit_end = limit_price_index.upper_bound( min_price );
|
||||||
|
|
||||||
/*
|
|
||||||
if( limit_itr != limit_price_index.end() )
|
if( limit_itr != limit_price_index.end() )
|
||||||
wdump((*limit_itr)(limit_itr->sell_price.to_real()));
|
wdump((*limit_itr)(limit_itr->sell_price.to_real()));
|
||||||
if( limit_end != limit_price_index.end() )
|
if( limit_end != limit_price_index.end() )
|
||||||
wdump((*limit_end)(limit_end->sell_price.to_real()));
|
wdump((*limit_end)(limit_end->sell_price.to_real()));
|
||||||
*/
|
|
||||||
|
|
||||||
if( limit_itr == limit_end )
|
if( limit_itr == limit_end )
|
||||||
{
|
{
|
||||||
//wlog( "no orders available to fill margin calls" );
|
wlog( "no orders available to fill margin calls" );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -158,10 +158,7 @@ namespace graphene { namespace chain {
|
||||||
* debt * settlement_price < debt * maintenance
|
* debt * settlement_price < debt * maintenance
|
||||||
* debt * maintenance_price() < debt * max_short_squeeze_price()
|
* debt * maintenance_price() < debt * max_short_squeeze_price()
|
||||||
*/
|
*/
|
||||||
price maintenance_price()const
|
price maintenance_price()const;
|
||||||
{
|
|
||||||
return ~price::call_price( settlement_price.base, settlement_price.quote, maintenance_collateral_ratio );
|
|
||||||
}
|
|
||||||
|
|
||||||
/** When selling collateral to pay off debt, the least amount of debt to receive should be
|
/** When selling collateral to pay off debt, the least amount of debt to receive should be
|
||||||
* min_usd = max_short_squeeze_price() * collateral
|
* min_usd = max_short_squeeze_price() * collateral
|
||||||
|
|
@ -169,10 +166,7 @@ namespace graphene { namespace chain {
|
||||||
* This is provided to ensure that a black swan cannot be trigged due to poor liquidity alone, it
|
* This is provided to ensure that a black swan cannot be trigged due to poor liquidity alone, it
|
||||||
* must be confirmed by having the max_short_squeeze_price() move below the black swan price.
|
* must be confirmed by having the max_short_squeeze_price() move below the black swan price.
|
||||||
*/
|
*/
|
||||||
price max_short_squeeze_price()const
|
price max_short_squeeze_price()const;
|
||||||
{
|
|
||||||
return ~price::call_price( settlement_price.base, settlement_price.quote, maximum_short_squeeze_ratio );
|
|
||||||
}
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
friend bool operator == ( const price_feed& a, const price_feed& b )
|
friend bool operator == ( const price_feed& a, const price_feed& b )
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
|
||||||
database_fixture::database_fixture()
|
database_fixture::database_fixture()
|
||||||
: app(), db( *app.chain_database() )
|
: app(), db( *app.chain_database() )
|
||||||
|
|
@ -745,25 +746,25 @@ void database_fixture::print_market( const string& syma, const string& symb )con
|
||||||
const auto& limit_idx = db.get_index_type<limit_order_index>();
|
const auto& limit_idx = db.get_index_type<limit_order_index>();
|
||||||
const auto& price_idx = limit_idx.indices().get<by_price>();
|
const auto& price_idx = limit_idx.indices().get<by_price>();
|
||||||
|
|
||||||
cout << std::fixed;
|
cerr << std::fixed;
|
||||||
cout.precision(5);
|
cerr.precision(5);
|
||||||
cout << std::setw(10) << std::left << "NAME" << " ";
|
cerr << std::setw(10) << std::left << "NAME" << " ";
|
||||||
cout << std::setw(16) << std::right << "FOR SALE" << " ";
|
cerr << std::setw(16) << std::right << "FOR SALE" << " ";
|
||||||
cout << std::setw(16) << std::right << "FOR WHAT" << " ";
|
cerr << std::setw(16) << std::right << "FOR WHAT" << " ";
|
||||||
cout << std::setw(10) << std::right << "PRICE" << " ";
|
cerr << std::setw(10) << std::right << "PRICE (S/W)" << " ";
|
||||||
cout << std::setw(10) << std::right << "1/PRICE" << "\n";
|
cerr << std::setw(10) << std::right << "1/PRICE (W/S)" << "\n";
|
||||||
cout << string(70, '=') << std::endl;
|
cerr << string(70, '=') << std::endl;
|
||||||
auto cur = price_idx.begin();
|
auto cur = price_idx.begin();
|
||||||
while( cur != price_idx.end() )
|
while( cur != price_idx.end() )
|
||||||
{
|
{
|
||||||
cout << std::setw( 10 ) << std::left << cur->seller(db).name << " ";
|
cerr << std::setw( 10 ) << std::left << cur->seller(db).name << " ";
|
||||||
cout << std::setw( 10 ) << std::right << cur->for_sale.value << " ";
|
cerr << std::setw( 10 ) << std::right << cur->for_sale.value << " ";
|
||||||
cout << std::setw( 5 ) << std::left << cur->amount_for_sale().asset_id(db).symbol << " ";
|
cerr << std::setw( 5 ) << std::left << cur->amount_for_sale().asset_id(db).symbol << " ";
|
||||||
cout << std::setw( 10 ) << std::right << cur->amount_to_receive().amount.value << " ";
|
cerr << std::setw( 10 ) << std::right << cur->amount_to_receive().amount.value << " ";
|
||||||
cout << std::setw( 5 ) << std::left << cur->amount_to_receive().asset_id(db).symbol << " ";
|
cerr << std::setw( 5 ) << std::left << cur->amount_to_receive().asset_id(db).symbol << " ";
|
||||||
cout << std::setw( 10 ) << std::right << cur->sell_price.to_real() << " ";
|
cerr << std::setw( 10 ) << std::right << cur->sell_price.to_real() << " ";
|
||||||
cout << std::setw( 10 ) << std::right << (~cur->sell_price).to_real() << " ";
|
cerr << std::setw( 10 ) << std::right << (~cur->sell_price).to_real() << " ";
|
||||||
cout << "\n";
|
cerr << "\n";
|
||||||
++cur;
|
++cur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -793,8 +794,10 @@ void database_fixture::print_call_orders()const
|
||||||
cout << std::setw(10) << std::right << "TYPE" << " ";
|
cout << std::setw(10) << std::right << "TYPE" << " ";
|
||||||
cout << std::setw(16) << std::right << "DEBT" << " ";
|
cout << std::setw(16) << std::right << "DEBT" << " ";
|
||||||
cout << std::setw(16) << std::right << "COLLAT" << " ";
|
cout << std::setw(16) << std::right << "COLLAT" << " ";
|
||||||
cout << std::setw(16) << std::right << "CALL PRICE" << " ";
|
cout << std::setw(16) << std::right << "CALL PRICE(D/C)" << " ";
|
||||||
cout << std::setw(16) << std::right << "~CALL PRICE" << "\n";
|
cout << std::setw(16) << std::right << "~CALL PRICE(C/D)" << " ";
|
||||||
|
cout << std::setw(16) << std::right << "SWAN(D/C)" << " ";
|
||||||
|
cout << std::setw(16) << std::right << "SWAN(C/D)" << "\n";
|
||||||
cout << string(70, '=');
|
cout << string(70, '=');
|
||||||
|
|
||||||
for( const call_order_object& o : db.get_index_type<call_order_index>().indices() )
|
for( const call_order_object& o : db.get_index_type<call_order_index>().indices() )
|
||||||
|
|
@ -805,6 +808,8 @@ void database_fixture::print_call_orders()const
|
||||||
cout << std::setw( 16 ) << std::right << pretty( o.get_collateral() ) << " ";
|
cout << std::setw( 16 ) << std::right << pretty( o.get_collateral() ) << " ";
|
||||||
cout << std::setw( 16 ) << std::right << o.call_price.to_real() << " ";
|
cout << std::setw( 16 ) << std::right << o.call_price.to_real() << " ";
|
||||||
cout << std::setw( 16 ) << std::right << (~o.call_price).to_real() << " ";
|
cout << std::setw( 16 ) << std::right << (~o.call_price).to_real() << " ";
|
||||||
|
cout << std::setw( 16 ) << std::right << (o.get_debt()/o.get_collateral()).to_real() << " ";
|
||||||
|
cout << std::setw( 16 ) << std::right << (~(o.get_debt()/o.get_collateral())).to_real() << " ";
|
||||||
}
|
}
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
|
|
@ -818,7 +823,7 @@ void database_fixture::print_joint_market( const string& syma, const string& sym
|
||||||
cout << std::setw(10) << std::right << "TYPE" << " ";
|
cout << std::setw(10) << std::right << "TYPE" << " ";
|
||||||
cout << std::setw(16) << std::right << "FOR SALE" << " ";
|
cout << std::setw(16) << std::right << "FOR SALE" << " ";
|
||||||
cout << std::setw(16) << std::right << "FOR WHAT" << " ";
|
cout << std::setw(16) << std::right << "FOR WHAT" << " ";
|
||||||
cout << std::setw(16) << std::right << "PRICE" << "\n";
|
cout << std::setw(16) << std::right << "PRICE (S/W)" << "\n";
|
||||||
cout << string(70, '=');
|
cout << string(70, '=');
|
||||||
|
|
||||||
const auto& limit_idx = db.get_index_type<limit_order_index>();
|
const auto& limit_idx = db.get_index_type<limit_order_index>();
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,25 @@ using namespace graphene::chain;
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE( operation_tests, database_fixture )
|
BOOST_FIXTURE_TEST_SUITE( operation_tests, database_fixture )
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( feed_limit_logic_test )
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
asset usd(100,1);
|
||||||
|
asset core(200,1);
|
||||||
|
price_feed feed;
|
||||||
|
feed.settlement_price = usd / core;
|
||||||
|
|
||||||
|
FC_ASSERT( usd * feed.settlement_price < usd * feed.maintenance_price() );
|
||||||
|
FC_ASSERT( usd * feed.maintenance_price() < usd * feed.max_short_squeeze_price() );
|
||||||
|
|
||||||
|
} catch (fc::exception& e) {
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
BOOST_AUTO_TEST_CASE( call_order_update_test )
|
BOOST_AUTO_TEST_CASE( call_order_update_test )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
BOOST_TEST_MESSAGE("creating actors dan and sam" );
|
|
||||||
ACTORS((dan)(sam));
|
ACTORS((dan)(sam));
|
||||||
const auto& bitusd = create_bitasset("BITUSD");
|
const auto& bitusd = create_bitasset("BITUSD");
|
||||||
const auto& core = asset_id_type()(db);
|
const auto& core = asset_id_type()(db);
|
||||||
|
|
@ -121,6 +136,315 @@ BOOST_AUTO_TEST_CASE( call_order_update_test )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test sets up a situation where a margin call will be executed and ensures that
|
||||||
|
* it is properly filled.
|
||||||
|
*
|
||||||
|
* A margin call can happen in the following situation:
|
||||||
|
* 0. there exists a bid above the mas short squeeze price
|
||||||
|
* 1. highest bid is lower than the call price of an order
|
||||||
|
* 2. the asset is not a prediction market
|
||||||
|
* 3. there is a valid price feed
|
||||||
|
*/
|
||||||
|
BOOST_AUTO_TEST_CASE( margin_call_limit_test )
|
||||||
|
{ try {
|
||||||
|
ACTORS((buyer)(seller)(borrower)(borrower2)(feedproducer));
|
||||||
|
|
||||||
|
const auto& bitusd = create_bitasset("BITUSD");
|
||||||
|
const auto& core = asset_id_type()(db);
|
||||||
|
|
||||||
|
int64_t init_balance(1000000);
|
||||||
|
|
||||||
|
transfer(genesis_account, buyer_id, asset(init_balance));
|
||||||
|
transfer(genesis_account, borrower_id, asset(init_balance));
|
||||||
|
transfer(genesis_account, borrower2_id, asset(init_balance));
|
||||||
|
update_feed_producers( bitusd, {feedproducer.id} );
|
||||||
|
|
||||||
|
price_feed current_feed;
|
||||||
|
current_feed.settlement_price = bitusd.amount( 100 ) / core.amount(100);
|
||||||
|
auto default_call_price = ~price::call_price( bitusd.amount(100), asset(100), 1750);
|
||||||
|
|
||||||
|
// starting out with price 1:1
|
||||||
|
publish_feed( bitusd, feedproducer, current_feed );
|
||||||
|
|
||||||
|
// start out with 2:1 collateral
|
||||||
|
borrow( borrower, bitusd.amount(5000), asset(10000), default_call_price );
|
||||||
|
borrow( borrower2, bitusd.amount(5000), asset(30000), default_call_price );
|
||||||
|
elog( "selling USD at 1:1, should be ok because we have 2:1 collateral" );
|
||||||
|
create_sell_order( borrower, bitusd.amount(5000), core.amount(5000) );
|
||||||
|
elog( "buying USD at 1:1" );
|
||||||
|
create_sell_order( buyer, core.amount(5000), bitusd.amount(5000) );
|
||||||
|
|
||||||
|
BOOST_REQUIRE_EQUAL( get_balance( borrower, bitusd ), 0 );
|
||||||
|
BOOST_REQUIRE_EQUAL( get_balance( buyer, bitusd ), 4950 ); // 1% market fee
|
||||||
|
BOOST_REQUIRE_EQUAL( get_balance( borrower, core ), init_balance - 10000 + 5000 );
|
||||||
|
BOOST_REQUIRE_EQUAL( get_balance( buyer, core ), init_balance - 5000 );
|
||||||
|
|
||||||
|
ilog( "print call orders..." );
|
||||||
|
print_call_orders();
|
||||||
|
ilog( "print market..." );
|
||||||
|
print_market( "", "" );
|
||||||
|
|
||||||
|
// sell the BitUSD for 50% more which represents a 33% fall in the value of the collateral
|
||||||
|
const auto order = create_sell_order( borrower2, bitusd.amount(1000), core.amount(1400) );
|
||||||
|
const auto order2 = create_sell_order( borrower2, bitusd.amount(1000), core.amount(1600) );
|
||||||
|
const auto order3 = create_sell_order( borrower2, bitusd.amount(1000), core.amount(1700) );
|
||||||
|
const auto order4 = create_sell_order( borrower2, bitusd.amount(1000), core.amount(1800) );
|
||||||
|
const auto order5 = create_sell_order( borrower2, bitusd.amount(950), core.amount(1850) );
|
||||||
|
|
||||||
|
ilog( "print call orders..." );
|
||||||
|
print_call_orders();
|
||||||
|
ilog( "print market..." );
|
||||||
|
print_market( "", "" );
|
||||||
|
|
||||||
|
FC_ASSERT( order, "order should not match because sell price is below short squeeze protection" );
|
||||||
|
wdump((bitusd.bitasset_data(db).current_feed.max_short_squeeze_price().to_real()));
|
||||||
|
wdump((bitusd.bitasset_data(db).current_feed.maintenance_price().to_real()));
|
||||||
|
wdump(((order->sell_price).to_real()));
|
||||||
|
|
||||||
|
// update the feed to indicate a 33% drop in value
|
||||||
|
BOOST_TEST_MESSAGE( "Update feed to indicate CORE fell in value by 33%" );
|
||||||
|
current_feed.settlement_price = bitusd.amount( 100 ) / core.amount(200);
|
||||||
|
publish_feed( bitusd, feedproducer, current_feed );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
const asset_object& bitusd = create_bitasset( "BITUSD" );
|
||||||
|
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
|
||||||
|
|
||||||
|
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
|
||||||
|
usd.current_feed.call_limit = core.amount(3) / bitusd.amount(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
const account_object& shorter1 = create_account( "shorter1" );
|
||||||
|
const account_object& shorter2 = create_account( "shorter2" );
|
||||||
|
const account_object& buyer1 = create_account( "buyer1" );
|
||||||
|
const account_object& buyer2 = create_account( "buyer2" );
|
||||||
|
|
||||||
|
transfer( genesis_account(db), shorter1, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), shorter2, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), buyer1, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), buyer2, asset( 10000 ) );
|
||||||
|
|
||||||
|
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
|
||||||
|
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
|
||||||
|
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
|
||||||
|
|
||||||
|
const auto& call_index = db.get_index_type<call_order_index>().indices().get<by_account>();
|
||||||
|
const auto call_itr = call_index.find(boost::make_tuple(shorter1.id, bitusd.id));
|
||||||
|
BOOST_REQUIRE( call_itr != call_index.end() );
|
||||||
|
const call_order_object& call = *call_itr;
|
||||||
|
BOOST_CHECK(call.get_collateral() == core.amount(2000));
|
||||||
|
BOOST_CHECK(call.get_debt() == bitusd.amount(1000));
|
||||||
|
BOOST_CHECK(call.call_price == price(core.amount(1500), bitusd.amount(1000)));
|
||||||
|
BOOST_CHECK_EQUAL(get_balance(shorter1, core), 9000);
|
||||||
|
|
||||||
|
ilog( "=================================== START===================================\n\n");
|
||||||
|
// this should cause the highest bid to below the margin call threshold
|
||||||
|
// which means it should be filled by the cover
|
||||||
|
auto unmatched = create_sell_order( buyer1, bitusd.amount(495), core.amount(750) );
|
||||||
|
if( unmatched ) edump((*unmatched));
|
||||||
|
BOOST_CHECK( !unmatched );
|
||||||
|
BOOST_CHECK(call.get_debt() == bitusd.amount(505));
|
||||||
|
BOOST_CHECK(call.get_collateral() == core.amount(1250));
|
||||||
|
|
||||||
|
auto below_call_price = create_sell_order(buyer1, bitusd.amount(200), core.amount(1));
|
||||||
|
BOOST_REQUIRE(below_call_price);
|
||||||
|
auto above_call_price = create_sell_order(buyer1, bitusd.amount(200), core.amount(303));
|
||||||
|
BOOST_REQUIRE(above_call_price);
|
||||||
|
auto above_id = above_call_price->id;
|
||||||
|
|
||||||
|
cancel_limit_order(*below_call_price);
|
||||||
|
BOOST_CHECK_THROW(db.get_object(above_id), fc::exception);
|
||||||
|
BOOST_CHECK(call.get_debt() == bitusd.amount(305));
|
||||||
|
BOOST_CHECK(call.get_collateral() == core.amount(947));
|
||||||
|
|
||||||
|
below_call_price = create_sell_order(buyer1, bitusd.amount(200), core.amount(1));
|
||||||
|
BOOST_REQUIRE(below_call_price);
|
||||||
|
auto below_id = below_call_price->id;
|
||||||
|
above_call_price = create_sell_order(buyer1, bitusd.amount(95), core.amount(144));
|
||||||
|
BOOST_REQUIRE(above_call_price);
|
||||||
|
above_id = above_call_price->id;
|
||||||
|
auto match_below_call = create_sell_order(buyer2, core.amount(1), bitusd.amount(200));
|
||||||
|
BOOST_CHECK(!match_below_call);
|
||||||
|
|
||||||
|
BOOST_CHECK_THROW(db.get_object(above_id), fc::exception);
|
||||||
|
BOOST_CHECK_THROW(db.get_object(below_id), fc::exception);
|
||||||
|
BOOST_CHECK(call.get_debt() == bitusd.amount(210));
|
||||||
|
BOOST_CHECK(call.get_collateral() == core.amount(803));
|
||||||
|
*/
|
||||||
|
} catch( const fc::exception& e) {
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( margin_call_limit_test_protected )
|
||||||
|
{ try {
|
||||||
|
FC_ASSERT( !"TODO - Reimplement with new short semantics" );
|
||||||
|
/*
|
||||||
|
const asset_object& bitusd = create_bitasset( "BITUSD" );
|
||||||
|
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
|
||||||
|
|
||||||
|
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
|
||||||
|
usd.current_feed.call_limit = core.amount(1) / bitusd.amount(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
const account_object& shorter1 = create_account( "shorter1" );
|
||||||
|
const account_object& shorter2 = create_account( "shorter2" );
|
||||||
|
const account_object& buyer1 = create_account( "buyer1" );
|
||||||
|
const account_object& buyer2 = create_account( "buyer2" );
|
||||||
|
|
||||||
|
transfer( genesis_account(db), shorter1, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), shorter2, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), buyer1, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), buyer2, asset( 10000 ) );
|
||||||
|
|
||||||
|
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
|
||||||
|
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
|
||||||
|
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
|
||||||
|
|
||||||
|
ilog( "=================================== START===================================\n\n");
|
||||||
|
// this should cause the highest bid to below the margin call threshold
|
||||||
|
// which means it should be filled by the cover
|
||||||
|
auto unmatched = create_sell_order( buyer1, bitusd.amount(990), core.amount(1500) );
|
||||||
|
if( unmatched ) edump((*unmatched));
|
||||||
|
BOOST_REQUIRE( unmatched );
|
||||||
|
*/
|
||||||
|
|
||||||
|
} catch( const fc::exception& e) {
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( dont_margin_call_limit_test )
|
||||||
|
{ try {
|
||||||
|
FC_ASSERT( !"TODO - Reimplement with new short semantics" );
|
||||||
|
/*
|
||||||
|
const asset_object& bitusd = create_bitasset( "BITUSD" );
|
||||||
|
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
|
||||||
|
|
||||||
|
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
|
||||||
|
usd.current_feed.call_limit = core.amount(3) / bitusd.amount(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
const account_object& shorter1 = create_account( "shorter1" );
|
||||||
|
const account_object& shorter2 = create_account( "shorter2" );
|
||||||
|
const account_object& buyer1 = create_account( "buyer1" );
|
||||||
|
const account_object& buyer2 = create_account( "buyer2" );
|
||||||
|
|
||||||
|
transfer( genesis_account(db), shorter1, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), shorter2, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), buyer1, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), buyer2, asset( 10000 ) );
|
||||||
|
|
||||||
|
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
|
||||||
|
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
|
||||||
|
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
|
||||||
|
|
||||||
|
// this should cause the highest bid to below the margin call threshold
|
||||||
|
// which means it should be filled by the cover
|
||||||
|
auto unmatched = create_sell_order( buyer1, bitusd.amount(990), core.amount(1100) );
|
||||||
|
if( unmatched ) edump((*unmatched));
|
||||||
|
BOOST_REQUIRE( unmatched );
|
||||||
|
*/
|
||||||
|
|
||||||
|
} catch( const fc::exception& e) {
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( margin_call_short_test )
|
||||||
|
{ try {
|
||||||
|
FC_ASSERT( !"TODO - Reimplement with new short semantics" );
|
||||||
|
/*
|
||||||
|
const asset_object& bitusd = create_bitasset( "BITUSD" );
|
||||||
|
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
|
||||||
|
|
||||||
|
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
|
||||||
|
usd.current_feed.call_limit = core.amount(3) / bitusd.amount(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
const account_object& shorter1 = create_account( "shorter1" );
|
||||||
|
const account_object& shorter2 = create_account( "shorter2" );
|
||||||
|
const account_object& buyer1 = create_account( "buyer1" );
|
||||||
|
const account_object& buyer2 = create_account( "buyer2" );
|
||||||
|
|
||||||
|
transfer( genesis_account(db), shorter1, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), shorter2, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), buyer1, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), buyer2, asset( 10000 ) );
|
||||||
|
|
||||||
|
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
|
||||||
|
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
|
||||||
|
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
|
||||||
|
ilog( "=================================== START===================================\n\n");
|
||||||
|
|
||||||
|
// this should cause the highest bid to below the margin call threshold
|
||||||
|
// which means it should be filled by the cover
|
||||||
|
auto unmatched = create_short( buyer1, bitusd.amount(990), core.amount(1500) );
|
||||||
|
if( unmatched ) edump((*unmatched));
|
||||||
|
BOOST_REQUIRE( !unmatched );
|
||||||
|
*/
|
||||||
|
|
||||||
|
} catch( const fc::exception& e) {
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( margin_call_short_test_limit_protected )
|
||||||
|
{ try {
|
||||||
|
FC_ASSERT( !"TODO - Reimplement with new short semantics" );
|
||||||
|
/*
|
||||||
|
const asset_object& bitusd = create_bitasset( "BITUSD" );
|
||||||
|
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
|
||||||
|
|
||||||
|
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
|
||||||
|
usd.current_feed.call_limit = core.amount(3) / bitusd.amount(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
const account_object& shorter1 = create_account( "shorter1" );
|
||||||
|
const account_object& shorter2 = create_account( "shorter2" );
|
||||||
|
const account_object& buyer1 = create_account( "buyer1" );
|
||||||
|
const account_object& buyer2 = create_account( "buyer2" );
|
||||||
|
|
||||||
|
transfer( genesis_account(db), shorter1, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), shorter2, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), buyer1, asset( 10000 ) );
|
||||||
|
transfer( genesis_account(db), buyer2, asset( 10000 ) );
|
||||||
|
|
||||||
|
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
|
||||||
|
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
|
||||||
|
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
|
||||||
|
ilog( "=================================== START===================================\n\n");
|
||||||
|
|
||||||
|
// this should cause the highest bid to below the margin call threshold
|
||||||
|
// which means it should be filled by the cover
|
||||||
|
auto unmatched = create_short( buyer1, bitusd.amount(990), core.amount(1500) );
|
||||||
|
if( unmatched ) edump((*unmatched));
|
||||||
|
BOOST_REQUIRE( unmatched );
|
||||||
|
*/
|
||||||
|
|
||||||
|
} catch( const fc::exception& e) {
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( create_account_test )
|
BOOST_AUTO_TEST_CASE( create_account_test )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
@ -947,234 +1271,6 @@ BOOST_AUTO_TEST_CASE( trade_amount_equals_zero )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( margin_call_limit_test )
|
|
||||||
{ try {
|
|
||||||
FC_ASSERT( !"TODO - Reimplement with new short semantics" );
|
|
||||||
/*
|
|
||||||
const asset_object& bitusd = create_bitasset( "BITUSD" );
|
|
||||||
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
|
|
||||||
|
|
||||||
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
|
|
||||||
usd.current_feed.call_limit = core.amount(3) / bitusd.amount(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
const account_object& shorter1 = create_account( "shorter1" );
|
|
||||||
const account_object& shorter2 = create_account( "shorter2" );
|
|
||||||
const account_object& buyer1 = create_account( "buyer1" );
|
|
||||||
const account_object& buyer2 = create_account( "buyer2" );
|
|
||||||
|
|
||||||
transfer( genesis_account(db), shorter1, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), shorter2, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), buyer1, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), buyer2, asset( 10000 ) );
|
|
||||||
|
|
||||||
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
|
|
||||||
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
|
|
||||||
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
|
|
||||||
|
|
||||||
const auto& call_index = db.get_index_type<call_order_index>().indices().get<by_account>();
|
|
||||||
const auto call_itr = call_index.find(boost::make_tuple(shorter1.id, bitusd.id));
|
|
||||||
BOOST_REQUIRE( call_itr != call_index.end() );
|
|
||||||
const call_order_object& call = *call_itr;
|
|
||||||
BOOST_CHECK(call.get_collateral() == core.amount(2000));
|
|
||||||
BOOST_CHECK(call.get_debt() == bitusd.amount(1000));
|
|
||||||
BOOST_CHECK(call.call_price == price(core.amount(1500), bitusd.amount(1000)));
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(shorter1, core), 9000);
|
|
||||||
|
|
||||||
ilog( "=================================== START===================================\n\n");
|
|
||||||
// this should cause the highest bid to below the margin call threshold
|
|
||||||
// which means it should be filled by the cover
|
|
||||||
auto unmatched = create_sell_order( buyer1, bitusd.amount(495), core.amount(750) );
|
|
||||||
if( unmatched ) edump((*unmatched));
|
|
||||||
BOOST_CHECK( !unmatched );
|
|
||||||
BOOST_CHECK(call.get_debt() == bitusd.amount(505));
|
|
||||||
BOOST_CHECK(call.get_collateral() == core.amount(1250));
|
|
||||||
|
|
||||||
auto below_call_price = create_sell_order(buyer1, bitusd.amount(200), core.amount(1));
|
|
||||||
BOOST_REQUIRE(below_call_price);
|
|
||||||
auto above_call_price = create_sell_order(buyer1, bitusd.amount(200), core.amount(303));
|
|
||||||
BOOST_REQUIRE(above_call_price);
|
|
||||||
auto above_id = above_call_price->id;
|
|
||||||
|
|
||||||
cancel_limit_order(*below_call_price);
|
|
||||||
BOOST_CHECK_THROW(db.get_object(above_id), fc::exception);
|
|
||||||
BOOST_CHECK(call.get_debt() == bitusd.amount(305));
|
|
||||||
BOOST_CHECK(call.get_collateral() == core.amount(947));
|
|
||||||
|
|
||||||
below_call_price = create_sell_order(buyer1, bitusd.amount(200), core.amount(1));
|
|
||||||
BOOST_REQUIRE(below_call_price);
|
|
||||||
auto below_id = below_call_price->id;
|
|
||||||
above_call_price = create_sell_order(buyer1, bitusd.amount(95), core.amount(144));
|
|
||||||
BOOST_REQUIRE(above_call_price);
|
|
||||||
above_id = above_call_price->id;
|
|
||||||
auto match_below_call = create_sell_order(buyer2, core.amount(1), bitusd.amount(200));
|
|
||||||
BOOST_CHECK(!match_below_call);
|
|
||||||
|
|
||||||
BOOST_CHECK_THROW(db.get_object(above_id), fc::exception);
|
|
||||||
BOOST_CHECK_THROW(db.get_object(below_id), fc::exception);
|
|
||||||
BOOST_CHECK(call.get_debt() == bitusd.amount(210));
|
|
||||||
BOOST_CHECK(call.get_collateral() == core.amount(803));
|
|
||||||
*/
|
|
||||||
} catch( const fc::exception& e) {
|
|
||||||
edump((e.to_detail_string()));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( margin_call_limit_test_protected )
|
|
||||||
{ try {
|
|
||||||
FC_ASSERT( !"TODO - Reimplement with new short semantics" );
|
|
||||||
/*
|
|
||||||
const asset_object& bitusd = create_bitasset( "BITUSD" );
|
|
||||||
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
|
|
||||||
|
|
||||||
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
|
|
||||||
usd.current_feed.call_limit = core.amount(1) / bitusd.amount(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
const account_object& shorter1 = create_account( "shorter1" );
|
|
||||||
const account_object& shorter2 = create_account( "shorter2" );
|
|
||||||
const account_object& buyer1 = create_account( "buyer1" );
|
|
||||||
const account_object& buyer2 = create_account( "buyer2" );
|
|
||||||
|
|
||||||
transfer( genesis_account(db), shorter1, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), shorter2, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), buyer1, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), buyer2, asset( 10000 ) );
|
|
||||||
|
|
||||||
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
|
|
||||||
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
|
|
||||||
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
|
|
||||||
|
|
||||||
ilog( "=================================== START===================================\n\n");
|
|
||||||
// this should cause the highest bid to below the margin call threshold
|
|
||||||
// which means it should be filled by the cover
|
|
||||||
auto unmatched = create_sell_order( buyer1, bitusd.amount(990), core.amount(1500) );
|
|
||||||
if( unmatched ) edump((*unmatched));
|
|
||||||
BOOST_REQUIRE( unmatched );
|
|
||||||
*/
|
|
||||||
|
|
||||||
} catch( const fc::exception& e) {
|
|
||||||
edump((e.to_detail_string()));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( dont_margin_call_limit_test )
|
|
||||||
{ try {
|
|
||||||
FC_ASSERT( !"TODO - Reimplement with new short semantics" );
|
|
||||||
/*
|
|
||||||
const asset_object& bitusd = create_bitasset( "BITUSD" );
|
|
||||||
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
|
|
||||||
|
|
||||||
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
|
|
||||||
usd.current_feed.call_limit = core.amount(3) / bitusd.amount(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
const account_object& shorter1 = create_account( "shorter1" );
|
|
||||||
const account_object& shorter2 = create_account( "shorter2" );
|
|
||||||
const account_object& buyer1 = create_account( "buyer1" );
|
|
||||||
const account_object& buyer2 = create_account( "buyer2" );
|
|
||||||
|
|
||||||
transfer( genesis_account(db), shorter1, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), shorter2, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), buyer1, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), buyer2, asset( 10000 ) );
|
|
||||||
|
|
||||||
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
|
|
||||||
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
|
|
||||||
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
|
|
||||||
|
|
||||||
// this should cause the highest bid to below the margin call threshold
|
|
||||||
// which means it should be filled by the cover
|
|
||||||
auto unmatched = create_sell_order( buyer1, bitusd.amount(990), core.amount(1100) );
|
|
||||||
if( unmatched ) edump((*unmatched));
|
|
||||||
BOOST_REQUIRE( unmatched );
|
|
||||||
*/
|
|
||||||
|
|
||||||
} catch( const fc::exception& e) {
|
|
||||||
edump((e.to_detail_string()));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( margin_call_short_test )
|
|
||||||
{ try {
|
|
||||||
FC_ASSERT( !"TODO - Reimplement with new short semantics" );
|
|
||||||
/*
|
|
||||||
const asset_object& bitusd = create_bitasset( "BITUSD" );
|
|
||||||
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
|
|
||||||
|
|
||||||
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
|
|
||||||
usd.current_feed.call_limit = core.amount(3) / bitusd.amount(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
const account_object& shorter1 = create_account( "shorter1" );
|
|
||||||
const account_object& shorter2 = create_account( "shorter2" );
|
|
||||||
const account_object& buyer1 = create_account( "buyer1" );
|
|
||||||
const account_object& buyer2 = create_account( "buyer2" );
|
|
||||||
|
|
||||||
transfer( genesis_account(db), shorter1, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), shorter2, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), buyer1, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), buyer2, asset( 10000 ) );
|
|
||||||
|
|
||||||
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
|
|
||||||
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
|
|
||||||
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
|
|
||||||
ilog( "=================================== START===================================\n\n");
|
|
||||||
|
|
||||||
// this should cause the highest bid to below the margin call threshold
|
|
||||||
// which means it should be filled by the cover
|
|
||||||
auto unmatched = create_short( buyer1, bitusd.amount(990), core.amount(1500) );
|
|
||||||
if( unmatched ) edump((*unmatched));
|
|
||||||
BOOST_REQUIRE( !unmatched );
|
|
||||||
*/
|
|
||||||
|
|
||||||
} catch( const fc::exception& e) {
|
|
||||||
edump((e.to_detail_string()));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( margin_call_short_test_limit_protected )
|
|
||||||
{ try {
|
|
||||||
FC_ASSERT( !"TODO - Reimplement with new short semantics" );
|
|
||||||
/*
|
|
||||||
const asset_object& bitusd = create_bitasset( "BITUSD" );
|
|
||||||
const asset_object& core = get_asset( GRAPHENE_SYMBOL );
|
|
||||||
|
|
||||||
db.modify( bitusd.bitasset_data(db), [&]( asset_bitasset_data_object& usd ){
|
|
||||||
usd.current_feed.call_limit = core.amount(3) / bitusd.amount(4);
|
|
||||||
});
|
|
||||||
|
|
||||||
const account_object& shorter1 = create_account( "shorter1" );
|
|
||||||
const account_object& shorter2 = create_account( "shorter2" );
|
|
||||||
const account_object& buyer1 = create_account( "buyer1" );
|
|
||||||
const account_object& buyer2 = create_account( "buyer2" );
|
|
||||||
|
|
||||||
transfer( genesis_account(db), shorter1, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), shorter2, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), buyer1, asset( 10000 ) );
|
|
||||||
transfer( genesis_account(db), buyer2, asset( 10000 ) );
|
|
||||||
|
|
||||||
BOOST_REQUIRE( create_sell_order( buyer1, asset(1000), bitusd.amount(1000) ) );
|
|
||||||
BOOST_REQUIRE( !create_short( shorter1, bitusd.amount(1000), asset(1000) ) );
|
|
||||||
BOOST_REQUIRE_EQUAL( get_balance(buyer1, bitusd), 990 ); // 1000 - 1% fee
|
|
||||||
ilog( "=================================== START===================================\n\n");
|
|
||||||
|
|
||||||
// this should cause the highest bid to below the margin call threshold
|
|
||||||
// which means it should be filled by the cover
|
|
||||||
auto unmatched = create_short( buyer1, bitusd.amount(990), core.amount(1500) );
|
|
||||||
if( unmatched ) edump((*unmatched));
|
|
||||||
BOOST_REQUIRE( unmatched );
|
|
||||||
*/
|
|
||||||
|
|
||||||
} catch( const fc::exception& e) {
|
|
||||||
edump((e.to_detail_string()));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an order that cannot be filled immediately and have the
|
* Create an order that cannot be filled immediately and have the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue