Skip to content

Commit

Permalink
steemit#1575: Implementation of as_decimal() and as_real() for price …
Browse files Browse the repository at this point in the history
…object, associated tests, modifications of get_order_book for SMT support
  • Loading branch information
sgerbino committed Sep 18, 2019
1 parent 6a22a40 commit 523f23e
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 28 deletions.
44 changes: 22 additions & 22 deletions libraries/plugins/apis/database_api/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1441,44 +1441,44 @@ DEFINE_API_IMPL( database_api_impl, find_limit_orders )


/* Order Book */

DEFINE_API_IMPL( database_api_impl, get_order_book )
{
FC_ASSERT( args.limit <= DATABASE_API_SINGLE_QUERY_LIMIT );
get_order_book_return result;

auto max_sell = price::max( SBD_SYMBOL, STEEM_SYMBOL );
auto max_buy = price::max( STEEM_SYMBOL, SBD_SYMBOL );
auto max_sell = price::max( std::get< 0 >( args.market ), std::get< 1 >( args.market ) );
auto max_buy = price::max( std::get< 1 >( args.market ), std::get< 0 >( args.market ) );

const auto& limit_price_idx = _db.get_index< chain::limit_order_index >().indices().get< chain::by_price >();
auto sell_itr = limit_price_idx.lower_bound( max_sell );
auto buy_itr = limit_price_idx.lower_bound( max_buy );
auto end = limit_price_idx.end();
auto sell_itr = limit_price_idx.lower_bound( max_sell );
auto buy_itr = limit_price_idx.lower_bound( max_buy );
auto end = limit_price_idx.end();

while( sell_itr != end && sell_itr->sell_price.base.symbol == SBD_SYMBOL && result.bids.size() < args.limit )
while ( sell_itr != end && sell_itr->sell_price.base.symbol == std::get< 0 >( args.market ) && result.bids.size() < args.limit )
{
auto itr = sell_itr;
order cur;
cur.order_price = itr->sell_price;
cur.real_price = 0.0;
// cur.real_price = (cur.order_price).to_real();
cur.sbd = itr->for_sale;
cur.steem = ( asset( itr->for_sale, SBD_SYMBOL ) * cur.order_price ).amount;
cur.created = itr->created;
result.bids.push_back( cur );
cur.order_price = itr->sell_price;
cur.decimal_price = itr->sell_price.as_decimal();
cur.real_price = itr->sell_price.as_real();
cur.for_sale = itr->amount_for_sale();
cur.to_receive = itr->amount_to_receive();
cur.created = itr->created;
result.bids.push_back( std::move( cur ) );
++sell_itr;
}
while( buy_itr != end && buy_itr->sell_price.base.symbol == STEEM_SYMBOL && result.asks.size() < args.limit )

while ( buy_itr != end && buy_itr->sell_price.base.symbol == std::get< 1 >( args.market ) && result.asks.size() < args.limit )
{
auto itr = buy_itr;
order cur;
cur.order_price = itr->sell_price;
cur.real_price = 0.0;
// cur.real_price = (~cur.order_price).to_real();
cur.steem = itr->for_sale;
cur.sbd = ( asset( itr->for_sale, STEEM_SYMBOL ) * cur.order_price ).amount;
cur.created = itr->created;
result.asks.push_back( cur );
cur.order_price = itr->sell_price;
cur.decimal_price = itr->sell_price.as_decimal();
cur.real_price = itr->sell_price.as_real();
cur.for_sale = itr->amount_for_sale();
cur.to_receive = itr->amount_to_receive();
cur.created = itr->created;
result.asks.push_back( std::move( cur ) );
++buy_itr;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,8 @@ typedef list_limit_orders_return find_limit_orders_return;

struct get_order_book_args
{
uint32_t limit;
uint32_t limit;
std::pair< asset_symbol_type, asset_symbol_type > market;
};

typedef order_book get_order_book_return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,9 +614,10 @@ struct api_proposal_vote_object
struct order
{
price order_price;
double real_price; // dollars per steem
share_type steem;
share_type sbd;
std::string decimal_price;
double real_price;
asset for_sale;
asset to_receive;
fc::time_point_sec created;
};

Expand Down Expand Up @@ -777,6 +778,6 @@ FC_REFLECT( steem::plugins::database_api::api_proposal_vote_object,
(proposal)
)

FC_REFLECT( steem::plugins::database_api::order, (order_price)(real_price)(steem)(sbd)(created) );
FC_REFLECT( steem::plugins::database_api::order, (order_price)(decimal_price)(real_price)(for_sale)(to_receive)(created) );

FC_REFLECT( steem::plugins::database_api::order_book, (asks)(bids) );
72 changes: 71 additions & 1 deletion libraries/protocol/asset.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <steem/protocol/asset.hpp>

#include <steem/protocol/validation.hpp>
#include <fc/io/json.hpp>

#include <boost/rational.hpp>
Expand Down Expand Up @@ -371,6 +371,76 @@ DEFINE_PRICE_COMPARISON_OPERATOR( >= )
FC_ASSERT( base.symbol != quote.symbol );
} FC_CAPTURE_AND_RETHROW( (base)(quote) ) }

std::string price::as_decimal() const
{ try {
std::string decimal_price;

static const auto tick_to_decimal = []( const int64_t base, const int64_t quote ) -> std::string
{
std::string decimal_str = boost::lexical_cast< std::string >( base );

int64_t num_zeros = 0;
for ( auto a = quote; a > 9; )
{
a /= 10;
num_zeros++;
}

int64_t num_digits = 0;
for ( auto d = base; d > 0; )
{
d /= 10;
num_digits++;
}

auto pos = num_digits - num_zeros;
if ( pos < 0 )
{
std::string prepend = "0.";
for ( ; pos < 0; pos++ )
{
prepend += "0";
}
decimal_str = prepend + decimal_str;
}
else
{
decimal_str.insert( pos, "." );
}

return decimal_str;
};

if ( is_tick_pricing( *this ) )
{
decimal_price = tick_to_decimal( base.amount.value, quote.amount.value );
}
else if ( is_tick_pricing( ~*this ) )
{
decimal_price = tick_to_decimal( quote.amount.value, base.amount.value );
}
else
{
double approx_real_price;
if ( ( base.symbol == SBD_SYMBOL && quote.symbol == STEEM_SYMBOL ) || ( base.symbol == STEEM_SYMBOL && quote.symbol.space() == asset_symbol_type::smt_nai_space ) )
approx_real_price = static_cast< double >( base.amount.value ) / static_cast< double >( quote.amount.value );
else
approx_real_price = static_cast< double >( quote.amount.value ) / static_cast< double >( base.amount.value );
decimal_price = boost::lexical_cast< std::string >( approx_real_price );
decimal_price += "?";
}

return decimal_price;
} FC_CAPTURE_AND_RETHROW( (base)(quote) ) }

double price::as_real() const
{ try {
auto decimal_price = as_decimal();
if ( decimal_price.back() == '?' )
decimal_price.pop_back();
return boost::lexical_cast< double >( decimal_price );
} FC_CAPTURE_AND_RETHROW( (base)(quote) ) }


} } // steem::protocol

Expand Down
3 changes: 3 additions & 0 deletions libraries/protocol/include/steem/protocol/asset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ namespace steem { namespace protocol {
price max()const { return price::max( base.symbol, quote.symbol ); }
price min()const { return price::min( base.symbol, quote.symbol ); }

std::string as_decimal()const;
double as_real()const;

bool is_null()const;
void validate()const;

Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ add_boost_test( chain_test
smt_tests/smt_create_apply
smt_tests/tick_pricing_rules_validation
smt_tests/tick_pricing_rules
smt_tests/price_as_decimal_and_real
undo_tests/undo_basic
undo_tests/undo_object_disapear
undo_tests/undo_key_collision
Expand Down
72 changes: 72 additions & 0 deletions tests/tests/smt_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,78 @@ BOOST_AUTO_TEST_CASE( tick_pricing_rules )
BOOST_REQUIRE( db->get_balance( "bob", SBD_SYMBOL ) == asset( 1000000 + 1000000, SBD_SYMBOL ) );
}

BOOST_AUTO_TEST_CASE( price_as_decimal_and_real )
{
BOOST_TEST_MESSAGE( "Testing: price_as_decimal_and_real" );

const auto symbol = get_new_smt_symbol( 3, this->db );

const auto float_cmp = []( double a, double b, double epsilon = 0.00005f ) -> bool
{
return ( std::fabs( a - b ) < epsilon );
};

price p;
p.base = asset( 123456, SBD_SYMBOL );
p.quote = asset( 1000, STEEM_SYMBOL );

BOOST_TEST_MESSAGE( " -- Testing SBD:STEEM pairing with Tick Pricing Rules" );

BOOST_REQUIRE( p.as_decimal() == "123.456" );
BOOST_REQUIRE( float_cmp( p.as_real(), 123.456f ) );

BOOST_TEST_MESSAGE( " -- Testing SBD:STEEM inverse pairing with Tick Pricing Rules" );

p = ~p;

BOOST_REQUIRE( p.as_decimal() == "123.456" );
BOOST_REQUIRE( float_cmp( p.as_real(), 123.456f ) );

BOOST_TEST_MESSAGE( " -- Testing STEEM:SMT pairing with Tick Pricing Rules" );

p.base = asset( 123, STEEM_SYMBOL );
p.quote = asset( 10000, symbol );

BOOST_REQUIRE( p.as_decimal() == "0.0123" );
BOOST_REQUIRE( float_cmp( p.as_real(), 0.0123f ) );

BOOST_TEST_MESSAGE( " -- Testing STEEM:SMT inverse pairing with Tick Pricing Rules" );

p = ~p;

BOOST_REQUIRE( p.as_decimal() == "0.0123" );
BOOST_REQUIRE( float_cmp( p.as_real(), 0.0123f ) );

BOOST_TEST_MESSAGE( " -- Testing STEEM:SMT pairing without Tick Pricing Rules" );

p.base = asset( 123, STEEM_SYMBOL );
p.quote = asset( 10001, symbol );

BOOST_REQUIRE( p.as_decimal() == "0.0122987701229877?" );
BOOST_REQUIRE( float_cmp( p.as_real(), 0.0122987701229877f ) );

BOOST_TEST_MESSAGE( " -- Testing STEEM:SMT inverse pairing without Tick Pricing Rules" );

p = ~p;

BOOST_REQUIRE( p.as_decimal() == "0.0122987701229877?" );
BOOST_REQUIRE( float_cmp( p.as_real(), 0.0122987701229877f ) );

BOOST_TEST_MESSAGE( " -- Testing SBD:STEEM pairing without Tick Pricing Rules" );

p.base = asset( 123, SBD_SYMBOL );
p.quote = asset( 10001, STEEM_SYMBOL );

BOOST_REQUIRE( p.as_decimal() == "0.0122987701229877?" );
BOOST_REQUIRE( float_cmp( p.as_real(), 0.0122987701229877f ) );

BOOST_TEST_MESSAGE( " -- Testing SBD:STEEM inverse pairing without Tick Pricing Rules" );

p = ~p;

BOOST_REQUIRE( p.as_decimal() == "0.0122987701229877?" );
BOOST_REQUIRE( float_cmp( p.as_real(), 0.0122987701229877f ) );
}
/*
* SMT legacy tests
*
Expand Down

0 comments on commit 523f23e

Please sign in to comment.