156    auto const& params(context.
params);
 
  159    if (!params.isMember(jss::oracles))
 
  161    if (!params[jss::oracles].isArray() || params[jss::oracles].size() == 0 ||
 
  162        params[jss::oracles].size() > maxOracles)
 
  168    if (!params.isMember(jss::base_asset))
 
  171    if (!params.isMember(jss::quote_asset))
 
  178        auto const& jv = params[field];
 
  180        return jv.isUInt() || (jv.isInt() && jv.asInt() >= 0) ||
 
  186    auto getField = [¶ms, &validUInt](
 
  192            if (!validUInt(params, field))
 
  194            return params[field].
asUInt();
 
  206            if (params[field].asString().empty())
 
  209            return params[field];
 
  217    auto const trim = getField(jss::trim);
 
  231    auto const timeThreshold = getField(jss::time_threshold, 0);
 
  238    auto const baseAsset = getCurrency(sfBaseAsset, jss::base_asset);
 
  244    auto const quoteAsset = getCurrency(sfQuoteAsset, jss::quote_asset);
 
  254    for (
auto const& oracle : params[jss::oracles])
 
  256        if (!oracle.isMember(jss::oracle_document_id) ||
 
  257            !oracle.isMember(jss::account))
 
  262        auto const documentID = validUInt(oracle, jss::oracle_document_id)
 
  266            parseBase58<AccountID>(oracle[jss::account].asString());
 
  267        if (!account || account->
isZero() || !documentID)
 
  278        auto const sle = ledger->read(
keylet::oracle(*account, *documentID));
 
  286                        return o.getFieldCurrency(sfBaseAsset).getText() ==
 
  287                            std::get<Json::Value>(baseAsset) &&
 
  288                            o.getFieldCurrency(sfQuoteAsset).getText() ==
 
  289                            std::get<Json::Value>(quoteAsset) &&
 
  290                            o.isFieldPresent(sfAssetPrice);
 
  292                iter != series.end())
 
  294                auto const price = iter->getFieldU64(sfAssetPrice);
 
  295                auto const scale = iter->isFieldPresent(sfScale)
 
  296                    ? -
static_cast<int>(iter->getFieldU8(sfScale))
 
  298                prices.insert(Prices::value_type(
 
  300                    STAmount{noIssue(), price, scale}));
 
  315    auto const latestTime = prices.left.
begin()->first;
 
  321        auto const oldestTime = prices.left.rbegin()->first;
 
  322        auto const upperBound =
 
  323            latestTime > threshold ? (latestTime - threshold) : oldestTime;
 
  324        if (upperBound > oldestTime)
 
  326                prices.left.upper_bound(upperBound), prices.left.end());
 
  339    result[jss::time] = latestTime;
 
  342    auto const [avg, sd, size] =
 
  343        getStats(prices.right.begin(), prices.right.end());
 
  344    result[jss::entire_set][jss::mean] = avg.getText();
 
  345    result[jss::entire_set][jss::size] = size;
 
  346    result[jss::entire_set][jss::standard_deviation] = 
to_string(sd);
 
  348    auto itAdvance = [&](
auto it, 
int distance) {
 
  353    auto const median = [&prices, &itAdvance, &size_ = size]() {
 
  354        auto const middle = size_ / 2;
 
  355        if ((size_ % 2) == 0)
 
  358            auto it = itAdvance(prices.right.begin(), middle - 1);
 
  359            auto const& a1 = it->first;
 
  360            auto const& a2 = (++it)->first;
 
  363        return itAdvance(prices.right.begin(), middle)->first;
 
  365    result[jss::median] = median.getText();
 
  369        auto const trimCount =
 
  372        auto const [avg, sd, size] = 
getStats(
 
  373            itAdvance(prices.right.begin(), trimCount),
 
  374            itAdvance(prices.right.end(), -trimCount));
 
  375        result[jss::trimmed_set][jss::mean] = avg.getText();
 
  376        result[jss::trimmed_set][jss::size] = size;
 
  377        result[jss::trimmed_set][jss::standard_deviation] = 
to_string(sd);
 
 
LedgerMaster & ledgerMaster