Merge commit 'ee3f81fa31e39a8ae4ebcfe5b3d78f2dbc103e1b' into betting

This commit is contained in:
Eric Frias 2017-06-20 17:44:12 -04:00
commit 50fef80189
4 changed files with 285 additions and 128 deletions

View file

@ -31,6 +31,8 @@
#include <fc/crypto/hex.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <cctype>
@ -1090,56 +1092,37 @@ market_ticker database_api_impl::get_ticker( const string& base, const string& q
try {
if( base_id > quote_id ) std::swap(base_id, quote_id);
const auto& bidx = _db.get_index_type<bucket_index>();
const auto& by_key_idx = bidx.indices().get<by_key>();
uint32_t bucket_size = 86400;
uint32_t day = 86400;
auto now = fc::time_point_sec( fc::time_point::now() );
auto itr = by_key_idx.lower_bound( bucket_key( base_id, quote_id, bucket_size,
now - bucket_size ) );
auto orders = get_order_book( base, quote, 1 );
auto trades = get_trade_history( base, quote, now, fc::time_point_sec( now.sec_since_epoch() - day ), 100 );
if( itr != by_key_idx.end() && itr->key.base == base_id && itr->key.quote == quote_id && itr->key.seconds == bucket_size )
{
auto trades = get_trade_history( base, quote, now, fc::time_point_sec( now.sec_since_epoch() - bucket_size ), 100 );
if (assets[0]->id == base_id)
{
result.latest = trades[0].price;
result.percent_change = ( result.latest / ( price_to_real( itr->open_quote, assets[1]->precision ) / price_to_real( itr->open_base, assets[0]->precision ) ) - 1 ) * 100;
//result.lowest_ask = price_to_real( itr->low_quote, assets[1]->precision ) / price_to_real( itr->low_base, assets[0]->precision );
//result.highest_bid = price_to_real( itr->high_quote, assets[1]->precision ) / price_to_real( itr->high_base, assets[0]->precision );
result.lowest_ask = orders.asks[0].first;
result.highest_bid = orders.bids[0].first;
}
else
{
result.latest = trades[0].price;
result.percent_change = ( result.latest / ( price_to_real( itr->open_base, assets[1]->precision ) / price_to_real( itr->open_quote, assets[0]->precision ) ) - 1) * 100;
//result.lowest_ask = price_to_real( itr->low_base, assets[1]->precision ) / price_to_real( itr->low_quote, assets[0]->precision );
//result.highest_bid = price_to_real( itr->high_base, assets[1]->precision ) / price_to_real( itr->high_quote, assets[0]->precision );
result.lowest_ask = orders.bids[0].first;
result.highest_bid = orders.asks[0].first;
}
for ( market_trade t: trades )
{
result.base_volume += t.amount;
result.quote_volume += t.value;
result.base_volume += t.value;
result.quote_volume += t.amount;
}
while (trades.size() == 100)
{
trades = get_trade_history( base, quote, trades[99].date, fc::time_point_sec( now.sec_since_epoch() - day ), 100 );
for ( market_trade t: trades )
{
result.base_volume += t.amount;
result.quote_volume += t.value;
result.base_volume += t.value;
result.quote_volume += t.amount;
}
}
trades = get_trade_history( base, quote, trades[99].date, fc::time_point_sec( now.sec_since_epoch() - bucket_size ), 100 );
}
trades = get_trade_history( base, quote, trades.back().date, fc::time_point_sec(), 1 );
result.percent_change = trades.size() > 0 ? ( ( result.latest / trades.back().price ) - 1 ) * 100 : 0;
//if (assets[0]->id == base_id)
{
result.lowest_ask = orders.asks[0].price;
result.highest_bid = orders.bids[0].price;
}
return result;
@ -1176,19 +1159,19 @@ market_volume database_api_impl::get_24_volume( const string& base, const string
for ( market_trade t: trades )
{
result.base_volume += t.amount;
result.quote_volume += t.value;
result.base_volume += t.value;
result.quote_volume += t.amount;
}
while (trades.size() == 100)
{
trades = get_trade_history( base, quote, trades[99].date, fc::time_point_sec( now.sec_since_epoch() - bucket_size ), 100 );
for ( market_trade t: trades )
{
result.base_volume += t.amount;
result.quote_volume += t.value;
result.base_volume += t.value;
result.quote_volume += t.amount;
}
trades = get_trade_history( base, quote, trades[99].date, fc::time_point_sec( now.sec_since_epoch() - bucket_size ), 100 );
}
return result;
@ -1202,6 +1185,7 @@ order_book database_api::get_order_book( const string& base, const string& quote
order_book database_api_impl::get_order_book( const string& base, const string& quote, unsigned limit )const
{
using boost::multiprecision::uint128_t;
FC_ASSERT( limit <= 50 );
order_book result;
@ -1221,21 +1205,28 @@ order_book database_api_impl::get_order_book( const string& base, const string&
auto price_to_real = [&]( const price& p )
{
if( p.base.asset_id == base_id )
return asset_to_real( p.quote, assets[1]->precision ) / asset_to_real( p.base, assets[0]->precision );
return asset_to_real( p.base, assets[0]->precision ) / asset_to_real( p.quote, assets[1]->precision );
else
return asset_to_real( p.base, assets[1]->precision ) / asset_to_real( p.quote, assets[0]->precision );
return asset_to_real( p.quote, assets[0]->precision ) / asset_to_real( p.base, assets[1]->precision );
};
for( const auto& o : orders ) {
for( const auto& o : orders )
{
if( o.sell_price.base.asset_id == base_id )
{
result.asks.push_back( std::make_pair( price_to_real(o.sell_price),
asset_to_real(o.sell_price.base, assets[0]->precision)) );
order ord;
ord.price = price_to_real( o.sell_price );
ord.quote = asset_to_real( share_type( ( uint128_t( o.for_sale.value ) * o.sell_price.quote.amount.value ) / o.sell_price.base.amount.value ), assets[1]->precision );
ord.base = asset_to_real( o.for_sale, assets[0]->precision );
result.bids.push_back( ord );
}
else
{
result.bids.push_back( std::make_pair( price_to_real(o.sell_price),
asset_to_real(o.sell_price.quote, assets[0]->precision ) ) );
order ord;
ord.price = price_to_real( o.sell_price );
ord.quote = asset_to_real( o.for_sale, assets[1]->precision );
ord.base = asset_to_real( share_type( ( uint64_t( o.for_sale.value ) * o.sell_price.quote.amount.value ) / o.sell_price.base.amount.value ), assets[0]->precision );
result.asks.push_back( ord );
}
}
@ -1290,13 +1281,13 @@ vector<market_trade> database_api_impl::get_trade_history( const string& base,
if( assets[0]->id == itr->op.receives.asset_id )
{
trade.amount = price_to_real( itr->op.receives.amount, assets[0]->precision );
trade.value = price_to_real( itr->op.pays.amount, assets[1]->precision );
trade.amount = price_to_real( itr->op.pays.amount, assets[1]->precision );
trade.value = price_to_real( itr->op.receives.amount, assets[0]->precision );
}
else
{
trade.amount = price_to_real( itr->op.pays.amount, assets[0]->precision );
trade.value = price_to_real( itr->op.receives.amount, assets[1]->precision );
trade.amount = price_to_real( itr->op.receives.amount, assets[1]->precision );
trade.value = price_to_real( itr->op.pays.amount, assets[0]->precision );
}
trade.date = itr->time;

View file

@ -69,12 +69,19 @@ using namespace std;
class database_api_impl;
struct order
{
double price;
double quote;
double base;
};
struct order_book
{
string base;
string quote;
vector< pair<double,double> > bids;
vector< pair<double,double> > asks;
vector< order > bids;
vector< order > asks;
};
struct market_ticker
@ -587,6 +594,8 @@ class database_api
};
} }
FC_REFLECT( graphene::app::order, (price)(quote)(base) );
FC_REFLECT( graphene::app::order_book, (base)(quote)(bids)(asks) );
FC_REFLECT( graphene::app::market_ticker, (base)(quote)(latest)(lowest_ask)(highest_bid)(percent_change)(base_volume)(quote_volume) );
FC_REFLECT( graphene::app::market_volume, (base)(quote)(base_volume)(quote_volume) );

View file

@ -852,6 +852,51 @@ class wallet_api
bool fill_or_kill = false,
bool broadcast = false);
/** Place a limit order attempting to sell one asset for another.
*
* This API call abstracts away some of the details of the sell_asset call to be more
* user friendly. All orders placed with sell never timeout and will not be killed if they
* cannot be filled immediately. If you wish for one of these parameters to be different,
* then sell_asset should be used instead.
*
* @param seller_account the account providing the asset being sold, and which will
* receive the processed of the sale.
* @param base The name or id of the asset to sell.
* @param quote The name or id of the asset to recieve.
* @param rate The rate in base:quote at which you want to sell.
* @param amount The amount of base you want to sell.
* @param broadcast true to broadcast the transaction on the network.
* @returns The signed transaction selling the funds.
*/
signed_transaction sell( string seller_account,
string base,
string quote,
double rate,
double amount,
bool broadcast );
/** Place a limit order attempting to buy one asset with another.
*
* This API call abstracts away some of the details of the sell_asset call to be more
* user friendly. All orders placed with buy never timeout and will not be killed if they
* cannot be filled immediately. If you wish for one of these parameters to be different,
* then sell_asset should be used instead.
*
* @param buyer_account The account buying the asset for another asset.
* @param base The name or id of the asset to buy.
* @param quote The name or id of the assest being offered as payment.
* @param rate The rate in base:quote at which you want to buy.
* @param amount the amount of base you want to buy.
* @param broadcast true to broadcast the transaction on the network.
* @param The signed transaction selling the funds.
*/
signed_transaction buy( string buyer_account,
string base,
string quote,
double rate,
double amount,
bool broadcast );
/** Borrow an asset or update the debt/collateral ratio for the loan.
*
* This is the first step in shorting an asset. Call \c sell_asset() to complete the short.
@ -1404,6 +1449,8 @@ class wallet_api
bool broadcast /* = false */
);
order_book get_order_book( const string& base, const string& quote, unsigned limit = 50);
vector<sport_object> list_sports() const;
vector<event_group_object> list_event_groups(sport_id_type sport_id) const;
vector<betting_market_group_object> list_betting_market_groups(event_id_type event_id) const;
@ -1584,6 +1631,8 @@ FC_API( graphene::wallet::wallet_api,
(upgrade_account)
(create_account_with_brain_key)
(sell_asset)
(sell)
(buy)
(borrow_asset)
(cancel_order)
(transfer)
@ -1669,4 +1718,5 @@ FC_API( graphene::wallet::wallet_api,
(propose_create_betting_market)
(place_bet)
(propose_resolve_betting_market)
(get_order_book)
)

View file

@ -2166,6 +2166,90 @@ public:
}
return ss.str();
};
m["get_order_book"] = [this](variant result, const fc::variants& a)
{
auto orders = result.as<order_book>();
auto bids = orders.bids;
auto asks = orders.asks;
std::stringstream ss;
std::stringstream sum_stream;
sum_stream << "Sum(" << orders.base << ')';
double bid_sum = 0;
double ask_sum = 0;
const int spacing = 20;
auto prettify_num = [&]( double n )
{
//ss << n;
if (abs( round( n ) - n ) < 0.00000000001 )
{
//ss << setiosflags( !ios::fixed ) << (int) n; // doesn't compile on Linux with gcc
ss << (int) n;
}
else if (n - floor(n) < 0.000001)
{
ss << setiosflags( ios::fixed ) << setprecision(10) << n;
}
else
{
ss << setiosflags( ios::fixed ) << setprecision(6) << n;
}
};
ss << setprecision( 8 ) << setiosflags( ios::fixed ) << setiosflags( ios::left );
ss << ' ' << setw( (spacing * 4) + 6 ) << "BUY ORDERS" << "SELL ORDERS\n"
<< ' ' << setw( spacing + 1 ) << "Price" << setw( spacing ) << orders.quote << ' ' << setw( spacing )
<< orders.base << ' ' << setw( spacing ) << sum_stream.str()
<< " " << setw( spacing + 1 ) << "Price" << setw( spacing ) << orders.quote << ' ' << setw( spacing )
<< orders.base << ' ' << setw( spacing ) << sum_stream.str()
<< "\n====================================================================================="
<< "|=====================================================================================\n";
for (int i = 0; i < bids.size() || i < asks.size() ; i++)
{
if ( i < bids.size() )
{
bid_sum += bids[i].base;
ss << ' ' << setw( spacing );
prettify_num( bids[i].price );
ss << ' ' << setw( spacing );
prettify_num( bids[i].quote );
ss << ' ' << setw( spacing );
prettify_num( bids[i].base );
ss << ' ' << setw( spacing );
prettify_num( bid_sum );
ss << ' ';
}
else
{
ss << setw( (spacing * 4) + 5 ) << ' ';
}
ss << '|';
if ( i < asks.size() )
{
ask_sum += asks[i].base;
ss << ' ' << setw( spacing );
prettify_num( asks[i].price );
ss << ' ' << setw( spacing );
prettify_num( asks[i].quote );
ss << ' ' << setw( spacing );
prettify_num( asks[i].base );
ss << ' ' << setw( spacing );
prettify_num( ask_sum );
}
ss << '\n';
}
ss << endl
<< "Buy Total: " << bid_sum << ' ' << orders.base << endl
<< "Sell Total: " << ask_sum << ' ' << orders.base << endl;
return ss.str();
};
return m;
}
@ -3552,6 +3636,28 @@ signed_transaction wallet_api::sell_asset(string seller_account,
symbol_to_receive, expiration, fill_or_kill, broadcast);
}
signed_transaction wallet_api::sell( string seller_account,
string base,
string quote,
double rate,
double amount,
bool broadcast )
{
return my->sell_asset( seller_account, std::to_string( amount ), base,
std::to_string( rate * amount ), quote, 0, false, broadcast );
}
signed_transaction wallet_api::buy( string buyer_account,
string base,
string quote,
double rate,
double amount,
bool broadcast )
{
return my->sell_asset( buyer_account, std::to_string( rate * amount ), quote,
std::to_string( amount ), base, 0, false, broadcast );
}
signed_transaction wallet_api::borrow_asset(string seller_name, string amount_to_sell,
string asset_symbol, string amount_of_collateral, bool broadcast)
{
@ -4355,11 +4461,12 @@ signed_transaction wallet_api::propose_resolve_betting_market(
return my->sign_transaction(tx, broadcast);
}
// default ctor necessary for FC_REFLECT
signed_block_with_info::signed_block_with_info()
order_book wallet_api::get_order_book( const string& base, const string& quote, unsigned limit )
{
return( my->_remote_db->get_order_book( base, quote, limit ) );
}
// default ctor necessary for FC_REFLECT
signed_block_with_info::signed_block_with_info( const signed_block& block )
: signed_block( block )
{