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