запрос свечи mongodb

Мне нужно запросить финансовые данные из монго и создать ежедневный график Candle Stick.

схема коллекции выглядит примерно так:

{
  symbol: 'GOOG',
  amount: 1000,
  rate: 123,
  created_at: ISODate('some point in time')
}

Каждая запись на графике (т.е. за данный день) должна состоять из 4 значений:

  1. высокий (максимум (скорость))
  2. низкий (мин(скорость))
  3. открытый (первая ставка в данный день)
  4. закрыть (последняя ставка в данный день)

Любая идея, как построить запрос?


person shaharsol    schedule 18.07.2018    source источник


Ответы (2)


Хорошо, понял это после того, как @David Peleg прислал мне этого репозитория:

db.collection.aggregate([
      {$match:{
        symbol:'GOOG'
      }},
      {$project:{
        "day":{
          "y": {"$year":"$created_at"},
          "m": {"$month":"$created_at"},
          "d": {"$dayOfMonth": "$created_at"}
        },
        created_at: 1,
        rate: 1
      }},
      {"$sort":{"created_at":1}},
      {"$group":{
        "_id": "$day",
        "created_at": {"$first":"$created_at"},
        "open": {"$first":"$rate"},
        "close": {"$last":"$rate"},
        "high": {"$max":"$rate"},
        "low": {"$min":"$rate"},
      }},
      {$project:{
        "_id": "$_id",
        "rates":{
          "open": "$open",
          "close": "$close",
          "high": "$high",
          "low": "$low"
        }
      }},
      {"$sort":{"_id":1}}
    ])
person shaharsol    schedule 19.07.2018

Я работал над аналогичным запросом в проекте, который я разрабатываю, и рад видеть, что пришел к аналогичным выводам.

Мои входящие данные исходят от API Robinhood; он похож на ваш, но дает мне метки даты в строках, поэтому я добавил $toDate и $toString, чтобы перевернуть строку в объекты Date. Я могу преобразовать входящие метки даты в объект Time в Ruby, а затем удалить эту дополнительную работу здесь.

Я все еще уточняю свою группировку, так как не уверен, что мне действительно нужно два. Мой входящий поток иногда дублирует данные (в секунду из-за ситуации со строковой меткой даты), поэтому первая группа должна очистить это, чтобы не ложно раздувать { "$sum": "$volume" } во второй группе.

Мой проект $project возвращает мою 1-метровую свечу данных в пределах 59-секундного диапазона запрашиваемой предыдущей минуты. Ключи соответствуют истории API Robinhood, поэтому я могу рассматривать их как один и тот же объект в коде.

var date_now   = new Date(new ISODate("2019-10-21T20:00:00.000Z"))
var date_end   = new Date(date_now.getTime() - 1000 * 1)
var date_begin = new Date(date_now.getTime() - 1000 * 60 * 10)
db.quotes.aggregate([
{ "$addFields": { "date": { "$toDate": "$time_pulled" } } },
{ $match: { symbol: "NUGT",
            date: { "$gte": date_begin,
                    "$lt":  date_end } } },
{ $group: { _id: "$date", // group by date to eliminate dups
    "symbol": { "$first": "$symbol" },
    "price":  { "$max": "$last_trade_price" },
    "volume": { "$max": "$volume" } } },
{ $sort:  { _id: 1 } },    // sort by date to get correct first/last prices
{ $group: { _id: "$symbol",
    //"date_begin":  { "$first": { "$toString": "$_id" } },
    //"date_end":    { "$last": { "$toString": "$_id" } },
    "high_price":  { "$max": "$price" },
    "low_price":   { "$min": "$price" },
    "open_price":  { "$first": "$price" },
    "close_price": { "$last": "$price" },
    "volume":      { "$sum": "$volume" } } },
{ $project: { _id: 1,
    begins_at: { "$toString": date_begin },
    volume: 1,
    high_price: 1,
    low_price: 1,
    open_price: 1,
    close_price: 1 } }
])

Результат:

/* 1 */
{
    "_id" : "NUGT",
    "high_price" : "26.860000",
    "low_price" : "26.740000",
    "open_price" : "26.834200",
    "close_price" : "26.820000",
    "volume" : 392086.0,
    "begins_at" : "2019-10-21T19:50:00.000Z"
}
person danarchy85    schedule 22.10.2019