bitshares基本概念详解【喂价】
什么是喂价
通俗说法:喂价就是一种资产与另一种资产的价格比率。
专业说法:可信的见证人将外盘交易汇率输入到区块链上,使得软件算法可以将这些信息并入到市场规则里,这些外盘汇率信息叫做“喂价”。
还是通俗说法比较靠谱,专业说法又要解释什么是外盘、内盘、见证人等。
喂价数据必须包括两种资产,和带资产精度的资产数量,如下:
"settlement_price": {
"base": {
"amount": 14569,
"asset_id": "1.3.113"
},
"quote": {
"amount": 85656,
"asset_id": "1.3.0"
}
}
谁来喂价
谁来喂价这个由资产属性来指定,可以是以下几种:
- 资产指定见证人喂价
- 资产指定理事会成员喂价
- 资产指定喂价人
以上1、2在资产数据的flags指定由有效见证人喂价、或者有效理事会成员喂价,定义如下:
enum asset_issuer_permission_flags
{
charge_market_fee = 0x01, /**< an issuer-specified percentage of all market trades in this asset is paid to the issuer */
white_list = 0x02, /**< accounts must be whitelisted in order to hold this asset */
override_authority = 0x04, /**< issuer may transfer asset back to himself */
transfer_restricted = 0x08, /**< require the issuer to be one party to every transfer */
disable_force_settle = 0x10, /**< disable force settling */
global_settle = 0x20, /**< allow the bitasset issuer to force a global settling -- this may be set in permissions, but not flags */
disable_confidential = 0x40, /**< allow the asset to be used with confidential transactions */
witness_fed_asset = 0x80, /**< allow the asset to be fed by witnesses */
committee_fed_asset = 0x100 /**< allow the asset to be fed by the committee */
};
如“CNY”的flags = 129 = 0x81 = witness_fed_asset | charge_market_fee
资产指定喂价人可以通过cli_wallet的如下命令指定:
signed_transaction update_asset_feed_producers(string symbol, flat_set<string> new_feed_producers, bool broadcast)
怎么喂价
cli_wallet
喂价命令格式:
publish_asset_feed nathan USD {"settlement_price": {"base": {"amount": 25,"asset_id": "1.3.1"},"quote": {"amount": 63647,"asset_id": "1.3.0"}},"maintenance_collateral_ratio": 1750,"maximum_short_squeeze_ratio":1100,"core_exchange_rate": {"base": {"amount": 25,"asset_id": "1.3.1"},"quote": {"amount": 66829,"asset_id": "1.3.0"}}} true
喂价信息包括资产对数量、最小抵押比率、强制平仓比率、核心兑换率。
抵押比率等可参考bitshares研究系列【喂价和资产抵押率】
wallet.cpp
发送 asset_publish_feed_operation 到节点
struct asset_publish_feed_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
asset fee; ///< paid for by publisher
account_id_type publisher;
asset_id_type asset_id; ///< asset for which the feed is published
price_feed feed;
extensions_type extensions;
account_id_type fee_payer()const { return publisher; }
void validate()const;
};
数据里有喂价发布人、资产id、喂价信息
喂价有效时间
资产options字段中会指定喂价有效时间、最小喂价人个数等信息:
"options": {
"feed_lifetime_sec": 86400,
"minimum_feeds": 7,
"force_settlement_delay_sec": 86400,
"force_settlement_offset_percent": 500,
"maximum_force_settlement_volume": 50,
"short_backing_asset": "1.3.0",
"extensions": []
}
feed_lifetime_sec指定了喂价有效时间,超过这个时间此喂价人的喂价数据就会失效。
minimum_feeds指定了有效喂价人的个数。
当前喂价
资产喂价有多人指定,那么谁的喂价是有效的呢?
系统采用所有喂价的中间值,因此如果某些见证人没有相当大程度上的勾结串通,想试图操纵喂价是非常困难的。喂价和其他受托人行为都是公开可审计的,而且受托人在任何时候都可以被BTS持有者投票撤掉。投票可参见bitshares基本概念详解【见证人】
asset_object.cpp
void graphene::chain::asset_bitasset_data_object::update_median_feeds(time_point_sec current_time)
{
current_feed_publication_time = current_time;
vector<std::reference_wrapper<const price_feed>> current_feeds;
for( const pair<account_id_type, pair<time_point_sec,price_feed>>& f : feeds )
{
if( (current_time - f.second.first).to_seconds() < options.feed_lifetime_sec &&
f.second.first != time_point_sec() )
{
current_feeds.emplace_back(f.second.second);
current_feed_publication_time = std::min(current_feed_publication_time, f.second.first);
}
}
// If there are no valid feeds, or the number available is less than the minimum to calculate a median...
if( current_feeds.size() < options.minimum_feeds )
{
//... don't calculate a median, and set a null feed
current_feed_publication_time = current_time;
current_feed = price_feed();
return;
}
if( current_feeds.size() == 1 )
{
current_feed = std::move(current_feeds.front());
return;
}
// *** Begin Median Calculations ***
price_feed median_feed;
const auto median_itr = current_feeds.begin() + current_feeds.size() / 2;
#define CALCULATE_MEDIAN_VALUE(r, data, field_name) \
std::nth_element( current_feeds.begin(), median_itr, current_feeds.end(), \
[](const price_feed& a, const price_feed& b) { \
return a.field_name < b.field_name; \
}); \
median_feed.field_name = median_itr->get().field_name;
BOOST_PP_SEQ_FOR_EACH( CALCULATE_MEDIAN_VALUE, ~, GRAPHENE_PRICE_FEED_FIELDS )
#undef CALCULATE_MEDIAN_VALUE
// *** End Median Calculations ***
current_feed = median_feed;
}
此函数会判断喂价人个数,如果有效喂价人个数不够,当前喂价为null,实际上这种情况可能会导致程序一些接口出错。
nth_element函数仅排序第n个元素(从0开始索引),即将位置n(从0开始)的元素放在第n大的位置,处理完之后,默认排在它前面的元素都不比它大,排在它后面的元素都不比它小。
BOOST_PP_SEQ_FOR_EACH宏,用于将一个序列中参数依次按照指定宏进行展开。
再看看GRAPHENE_PRICE_FEED_FIELDS宏定义:
#define GRAPHENE_PRICE_FEED_FIELDS (settlement_price)(maintenance_collateral_ratio)(maximum_short_squeeze_ratio) \
(maintenance_collateral_cash_ratio)(maximum_short_squeeze_cash_ratio)\
(core_exchange_rate)
使用BOOST_PP_SEQ_FOR_EACH会展开为6个CALCULATE_MEDIAN_VALUE语句。
如果喂价人为8个,也就是current_feeds.size() = 8,用update_median_feeds函数会算出这8人喂价中排在第4位的settlement_price、maintenance_collateral_ratio、maximum_short_squeeze_ratio、maintenance_collateral_cash_ratio、maximum_short_squeeze_cash_ratio、core_exchange_rate。
注意这里计算的是每项数据的中间值
感谢您阅读 @chaimyu 的帖子,期待您能留言交流!
你这一系列BTS的文章总结的真好,学习了
谢谢,没时间写
好专业。
崇拜你
互相学习吧
u 喜欢你的分析帖
继续让你喜欢😘
你好请接受cn区点赞机器人 @cnbuddy 对你作为cn区一员的感谢。如果不想再收到我的留言,请回复“取消”。
你超~強!石墨烯專家!期待你對EOS的剖析。
学习中...eos是应该看看,你币很厉害啊
同期待分析 EOS !
略懂而已,沒深入研究。介紹數位貨幣的文章是轉發的,我只是加上一點評論。現在EOS要延遲上線了……
以后跟楼主学习了,新人请多指教!!