25 #include <boost/rational.hpp> 26 #include <boost/multiprecision/cpp_int.hpp> 31 namespace graphene {
namespace protocol {
42 return amult == bmult;
74 FC_THROW_EXCEPTION( fc::assert_exception,
"invalid asset * price", (
"asset",a)(
"price",b) );
79 const asset& a = *
this;
97 "invalid asset::multiply_and_round_up(price)", (
"asset",a)(
"price",b) );
103 return price{base,quote};
116 FC_ASSERT( r.numerator() > 0 && r.denominator() > 0 );
118 if( r.numerator() == r.denominator() )
return p;
121 boost::rational<uint128_t> r128( r.numerator(), r.denominator() );
122 auto cp = p128 * r128;
125 bool shrinked =
false;
126 bool using_max =
false;
128 while( cp.numerator() > max || cp.denominator() > max )
130 if( 1 == cp.numerator() )
132 cp = boost::rational<uint128_t>( 1, max );
136 else if( 1 == cp.denominator() )
138 cp = boost::rational<uint128_t>( max, 1 );
144 cp = boost::rational<uint128_t>( cp.numerator() >> 1, cp.denominator() >> 1 );
150 uint128_t num = ocp.numerator();
151 uint128_t den = ocp.denominator();
152 FC_ASSERT( num > 0 && den > 0,
"Internal error" );
156 num = std::min( num, max );
162 den = std::min( den, max );
165 boost::rational<uint128_t> ncp( num, den );
166 if( num == max || den == max )
172 auto diff1 = (ncp >= ocp) ? (ncp - ocp) : (ocp - ncp);
173 auto diff2 = (cp >= ocp) ? (cp - ocp) : (ocp - cp);
174 if( diff1 < diff2 ) cp = ncp;
181 if( shrinked || using_max )
183 bool flipped = ( r.numerator() > r.denominator() ) ? ( np < p ) : ( np > p );
195 return p *
ratio_type( r.denominator(), r.numerator() );
220 auto cp = swan * ratio;
223 cp = boost::rational<uint128_t>( (cp.numerator() >> 1)+1, (cp.denominator() >> 1)+1 );
225 return (
asset( static_cast<int64_t>(cp.denominator()), collateral.
asset_id )
226 /
asset( static_cast<int64_t>(cp.numerator()), debt.
asset_id ) );
232 return ( base.asset_id == asset_id_type() && quote.asset_id == asset_id_type() );
237 FC_ASSERT( base.amount.value > 0,
"Base amount should be positive" );
238 FC_ASSERT( quote.amount.value > 0,
"Quote amount should be positive" );
239 FC_ASSERT( base.asset_id != quote.asset_id,
"Base asset ID and quote asset ID should be different" );
240 if( check_upper_bound )
243 "Base amount should not be greater than ${max}",
246 "Quote amount should not be greater than ${max}",
253 if( !settlement_price.is_null() )
254 settlement_price.validate();
270 if( !settlement_price.is_null() )
271 return (settlement_price.base.asset_id == asset_id);
272 if( !core_exchange_rate.is_null() )
273 return (core_exchange_rate.base.asset_id == asset_id);
285 boost::rational<uint128_t> sp( settlement_price.base.amount.value, settlement_price.quote.amount.value );
287 auto cp = sp * ratio;
290 cp = boost::rational<uint128_t>( (cp.numerator() >> 1)+(cp.numerator()&1U),
291 (cp.denominator() >> 1)+(cp.denominator()&1U) );
293 return (
asset( static_cast<int64_t>(cp.numerator()), settlement_price.base.asset_id )
294 /
asset( static_cast<int64_t>(cp.denominator()), settlement_price.quote.asset_id ) );
310 return settlement_price / margin_call_order_ratio( maybe_mcfr );
316 const uint16_t mcfr = maybe_mcfr.
valid() ? *maybe_mcfr : 0;
317 uint16_t numerator = (mcfr < maximum_short_squeeze_ratio) ?
328 auto numerator = get_margin_call_price_numerator( maybe_mcfr );
336 auto numerator = get_margin_call_price_numerator( maybe_mcfr );
337 return ratio_type( numerator, maximum_short_squeeze_ratio );
344 if( settlement_price.is_null() )
354 static constexpr int64_t v = 10 *
p10<N-1>::v;
360 static constexpr int64_t v = 1;
366 static constexpr std::array<int64_t, 19> scaled_precision_lut =
375 return scaled_precision_lut[ precision ];
#define GRAPHENE_COLLATERAL_RATIO_DENOM
asset operator*(const asset &a, const price &b)
Multiply and round down.
boost::rational< int32_t > ratio_type
ratio_type margin_call_pays_ratio(const fc::optional< uint16_t > &margin_call_fee_ratio) const
price max_short_squeeze_price_before_hf_1270() const
ratio_type margin_call_order_ratio(const fc::optional< uint16_t > &margin_call_fee_ratio) const
price operator/(const asset &base, const asset "e)
bool operator<(const price &a, const price &b)
asset multiply_and_round_up(const price &p) const
Multiply and round up.
static share_type scaled_precision(uint8_t precision)
#define GRAPHENE_MAX_COLLATERAL_RATIO
higher than this is unnecessary and may exceed int16 storage
price margin_call_order_price(const fc::optional< uint16_t > &margin_call_fee_ratio) const
The price struct stores asset prices in the BitShares system.
#define FC_CAPTURE_AND_RETHROW(...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
asset(share_type a=0, asset_id_type id=asset_id_type())
#define GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION(type)
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
price maintenance_collateralization() const
#define GRAPHENE_MIN_COLLATERAL_RATIO
lower than this could result in divide by 0
defines market parameters for margin positions
safe< int64_t > share_type
void validate(bool check_upper_bound=false) const
Check if the object is valid.
constexpr int64_t GRAPHENE_MAX_SHARE_SUPPLY(1000000000000000LL)
price max_short_squeeze_price() const
static price call_price(const asset &debt, const asset &collateral, uint16_t collateral_ratio)
bool is_for(asset_id_type asset_id) const
bool operator==(const price &a, const price &b)